Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 831d5d6..623af34 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -352,3 +352,4 @@
 4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
 c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108
 1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109
+925be13b3740d07a5958ccb5ab3c0ae1baba7055 jdk-9+110
diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4
index d748c4f..753d170 100644
--- a/common/autoconf/basics.m4
+++ b/common/autoconf/basics.m4
@@ -843,6 +843,8 @@
   AC_CONFIG_FILES([$OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in])
   # The bootcycle-spec.gmk file contains support for boot cycle builds.
   AC_CONFIG_FILES([$OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in])
+  # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling.
+  AC_CONFIG_FILES([$OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in])
   # The compare.sh is used to compare the build output to other builds.
   AC_CONFIG_FILES([$OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in])
   # The generated Makefile knows where the spec.gmk is and where the source is.
diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4
index 7864ea9..91bf548 100644
--- a/common/autoconf/boot-jdk.m4
+++ b/common/autoconf/boot-jdk.m4
@@ -304,6 +304,18 @@
   # When compiling code to be executed by the Boot JDK, force jdk8 compatibility.
   BOOT_JDK_SOURCETARGET="-source 8 -target 8"
   AC_SUBST(BOOT_JDK_SOURCETARGET)
+
+  ADD_JVM_ARG_IF_OK([-Xpatch:], dummy, [$JAVA])
+  AC_MSG_CHECKING([if Boot JDK supports modules])
+  if test "x$JVM_ARG_OK" = "xtrue"; then
+    AC_MSG_RESULT([yes])
+    BOOT_JDK_MODULAR="true"
+  else
+    AC_MSG_RESULT([no])
+    BOOT_JDK_MODULAR="false"
+  fi
+  AC_SUBST(BOOT_JDK_MODULAR)
+
   AC_SUBST(JAVAC_FLAGS)
 
   # Check if the boot jdk is 32 or 64 bit
@@ -397,3 +409,100 @@
   done
   AC_SUBST(JAVA_TOOL_FLAGS_SMALL)
 ])
+
+# BUILD_JDK: the location of the latest JDK that can run
+#   on the host system and supports the target class file version
+#   generated in this JDK build.  This variable should only be
+#   used after the launchers are built.
+#
+
+# Execute the check given as argument, and verify the result.
+# If the JDK was previously found, do nothing.
+# $1 A command line (typically autoconf macro) to execute
+AC_DEFUN([BOOTJDK_CHECK_BUILD_JDK],
+[
+  if test "x$BUILD_JDK_FOUND" = xno; then
+    # Execute the test
+    $1
+
+    # If previous step claimed to have found a JDK, check it to see if it seems to be valid.
+    if test "x$BUILD_JDK_FOUND" = xmaybe; then
+      # Do we have a bin/java?
+      if test ! -x "$BUILD_JDK/bin/java"; then
+        AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/java; ignoring])
+        BUILD_JDK_FOUND=no
+      elif test ! -x "$BUILD_JDK/bin/jlink"; then
+        AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/jlink; ignoring])
+        BUILD_JDK_FOUND=no
+      elif test ! -x "$BUILD_JDK/bin/javac"; then
+        # Do we have a bin/javac?
+        AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/javac; ignoring])
+        AC_MSG_NOTICE([(This might be a JRE instead of an JDK)])
+        BUILD_JDK_FOUND=no
+      else
+        # Oh, this is looking good! We probably have found a proper JDK. Is it the correct version?
+        BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | head -n 1`
+
+        # Extra M4 quote needed to protect [] in grep expression.
+        [FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | grep  '\"1\.[9]\.'`]
+        if test "x$FOUND_CORRECT_VERSION" = x; then
+          AC_MSG_NOTICE([Potential Boot JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring])
+          AC_MSG_NOTICE([(Your Build JDK must be version 9)])
+          BUILD_JDK_FOUND=no
+        else
+          # We're done!
+          BUILD_JDK_FOUND=yes
+          BASIC_FIXUP_PATH(BUILD_JDK)
+          AC_MSG_CHECKING([for Build JDK])
+          AC_MSG_RESULT([$BUILD_JDK])
+          AC_MSG_CHECKING([Build JDK version])
+          BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | $TR '\n\r' '  '`
+          AC_MSG_RESULT([$BUILD_JDK_VERSION])
+        fi # end check jdk version
+      fi # end check java
+    fi # end check build jdk found
+  fi
+])
+
+# By default the BUILD_JDK is the JDK_OUTPUTDIR.  If the target architecture
+# is different than the host system doing the build (e.g. cross-compilation),
+# a special BUILD_JDK is built as part of the build process.  An external
+# prebuilt BUILD_JDK can also be supplied.
+AC_DEFUN([BOOTJDK_SETUP_BUILD_JDK],
+[
+  AC_ARG_WITH(build-jdk, [AS_HELP_STRING([--with-build-jdk],
+      [path to JDK of same version as is being built@<:@the newly built JDK@:>@])])
+
+  CREATE_BUILDJDK_FOR_HOST=false
+  BUILD_JDK_FOUND="no"
+  if test "x$with_build_jdk" != "x"; then
+    BOOTJDK_CHECK_BUILD_JDK([
+       if test "x$with_build_jdk" != x; then
+         BUILD_JDK=$with_build_jdk
+         BUILD_JDK_FOUND=maybe
+         AC_MSG_NOTICE([Found potential Build JDK using configure arguments])
+       fi])
+  else
+    if test "x$COMPILE_TYPE" = "xcross"; then
+      BUILD_JDK="\$(BUILDJDK_OUTPUTDIR)/jdk"
+      BUILD_JDK_FOUND=yes
+      CREATE_BUILDJDK=true
+      AC_MSG_CHECKING([for Build JDK])
+      AC_MSG_RESULT([yes, will build it for the host platform])
+    else
+      BUILD_JDK="\$(JDK_OUTPUTDIR)"
+      BUILD_JDK_FOUND=yes
+      AC_MSG_CHECKING([for Build JDK])
+      AC_MSG_RESULT([yes, will use output dir])
+    fi
+  fi
+
+  if test "x$BUILD_JDK_FOUND" != "xyes"; then
+    AC_MSG_CHECKING([for Build JDK])
+    AC_MSG_RESULT([no])
+    AC_MSG_ERROR([Could not find a suitable Build JDK])
+  fi
+
+  AC_SUBST(CREATE_BUILDJDK)
+  AC_SUBST(BUILD_JDK)
+])
diff --git a/common/autoconf/bootcycle-spec.gmk.in b/common/autoconf/bootcycle-spec.gmk.in
index 0335615..c37097d 100644
--- a/common/autoconf/bootcycle-spec.gmk.in
+++ b/common/autoconf/bootcycle-spec.gmk.in
@@ -25,6 +25,8 @@
 
 # Support for building boot cycle builds
 
+BOOT_JDK_MODULAR := true
+
 # First include the real base spec.gmk file
 include @SPEC@
 
diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in
new file mode 100644
index 0000000..f92602e
--- /dev/null
+++ b/common/autoconf/buildjdk-spec.gmk.in
@@ -0,0 +1,148 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# This spec file is used to compile a BUILD_JDK while cross compiling. The
+# BUILD_JDK runs on the build/host platform and is of the same version as
+# the main build.
+
+# First include the real base spec.gmk file
+include @SPEC@
+
+CC := @BUILD_CC@
+CXX := @BUILD_CXX@
+LD := @BUILD_LD@
+AS := @BUILD_AS@
+NM := @BUILD_NM@
+AR := @BUILD_AR@
+OBJCOPY := @BUILD_OBJCOPY@
+STRIP := @BUILD_STRIP@
+SYSROOT_CFLAGS := @BUILD_SYSROOT_CFLAGS@
+SYSROOT_LDFLAGS := @BUILD_SYSROOT_LDFLAGS@
+
+# These directories should not be moved to BUILDJDK_OUTPUTDIR
+HOTSPOT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_OUTPUTDIR))
+HOTSPOT_DIST := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_DIST))
+SUPPORT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(SUPPORT_OUTPUTDIR))
+JDK_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(JDK_OUTPUTDIR))
+
+OPENJDK_BUILD_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@
+OPENJDK_BUILD_CPU_LEGACY_LIB := @OPENJDK_BUILD_CPU_LEGACY_LIB@
+OPENJDK_BUILD_CPU_LIBDIR := @OPENJDK_BUILD_CPU_LIBDIR@
+OPENJDK_TARGET_CPU_LIBDIR := @OPENJDK_BUILD_CPU_LIBDIR@
+OPENJDK_TARGET_CPU := @OPENJDK_BUILD_CPU@
+OPENJDK_TARGET_CPU_ARCH := @OPENJDK_BUILD_CPU_ARCH@
+OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@
+OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@
+OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@
+
+CFLAGS_JDKLIB := @OPENJDK_BUILD_CFLAGS_JDKLIB@
+CXXFLAGS_JDKLIB := @OPENJDK_BUILD_CXXFLAGS_JDKLIB@
+LDFLAGS_JDKLIB := @OPENJDK_BUILD_LDFLAGS_JDKLIB@
+CFLAGS_JDKEXE := @OPENJDK_BUILD_CFLAGS_JDKEXE@
+CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@
+LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@
+OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@
+
+# The compiler for the build platform is likely not warning compatible with the official
+# compiler.
+WARNINGS_AS_ERRORS := false
+DISABLE_WARNING_PREFIX := @BUILD_CC_DISABLE_WARNING_PREFIX@
+
+# Save speed and disk space by not enabling debug symbols for the buildjdk
+ENABLE_DEBUG_SYMBOLS := false
+
+####################################################
+#
+# Legacy Hotspot support
+
+# Legacy setting: OPT or DBG
+VARIANT := OPT
+# Legacy setting: true or false
+FASTDEBUG := false
+# Legacy setting: debugging the class files?
+DEBUG_CLASSFILES := false
+
+# 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 runs Queens test after building
+TEST_IN_BUILD := 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
+
+# Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files.
+# This is needed to get the LOG setting to work properly.
+include $(SRC_ROOT)/make/common/MakeBase.gmk
diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac
index 127d908..c7bab7c 100644
--- a/common/autoconf/configure.ac
+++ b/common/autoconf/configure.ac
@@ -134,6 +134,7 @@
 
 # We need build & target for this.
 JDKOPT_SETUP_JDK_OPTIONS
+JDKOPT_SETUP_JLINK_OPTIONS
 HOTSPOT_SETUP_HOTSPOT_OPTIONS
 JDKVER_SETUP_JDK_VERSION_NUMBERS
 
@@ -144,6 +145,7 @@
 ###############################################################################
 
 BOOTJDK_SETUP_BOOT_JDK
+BOOTJDK_SETUP_BUILD_JDK
 
 ###############################################################################
 #
@@ -155,6 +157,8 @@
 SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS
 SRCDIRS_SETUP_OUTPUT_DIRS
 
+SRCDIRS_SETUP_IMPORT_MODULES
+
 ###############################################################################
 #
 # Setup the toolchain (compilers etc), i.e. tools used to compile and process
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index 6b08cbb..9ea5eaa 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -689,9 +689,6 @@
       ;;
   esac
 
-  # Setup LP64
-  COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $ADD_LP64"
-
   # Set some common defines. These works for all compilers, but assume
   # -D is universally accepted.
 
@@ -722,7 +719,12 @@
   COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE"
 
   # Setup target CPU
-  COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
+  OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $ADD_LP64 \
+      -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
+  OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $OPENJDK_BUILD_ADD_LP64 \
+      -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY"
 
   # Setup debug/release defines
   if test "x$DEBUG_LEVEL" = xrelease; then
@@ -766,17 +768,35 @@
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
 
   # The shared libraries are compiled using the picflag.
-  CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
-  CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
+  CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
+  CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
 
   # Executable flags
-  CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK"
-  CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK"
+  CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CFLAGS_JDK $EXTRA_CFLAGS_JDK"
+  CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK"
+
+  # The corresponding flags for building for the build platform. This is still an
+  # approximation, we only need something that runs on this machine when cross
+  # compiling the product.
+  OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $PICFLAG $CFLAGS_JDKLIB_EXTRA"
+  OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
+  OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
+  OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
 
   AC_SUBST(CFLAGS_JDKLIB)
   AC_SUBST(CFLAGS_JDKEXE)
   AC_SUBST(CXXFLAGS_JDKLIB)
   AC_SUBST(CXXFLAGS_JDKEXE)
+  AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKLIB)
+  AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKEXE)
+  AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKLIB)
+  AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKEXE)
 
   # Flags for compiling test libraries
   CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
@@ -872,6 +892,9 @@
     LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
   fi
 
+  OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}"
+  LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}"
+
   # Customize LDFLAGS for libs
   LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
 
@@ -882,30 +905,39 @@
     JDKLIB_LIBS=""
   else
     LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
-        -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
+        -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)"
 
     # On some platforms (mac) the linker warns about non existing -L dirs.
     # Add server first if available. Linking aginst client does not always produce the same results.
     # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1.
     # Default to server for other variants.
     if test "x$JVM_VARIANT_SERVER" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
     elif test "x$JVM_VARIANT_CLIENT" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/client"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client"
     elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/minimal"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal"
     else
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
     fi
 
     JDKLIB_LIBS="-ljava -ljvm"
     if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
       JDKLIB_LIBS="$JDKLIB_LIBS -lc"
     fi
+
+    # When building a buildjdk, it's always only the server variant
+    OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \
+        -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
   fi
 
+  OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}"
+  LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}"
+
   AC_SUBST(LDFLAGS_JDKLIB)
   AC_SUBST(LDFLAGS_JDKEXE)
+  AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB)
+  AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE)
   AC_SUBST(JDKLIB_LIBS)
   AC_SUBST(JDKEXE_LIBS)
   AC_SUBST(LDFLAGS_CXX_JDK)
@@ -1075,5 +1107,6 @@
       ;;
   esac
   AC_SUBST(DISABLE_WARNING_PREFIX)
+  AC_SUBST(BUILD_CC_DISABLE_WARNING_PREFIX)
   AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
 ])
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 58beee0..e4ea273 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -694,6 +694,7 @@
 COPY_DEBUG_SYMBOLS
 COMPILE_WITH_DEBUG_SYMBOLS
 CFLAGS_WARNINGS_ARE_ERRORS
+BUILD_CC_DISABLE_WARNING_PREFIX
 DISABLE_WARNING_PREFIX
 HOTSPOT_SET_WARNINGS_AS_ERRORS
 WARNINGS_AS_ERRORS
@@ -705,12 +706,18 @@
 LDFLAGS_CXX_JDK
 JDKEXE_LIBS
 JDKLIB_LIBS
+OPENJDK_BUILD_LDFLAGS_JDKEXE
+OPENJDK_BUILD_LDFLAGS_JDKLIB
 LDFLAGS_JDKEXE
 LDFLAGS_JDKLIB
 CXXFLAGS_TESTEXE
 CXXFLAGS_TESTLIB
 CFLAGS_TESTEXE
 CFLAGS_TESTLIB
+OPENJDK_BUILD_CXXFLAGS_JDKEXE
+OPENJDK_BUILD_CXXFLAGS_JDKLIB
+OPENJDK_BUILD_CFLAGS_JDKEXE
+OPENJDK_BUILD_CFLAGS_JDKLIB
 CXXFLAGS_JDKEXE
 CXXFLAGS_JDKLIB
 CFLAGS_JDKEXE
@@ -759,6 +766,8 @@
 BUILD_AS
 BUILD_LDCXX
 BUILD_LD
+BUILD_STRIP
+BUILD_OBJCOPY
 BUILD_AR
 BUILD_NM
 BUILD_CXX
@@ -821,6 +830,12 @@
 LIBRARY_PREFIX
 TOOLCHAIN_TYPE
 STATIC_BUILD
+IMPORT_MODULES_MAKE
+IMPORT_MODULES_SRC
+IMPORT_MODULES_CONF
+IMPORT_MODULES_LIBS
+IMPORT_MODULES_CMDS
+IMPORT_MODULES_CLASSES
 BUILD_HOTSPOT
 HOTSPOT_DIST
 BUILD_OUTPUT
@@ -831,8 +846,11 @@
 JAXP_TOPDIR
 CORBA_TOPDIR
 LANGTOOLS_TOPDIR
+BUILD_JDK
+CREATE_BUILDJDK
 BOOT_JDK_BITS
 JAVAC_FLAGS
+BOOT_JDK_MODULAR
 BOOT_JDK_SOURCETARGET
 JARSIGNER
 JAR
@@ -862,6 +880,7 @@
 PRODUCT_NAME
 LAUNCHER_NAME
 TEST_IN_BUILD
+JLINK_KEEP_PACKAGED_MODULES
 COPYRIGHT_YEAR
 COMPRESS_JARS
 INCLUDE_SA
@@ -930,9 +949,13 @@
 DEFINE_CROSS_COMPILE_ARCH
 LP64
 OPENJDK_TARGET_OS_EXPORT_DIR
+OPENJDK_BUILD_CPU_JLI_CFLAGS
 OPENJDK_TARGET_CPU_JLI_CFLAGS
 OPENJDK_TARGET_CPU_OSARCH
 OPENJDK_TARGET_CPU_ISADIR
+OPENJDK_BUILD_CPU_LIBDIR
+OPENJDK_BUILD_CPU_LEGACY_LIB
+OPENJDK_BUILD_CPU_LEGACY
 OPENJDK_TARGET_CPU_LIBDIR
 OPENJDK_TARGET_CPU_LEGACY_LIB
 OPENJDK_TARGET_CPU_LEGACY
@@ -1080,6 +1103,7 @@
 with_cacerts_file
 enable_unlimited_crypto
 with_copyright_year
+enable_keep_packaged_modules
 enable_hotspot_test_in_build
 with_milestone
 with_update_version
@@ -1094,6 +1118,7 @@
 with_version_security
 with_version_patch
 with_boot_jdk
+with_build_jdk
 with_add_source_root
 with_override_source_root
 with_adds_and_overrides
@@ -1105,6 +1130,7 @@
 with_override_nashorn
 with_override_jdk
 with_import_hotspot
+with_import_modules
 enable_static_build
 with_toolchain_type
 with_extra_cflags
@@ -1248,6 +1274,8 @@
 BUILD_CXX
 BUILD_NM
 BUILD_AR
+BUILD_OBJCOPY
+BUILD_STRIP
 JTREGEXE
 XMKMF
 FREETYPE_CFLAGS
@@ -1890,6 +1918,8 @@
                           support) [enabled]
   --enable-unlimited-crypto
                           Enable unlimited crypto policy [disabled]
+  --disable-keep-packaged-modules
+                          Do not keep packaged modules in jdk image [enable]
   --enable-hotspot-test-in-build
                           run the Queens test after Hotspot build [disabled]
   --enable-static-build   enable static library build [disabled]
@@ -1973,6 +2003,8 @@
   --with-version-patch    Set version 'PATCH' field (fourth number) [not
                           specified]
   --with-boot-jdk         path to Boot JDK (used to bootstrap build) [probed]
+  --with-build-jdk        path to JDK of same version as is being built[the
+                          newly built JDK]
   --with-add-source-root  Deprecated. Option is kept for backwards
                           compatibility and is ignored
   --with-override-source-root
@@ -1999,6 +2031,8 @@
   --with-import-hotspot   import hotspot binaries from this jdk image or
                           hotspot build dist dir instead of building from
                           source
+  --with-import-modules   import a set of prebuilt modules either as a zip
+                          file or an exploded directory
   --with-toolchain-type   the toolchain type (or family) to use, use '--help'
                           to show possible values [platform dependent]
   --with-extra-cflags     extra flags to be used when compiling jdk c-files
@@ -2167,6 +2201,9 @@
   BUILD_CXX   Override default value for BUILD_CXX
   BUILD_NM    Override default value for BUILD_NM
   BUILD_AR    Override default value for BUILD_AR
+  BUILD_OBJCOPY
+              Override default value for BUILD_OBJCOPY
+  BUILD_STRIP Override default value for BUILD_STRIP
   JTREGEXE    Override default value for JTREGEXE
   XMKMF       Path to xmkmf, Makefile generator for X Window System
   FREETYPE_CFLAGS
@@ -3777,6 +3814,23 @@
 
 
 
+# BUILD_JDK: the location of the latest JDK that can run
+#   on the host system and supports the target class file version
+#   generated in this JDK build.  This variable should only be
+#   used after the launchers are built.
+#
+
+# Execute the check given as argument, and verify the result.
+# If the JDK was previously found, do nothing.
+# $1 A command line (typically autoconf macro) to execute
+
+
+# By default the BUILD_JDK is the JDK_OUTPUTDIR.  If the target architecture
+# is different than the host system doing the build (e.g. cross-compilation),
+# a special BUILD_JDK is built as part of the build process.  An external
+# prebuilt BUILD_JDK can also be supplied.
+
+
 #
 # Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4192,6 +4246,13 @@
 #
 
 
+################################################################################
+#
+# jlink options.
+# We always keep packaged modules in JDK image.
+#
+
+
 #
 # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4628,6 +4689,12 @@
 
 
 
+################################################################################
+# Define a mechanism for importing extra prebuilt modules
+#
+
+
+
 #
 # Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4862,7 +4929,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1457684806
+DATE_WHEN_GENERATED=1458008154
 
 ###############################################################################
 #
@@ -15157,6 +15224,37 @@
   fi
 
 
+  # Now do the same for OPENJDK_BUILD_CPU...
+  # Also store the legacy naming of the cpu.
+  # Ie i586 and amd64 instead of x86 and x86_64
+  OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_LEGACY="i586"
+  elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    # On all platforms except MacOSX replace x86_64 with amd64.
+    OPENJDK_BUILD_CPU_LEGACY="amd64"
+  fi
+
+
+  # And the second legacy naming of the cpu.
+  # Ie i386 and amd64 instead of x86 and x86_64.
+  OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_LEGACY_LIB="i386"
+  elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    OPENJDK_BUILD_CPU_LEGACY_LIB="amd64"
+  fi
+
+
+  # This is the name of the cpu (but using i386 and amd64 instead of
+  # x86 and x86_64, respectively), preceeded by a /, to be used when
+  # locating libraries. On macosx, it's empty, though.
+  OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB"
+  if test "x$OPENJDK_BUILD_OS" = xmacosx; then
+    OPENJDK_BUILD_CPU_LIBDIR=""
+  fi
+
+
   # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to
   # /amd64 or /sparcv9. This string is appended to some library paths, like this:
   # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so
@@ -15199,6 +15297,24 @@
   fi
 
 
+  OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_JLI="i386"
+  elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    # On all platforms except macosx, we replace x86_64 with amd64.
+    OPENJDK_BUILD_CPU_JLI="amd64"
+  fi
+  # Now setup the -D flags for building libjli.
+  OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'"
+  if test "x$OPENJDK_BUILD_OS" = xsolaris; then
+    if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then
+      OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'"
+    elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then
+      OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'"
+    fi
+  fi
+
+
   if test "x$OPENJDK_TARGET_OS" = xmacosx; then
       OPENJDK_TARGET_OS_EXPORT_DIR=macosx
   else
@@ -15216,6 +15332,11 @@
   fi
   LP64=$A_LP64
 
+  if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then
+    if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then
+      OPENJDK_BUILD_ADD_LP64="-D_LP64=1"
+    fi
+  fi
 
   if test "x$COMPILE_TYPE" = "xcross"; then
     # FIXME: ... or should this include reduced builds..?
@@ -16701,6 +16822,9 @@
   # The bootcycle-spec.gmk file contains support for boot cycle builds.
   ac_config_files="$ac_config_files $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in"
 
+  # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling.
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in"
+
   # The compare.sh is used to compare the build output to other builds.
   ac_config_files="$ac_config_files $OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in"
 
@@ -23299,6 +23423,35 @@
 
 
 
+  # Check whether --enable-keep-packaged-modules was given.
+if test "${enable_keep_packaged_modules+set}" = set; then :
+  enableval=$enable_keep_packaged_modules;
+fi
+
+
+  if test "x$enable_keep_packaged_modules" = "xyes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if packaged modules are kept" >&5
+$as_echo_n "checking if packaged modules are kept... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    JLINK_KEEP_PACKAGED_MODULES=true
+  elif test "x$enable_keep_packaged_modules" = "xno"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if packaged modules are kept" >&5
+$as_echo_n "checking if packaged modules are kept... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    JLINK_KEEP_PACKAGED_MODULES=false
+  elif test "x$enable_keep_packaged_modules" = "x"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5
+$as_echo "yes (default)" >&6; }
+    JLINK_KEEP_PACKAGED_MODULES=true
+  else
+    as_fn_error $? "--enable-keep-packaged-modules accepts no argument" "$LINENO" 5
+  fi
+
+
+
+
   # Control wether Hotspot runs Queens test after build.
   # Check whether --enable-hotspot-test-in-build was given.
 if test "${enable_hotspot_test_in_build+set}" = set; then :
@@ -29596,6 +29749,35 @@
 
 
 
+  $ECHO "Check if jvm arg is ok: -Xpatch:" >&5
+  $ECHO "Command: $JAVA -Xpatch: -version" >&5
+  OUTPUT=`$JAVA -Xpatch: -version 2>&1`
+  FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn`
+  FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""`
+  if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+    dummy="$dummy -Xpatch:"
+    JVM_ARG_OK=true
+  else
+    $ECHO "Arg failed:" >&5
+    $ECHO "$OUTPUT" >&5
+    JVM_ARG_OK=false
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Boot JDK supports modules" >&5
+$as_echo_n "checking if Boot JDK supports modules... " >&6; }
+  if test "x$JVM_ARG_OK" = "xtrue"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    BOOT_JDK_MODULAR="true"
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    BOOT_JDK_MODULAR="false"
+  fi
+
+
+
+
   # Check if the boot jdk is 32 or 64 bit
   if "$JAVA" -d64 -version > /dev/null 2>&1; then
     BOOT_JDK_BITS="64"
@@ -29609,6 +29791,237 @@
 
 
 
+
+# Check whether --with-build-jdk was given.
+if test "${with_build_jdk+set}" = set; then :
+  withval=$with_build_jdk;
+fi
+
+
+  CREATE_BUILDJDK_FOR_HOST=false
+  BUILD_JDK_FOUND="no"
+  if test "x$with_build_jdk" != "x"; then
+
+  if test "x$BUILD_JDK_FOUND" = xno; then
+    # Execute the test
+
+       if test "x$with_build_jdk" != x; then
+         BUILD_JDK=$with_build_jdk
+         BUILD_JDK_FOUND=maybe
+         { $as_echo "$as_me:${as_lineno-$LINENO}: Found potential Build JDK using configure arguments" >&5
+$as_echo "$as_me: Found potential Build JDK using configure arguments" >&6;}
+       fi
+
+    # If previous step claimed to have found a JDK, check it to see if it seems to be valid.
+    if test "x$BUILD_JDK_FOUND" = xmaybe; then
+      # Do we have a bin/java?
+      if test ! -x "$BUILD_JDK/bin/java"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Build JDK found at $BUILD_JDK did not contain bin/java; ignoring" >&5
+$as_echo "$as_me: Potential Build JDK found at $BUILD_JDK did not contain bin/java; ignoring" >&6;}
+        BUILD_JDK_FOUND=no
+      elif test ! -x "$BUILD_JDK/bin/jlink"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Build JDK found at $BUILD_JDK did not contain bin/jlink; ignoring" >&5
+$as_echo "$as_me: Potential Build JDK found at $BUILD_JDK did not contain bin/jlink; ignoring" >&6;}
+        BUILD_JDK_FOUND=no
+      elif test ! -x "$BUILD_JDK/bin/javac"; then
+        # Do we have a bin/javac?
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Build JDK found at $BUILD_JDK did not contain bin/javac; ignoring" >&5
+$as_echo "$as_me: Potential Build JDK found at $BUILD_JDK did not contain bin/javac; ignoring" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: (This might be a JRE instead of an JDK)" >&5
+$as_echo "$as_me: (This might be a JRE instead of an JDK)" >&6;}
+        BUILD_JDK_FOUND=no
+      else
+        # Oh, this is looking good! We probably have found a proper JDK. Is it the correct version?
+        BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | head -n 1`
+
+        # Extra M4 quote needed to protect [] in grep expression.
+        FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | grep  '\"1\.[9]\.'`
+        if test "x$FOUND_CORRECT_VERSION" = x; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring" >&5
+$as_echo "$as_me: Potential Boot JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Build JDK must be version 9)" >&5
+$as_echo "$as_me: (Your Build JDK must be version 9)" >&6;}
+          BUILD_JDK_FOUND=no
+        else
+          # We're done!
+          BUILD_JDK_FOUND=yes
+
+  # Only process if variable expands to non-empty
+
+  if test "x$BUILD_JDK" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$BUILD_JDK"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_JDK, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of BUILD_JDK, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of BUILD_JDK" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    BUILD_JDK="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_JDK to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting BUILD_JDK to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$BUILD_JDK"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    BUILD_JDK="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_JDK to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting BUILD_JDK to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$BUILD_JDK"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_JDK, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of BUILD_JDK, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of BUILD_JDK, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        BUILD_JDK="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        BUILD_JDK="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Build JDK" >&5
+$as_echo_n "checking for Build JDK... " >&6; }
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_JDK" >&5
+$as_echo "$BUILD_JDK" >&6; }
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking Build JDK version" >&5
+$as_echo_n "checking Build JDK version... " >&6; }
+          BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | $TR '\n\r' '  '`
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_JDK_VERSION" >&5
+$as_echo "$BUILD_JDK_VERSION" >&6; }
+        fi # end check jdk version
+      fi # end check java
+    fi # end check build jdk found
+  fi
+
+  else
+    if test "x$COMPILE_TYPE" = "xcross"; then
+      BUILD_JDK="\$(BUILDJDK_OUTPUTDIR)/jdk"
+      BUILD_JDK_FOUND=yes
+      CREATE_BUILDJDK=true
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Build JDK" >&5
+$as_echo_n "checking for Build JDK... " >&6; }
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, will build it for the host platform" >&5
+$as_echo "yes, will build it for the host platform" >&6; }
+    else
+      BUILD_JDK="\$(JDK_OUTPUTDIR)"
+      BUILD_JDK_FOUND=yes
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Build JDK" >&5
+$as_echo_n "checking for Build JDK... " >&6; }
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, will use output dir" >&5
+$as_echo "yes, will use output dir" >&6; }
+    fi
+  fi
+
+  if test "x$BUILD_JDK_FOUND" != "xyes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Build JDK" >&5
+$as_echo_n "checking for Build JDK... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    as_fn_error $? "Could not find a suitable Build JDK" "$LINENO" 5
+  fi
+
+
+
+
+
 ###############################################################################
 #
 # Configure the sources to use. We can add or override individual directories.
@@ -29758,6 +30171,189 @@
   JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
 
 
+
+
+# Check whether --with-import-modules was given.
+if test "${with_import_modules+set}" = set; then :
+  withval=$with_import_modules;
+fi
+
+
+  if test "x$with_import_modules" != x \
+      && test "x$with_import_modules" != "xno"; then
+    if test -d "$with_import_modules"; then
+      IMPORT_MODULES_TOPDIR="$with_import_modules"
+
+  # Only process if variable expands to non-empty
+
+  if test "x$IMPORT_MODULES_TOPDIR" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$IMPORT_MODULES_TOPDIR"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of IMPORT_MODULES_TOPDIR, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of IMPORT_MODULES_TOPDIR, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of IMPORT_MODULES_TOPDIR" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    IMPORT_MODULES_TOPDIR="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting IMPORT_MODULES_TOPDIR to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting IMPORT_MODULES_TOPDIR to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$IMPORT_MODULES_TOPDIR"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    IMPORT_MODULES_TOPDIR="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting IMPORT_MODULES_TOPDIR to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting IMPORT_MODULES_TOPDIR to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$IMPORT_MODULES_TOPDIR"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of IMPORT_MODULES_TOPDIR, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of IMPORT_MODULES_TOPDIR, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of IMPORT_MODULES_TOPDIR, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        IMPORT_MODULES_TOPDIR="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        IMPORT_MODULES_TOPDIR="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+    elif test -e "$with_import_modules"; then
+      IMPORT_MODULES_TOPDIR="$CONFIGURESUPPORT_OUTPUTDIR/import-modules"
+      $RM -rf "$IMPORT_MODULES_TOPDIR"
+      $MKDIR -p "$IMPORT_MODULES_TOPDIR"
+      if ! $UNZIP -q "$with_import_modules" -d "$IMPORT_MODULES_TOPDIR"; then
+        as_fn_error $? "--with-import-modules=\"$with_import_modules\" must point to a dir or a zip file" "$LINENO" 5
+      fi
+    else
+      as_fn_error $? "--with-import-modules=\"$with_import_modules\" must point to a dir or a zip file" "$LINENO" 5
+    fi
+  fi
+
+  if test -d "$IMPORT_MODULES_TOPDIR/modules"; then
+    IMPORT_MODULES_CLASSES="$IMPORT_MODULES_TOPDIR/modules"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_cmds"; then
+    IMPORT_MODULES_CMDS="$IMPORT_MODULES_TOPDIR/modules_cmds"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_libs"; then
+    IMPORT_MODULES_LIBS="$IMPORT_MODULES_TOPDIR/modules_libs"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_conf"; then
+    IMPORT_MODULES_CONF="$IMPORT_MODULES_TOPDIR/modules_conf"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
+    IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/make"; then
+    IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
+  fi
+
+
+
+
+
+
+
+
+
 ###############################################################################
 #
 # Setup the toolchain (compilers etc), i.e. tools used to compile and process
@@ -44514,6 +45110,972 @@
     fi
   fi
 
+
+
+  # Publish this variable in the help.
+
+
+  if [ -z "${BUILD_OBJCOPY+x}" ]; then
+    # The variable is not set by user, try to locate tool using the code snippet
+    for ac_prog in objcopy
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_OBJCOPY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_OBJCOPY in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_OBJCOPY="$BUILD_OBJCOPY" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_OBJCOPY="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_OBJCOPY=$ac_cv_path_BUILD_OBJCOPY
+if test -n "$BUILD_OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_OBJCOPY" >&5
+$as_echo "$BUILD_OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$BUILD_OBJCOPY" && break
+done
+
+  else
+    # The variable is set, but is it from the command line or the environment?
+
+    # Try to remove the string !BUILD_OBJCOPY! from our list.
+    try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_OBJCOPY!/}
+    if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+      # If it failed, the variable was not from the command line. Ignore it,
+      # but warn the user (except for BASH, which is always set by the calling BASH).
+      if test "xBUILD_OBJCOPY" != xBASH; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_OBJCOPY from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of BUILD_OBJCOPY from the environment. Use command line variables instead." >&2;}
+      fi
+      # Try to locate tool using the code snippet
+      for ac_prog in objcopy
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_OBJCOPY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_OBJCOPY in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_OBJCOPY="$BUILD_OBJCOPY" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_OBJCOPY="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_OBJCOPY=$ac_cv_path_BUILD_OBJCOPY
+if test -n "$BUILD_OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_OBJCOPY" >&5
+$as_echo "$BUILD_OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$BUILD_OBJCOPY" && break
+done
+
+    else
+      # If it succeeded, then it was overridden by the user. We will use it
+      # for the tool.
+
+      # First remove it from the list of overridden variables, so we can test
+      # for unknown variables in the end.
+      CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+      # Check if we try to supply an empty value
+      if test "x$BUILD_OBJCOPY" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool BUILD_OBJCOPY= (no value)" >&5
+$as_echo "$as_me: Setting user supplied tool BUILD_OBJCOPY= (no value)" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_OBJCOPY" >&5
+$as_echo_n "checking for BUILD_OBJCOPY... " >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+      else
+        # Check if the provided tool contains a complete path.
+        tool_specified="$BUILD_OBJCOPY"
+        tool_basename="${tool_specified##*/}"
+        if test "x$tool_basename" = "x$tool_specified"; then
+          # A command without a complete path is provided, search $PATH.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_OBJCOPY=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool BUILD_OBJCOPY=$tool_basename" >&6;}
+          # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_OBJCOPY+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_OBJCOPY in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_OBJCOPY="$BUILD_OBJCOPY" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_OBJCOPY="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_OBJCOPY=$ac_cv_path_BUILD_OBJCOPY
+if test -n "$BUILD_OBJCOPY"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_OBJCOPY" >&5
+$as_echo "$BUILD_OBJCOPY" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+          if test "x$BUILD_OBJCOPY" = x; then
+            as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+          fi
+        else
+          # Otherwise we believe it is a complete path. Use it as it is.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_OBJCOPY=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool BUILD_OBJCOPY=$tool_specified" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_OBJCOPY" >&5
+$as_echo_n "checking for BUILD_OBJCOPY... " >&6; }
+          if test ! -x "$tool_specified"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+            as_fn_error $? "User supplied tool BUILD_OBJCOPY=$tool_specified does not exist or is not executable" "$LINENO" 5
+          fi
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+        fi
+      fi
+    fi
+
+  fi
+
+
+
+  # Only process if variable expands to non-empty
+
+  if test "x$BUILD_OBJCOPY" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # First separate the path from the arguments. This will split at the first
+  # space.
+  complete="$BUILD_OBJCOPY"
+  path="${complete%% *}"
+  tmp="$complete EOL"
+  arguments="${tmp#* }"
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  new_path=`$CYGPATH -u "$path"`
+
+  # Now try to locate executable using which
+  new_path=`$WHICH "$new_path" 2> /dev/null`
+  # bat and cmd files are not always considered executable in cygwin causing which
+  # to not find them
+  if test "x$new_path" = x \
+      && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+      && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+    new_path=`$CYGPATH -u "$path"`
+  fi
+  if test "x$new_path" = x; then
+    # Oops. Which didn't find the executable.
+    # The splitting of arguments from the executable at a space might have been incorrect,
+    # since paths with space are more likely in Windows. Give it another try with the whole
+    # argument.
+    path="$complete"
+    arguments="EOL"
+    new_path=`$CYGPATH -u "$path"`
+    new_path=`$WHICH "$new_path" 2> /dev/null`
+    # bat and cmd files are not always considered executable in cygwin causing which
+    # to not find them
+    if test "x$new_path" = x \
+        && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+        && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+      new_path=`$CYGPATH -u "$path"`
+    fi
+    if test "x$new_path" = x; then
+      # It's still not found. Now this is an unrecoverable error.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&6;}
+      has_space=`$ECHO "$complete" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5
+$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;}
+      fi
+      as_fn_error $? "Cannot locate the the path of BUILD_OBJCOPY" "$LINENO" 5
+    fi
+  fi
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file presence.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    # Short path failed, file does not exist as specified.
+    # Try adding .exe or .cmd
+    if test -f "${new_path}.exe"; then
+      input_to_shortpath="${new_path}.exe"
+    elif test -f "${new_path}.cmd"; then
+      input_to_shortpath="${new_path}.cmd"
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_OBJCOPY, which resolves as \"$new_path\", is invalid." >&5
+$as_echo "$as_me: The path of BUILD_OBJCOPY, which resolves as \"$new_path\", is invalid." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5
+$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;}
+      as_fn_error $? "Cannot locate the the path of BUILD_OBJCOPY" "$LINENO" 5
+    fi
+  else
+    input_to_shortpath="$new_path"
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+  new_path="$input_to_shortpath"
+
+  input_path="$input_to_shortpath"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+  # remove trailing .exe if any
+  new_path="${new_path/%.exe/}"
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  # First separate the path from the arguments. This will split at the first
+  # space.
+  complete="$BUILD_OBJCOPY"
+  path="${complete%% *}"
+  tmp="$complete EOL"
+  arguments="${tmp#* }"
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+
+  # Now try to locate executable using which
+  new_path=`$WHICH "$new_path" 2> /dev/null`
+
+  if test "x$new_path" = x; then
+    # Oops. Which didn't find the executable.
+    # The splitting of arguments from the executable at a space might have been incorrect,
+    # since paths with space are more likely in Windows. Give it another try with the whole
+    # argument.
+    path="$complete"
+    arguments="EOL"
+    new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+
+    new_path=`$WHICH "$new_path" 2> /dev/null`
+    # bat and cmd files are not always considered executable in MSYS causing which
+    # to not find them
+    if test "x$new_path" = x \
+        && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+        && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+      new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+    fi
+
+    if test "x$new_path" = x; then
+      # It's still not found. Now this is an unrecoverable error.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&6;}
+      has_space=`$ECHO "$complete" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5
+$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;}
+      fi
+      as_fn_error $? "Cannot locate the the path of BUILD_OBJCOPY" "$LINENO" 5
+    fi
+  fi
+
+  # Now new_path has a complete unix path to the binary
+  if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then
+    # Keep paths in /bin as-is, but remove trailing .exe if any
+    new_path="${new_path/%.exe/}"
+    # Do not save /bin paths to all_fixpath_prefixes!
+  else
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $new_path`
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+    # Output is in $new_path
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+    # remove trailing .exe if any
+    new_path="${new_path/%.exe/}"
+
+    # Save the first 10 bytes of this path to the storage, so fixpath can work.
+    all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+  fi
+
+    else
+      # We're on a unix platform. Hooray! :)
+      # First separate the path from the arguments. This will split at the first
+      # space.
+      complete="$BUILD_OBJCOPY"
+      path="${complete%% *}"
+      tmp="$complete EOL"
+      arguments="${tmp#* }"
+
+      # Cannot rely on the command "which" here since it doesn't always work.
+      is_absolute_path=`$ECHO "$path" | $GREP ^/`
+      if test -z "$is_absolute_path"; then
+        # Path to executable is not absolute. Find it.
+        IFS_save="$IFS"
+        IFS=:
+        for p in $PATH; do
+          if test -f "$p/$path" && test -x "$p/$path"; then
+            new_path="$p/$path"
+            break
+          fi
+        done
+        IFS="$IFS_save"
+      else
+        # This is an absolute path, we can use it without further modifications.
+        new_path="$path"
+      fi
+
+      if test "x$new_path" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_OBJCOPY, which resolves as \"$complete\", is not found." >&6;}
+        has_space=`$ECHO "$complete" | $GREP " "`
+        if test "x$has_space" != x; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5
+$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;}
+        fi
+        as_fn_error $? "Cannot locate the the path of BUILD_OBJCOPY" "$LINENO" 5
+      fi
+    fi
+
+    # Now join together the path and the arguments once again
+    if test "x$arguments" != xEOL; then
+      new_complete="$new_path ${arguments% *}"
+    else
+      new_complete="$new_path"
+    fi
+
+    if test "x$complete" != "x$new_complete"; then
+      BUILD_OBJCOPY="$new_complete"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_OBJCOPY to \"$new_complete\"" >&5
+$as_echo "$as_me: Rewriting BUILD_OBJCOPY to \"$new_complete\"" >&6;}
+    fi
+  fi
+
+
+
+  # Publish this variable in the help.
+
+
+  if [ -z "${BUILD_STRIP+x}" ]; then
+    # The variable is not set by user, try to locate tool using the code snippet
+    for ac_prog in strip
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_STRIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_STRIP="$BUILD_STRIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_STRIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_STRIP=$ac_cv_path_BUILD_STRIP
+if test -n "$BUILD_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_STRIP" >&5
+$as_echo "$BUILD_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$BUILD_STRIP" && break
+done
+
+  else
+    # The variable is set, but is it from the command line or the environment?
+
+    # Try to remove the string !BUILD_STRIP! from our list.
+    try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!BUILD_STRIP!/}
+    if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+      # If it failed, the variable was not from the command line. Ignore it,
+      # but warn the user (except for BASH, which is always set by the calling BASH).
+      if test "xBUILD_STRIP" != xBASH; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of BUILD_STRIP from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of BUILD_STRIP from the environment. Use command line variables instead." >&2;}
+      fi
+      # Try to locate tool using the code snippet
+      for ac_prog in strip
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_STRIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_STRIP="$BUILD_STRIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_STRIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_STRIP=$ac_cv_path_BUILD_STRIP
+if test -n "$BUILD_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_STRIP" >&5
+$as_echo "$BUILD_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$BUILD_STRIP" && break
+done
+
+    else
+      # If it succeeded, then it was overridden by the user. We will use it
+      # for the tool.
+
+      # First remove it from the list of overridden variables, so we can test
+      # for unknown variables in the end.
+      CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+      # Check if we try to supply an empty value
+      if test "x$BUILD_STRIP" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool BUILD_STRIP= (no value)" >&5
+$as_echo "$as_me: Setting user supplied tool BUILD_STRIP= (no value)" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_STRIP" >&5
+$as_echo_n "checking for BUILD_STRIP... " >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+      else
+        # Check if the provided tool contains a complete path.
+        tool_specified="$BUILD_STRIP"
+        tool_basename="${tool_specified##*/}"
+        if test "x$tool_basename" = "x$tool_specified"; then
+          # A command without a complete path is provided, search $PATH.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool BUILD_STRIP=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool BUILD_STRIP=$tool_basename" >&6;}
+          # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BUILD_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BUILD_STRIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BUILD_STRIP="$BUILD_STRIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_BUILD_STRIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BUILD_STRIP=$ac_cv_path_BUILD_STRIP
+if test -n "$BUILD_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_STRIP" >&5
+$as_echo "$BUILD_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+          if test "x$BUILD_STRIP" = x; then
+            as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+          fi
+        else
+          # Otherwise we believe it is a complete path. Use it as it is.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool BUILD_STRIP=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool BUILD_STRIP=$tool_specified" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BUILD_STRIP" >&5
+$as_echo_n "checking for BUILD_STRIP... " >&6; }
+          if test ! -x "$tool_specified"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+            as_fn_error $? "User supplied tool BUILD_STRIP=$tool_specified does not exist or is not executable" "$LINENO" 5
+          fi
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+        fi
+      fi
+    fi
+
+  fi
+
+
+
+  # Only process if variable expands to non-empty
+
+  if test "x$BUILD_STRIP" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # First separate the path from the arguments. This will split at the first
+  # space.
+  complete="$BUILD_STRIP"
+  path="${complete%% *}"
+  tmp="$complete EOL"
+  arguments="${tmp#* }"
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  new_path=`$CYGPATH -u "$path"`
+
+  # Now try to locate executable using which
+  new_path=`$WHICH "$new_path" 2> /dev/null`
+  # bat and cmd files are not always considered executable in cygwin causing which
+  # to not find them
+  if test "x$new_path" = x \
+      && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+      && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+    new_path=`$CYGPATH -u "$path"`
+  fi
+  if test "x$new_path" = x; then
+    # Oops. Which didn't find the executable.
+    # The splitting of arguments from the executable at a space might have been incorrect,
+    # since paths with space are more likely in Windows. Give it another try with the whole
+    # argument.
+    path="$complete"
+    arguments="EOL"
+    new_path=`$CYGPATH -u "$path"`
+    new_path=`$WHICH "$new_path" 2> /dev/null`
+    # bat and cmd files are not always considered executable in cygwin causing which
+    # to not find them
+    if test "x$new_path" = x \
+        && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+        && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+      new_path=`$CYGPATH -u "$path"`
+    fi
+    if test "x$new_path" = x; then
+      # It's still not found. Now this is an unrecoverable error.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&6;}
+      has_space=`$ECHO "$complete" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5
+$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;}
+      fi
+      as_fn_error $? "Cannot locate the the path of BUILD_STRIP" "$LINENO" 5
+    fi
+  fi
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file presence.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    # Short path failed, file does not exist as specified.
+    # Try adding .exe or .cmd
+    if test -f "${new_path}.exe"; then
+      input_to_shortpath="${new_path}.exe"
+    elif test -f "${new_path}.cmd"; then
+      input_to_shortpath="${new_path}.cmd"
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_STRIP, which resolves as \"$new_path\", is invalid." >&5
+$as_echo "$as_me: The path of BUILD_STRIP, which resolves as \"$new_path\", is invalid." >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5
+$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;}
+      as_fn_error $? "Cannot locate the the path of BUILD_STRIP" "$LINENO" 5
+    fi
+  else
+    input_to_shortpath="$new_path"
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+  new_path="$input_to_shortpath"
+
+  input_path="$input_to_shortpath"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $input_to_shortpath | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+  # remove trailing .exe if any
+  new_path="${new_path/%.exe/}"
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  # First separate the path from the arguments. This will split at the first
+  # space.
+  complete="$BUILD_STRIP"
+  path="${complete%% *}"
+  tmp="$complete EOL"
+  arguments="${tmp#* }"
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+
+  # Now try to locate executable using which
+  new_path=`$WHICH "$new_path" 2> /dev/null`
+
+  if test "x$new_path" = x; then
+    # Oops. Which didn't find the executable.
+    # The splitting of arguments from the executable at a space might have been incorrect,
+    # since paths with space are more likely in Windows. Give it another try with the whole
+    # argument.
+    path="$complete"
+    arguments="EOL"
+    new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+
+    new_path=`$WHICH "$new_path" 2> /dev/null`
+    # bat and cmd files are not always considered executable in MSYS causing which
+    # to not find them
+    if test "x$new_path" = x \
+        && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
+        && test "x`$LS \"$path\" 2>/dev/null`" != x; then
+      new_path="$path"
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+    fi
+
+    if test "x$new_path" = x; then
+      # It's still not found. Now this is an unrecoverable error.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&6;}
+      has_space=`$ECHO "$complete" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5
+$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;}
+      fi
+      as_fn_error $? "Cannot locate the the path of BUILD_STRIP" "$LINENO" 5
+    fi
+  fi
+
+  # Now new_path has a complete unix path to the binary
+  if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then
+    # Keep paths in /bin as-is, but remove trailing .exe if any
+    new_path="${new_path/%.exe/}"
+    # Do not save /bin paths to all_fixpath_prefixes!
+  else
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $new_path`
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+    # Output is in $new_path
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+    # remove trailing .exe if any
+    new_path="${new_path/%.exe/}"
+
+    # Save the first 10 bytes of this path to the storage, so fixpath can work.
+    all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+  fi
+
+    else
+      # We're on a unix platform. Hooray! :)
+      # First separate the path from the arguments. This will split at the first
+      # space.
+      complete="$BUILD_STRIP"
+      path="${complete%% *}"
+      tmp="$complete EOL"
+      arguments="${tmp#* }"
+
+      # Cannot rely on the command "which" here since it doesn't always work.
+      is_absolute_path=`$ECHO "$path" | $GREP ^/`
+      if test -z "$is_absolute_path"; then
+        # Path to executable is not absolute. Find it.
+        IFS_save="$IFS"
+        IFS=:
+        for p in $PATH; do
+          if test -f "$p/$path" && test -x "$p/$path"; then
+            new_path="$p/$path"
+            break
+          fi
+        done
+        IFS="$IFS_save"
+      else
+        # This is an absolute path, we can use it without further modifications.
+        new_path="$path"
+      fi
+
+      if test "x$new_path" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of BUILD_STRIP, which resolves as \"$complete\", is not found." >&6;}
+        has_space=`$ECHO "$complete" | $GREP " "`
+        if test "x$has_space" != x; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5
+$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;}
+        fi
+        as_fn_error $? "Cannot locate the the path of BUILD_STRIP" "$LINENO" 5
+      fi
+    fi
+
+    # Now join together the path and the arguments once again
+    if test "x$arguments" != xEOL; then
+      new_complete="$new_path ${arguments% *}"
+    else
+      new_complete="$new_path"
+    fi
+
+    if test "x$complete" != "x$new_complete"; then
+      BUILD_STRIP="$new_complete"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_STRIP to \"$new_complete\"" >&5
+$as_echo "$as_me: Rewriting BUILD_STRIP to \"$new_complete\"" >&6;}
+    fi
+  fi
+
     # Assume the C compiler is the assembler
     BUILD_AS="$BUILD_CC -c"
     # Just like for the target compiler, use the compiler as linker
@@ -44530,6 +46092,8 @@
     BUILD_LDCXX="$LDCXX"
     BUILD_NM="$NM"
     BUILD_AS="$AS"
+    BUILD_OBJCOPY="$OBJCOPY"
+    BUILD_STRIP="$STRIP"
     BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
     BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
     BUILD_AR="$AR"
@@ -46684,9 +48248,6 @@
       ;;
   esac
 
-  # Setup LP64
-  COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $ADD_LP64"
-
   # Set some common defines. These works for all compilers, but assume
   # -D is universally accepted.
 
@@ -46717,7 +48278,12 @@
   COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE"
 
   # Setup target CPU
-  COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
+  OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $ADD_LP64 \
+      -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
+  OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $OPENJDK_BUILD_ADD_LP64 \
+      -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY"
 
   # Setup debug/release defines
   if test "x$DEBUG_LEVEL" = xrelease; then
@@ -46761,12 +48327,30 @@
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
 
   # The shared libraries are compiled using the picflag.
-  CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
-  CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
+  CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
+  CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
 
   # Executable flags
-  CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK"
-  CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK"
+  CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CFLAGS_JDK $EXTRA_CFLAGS_JDK"
+  CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
+      $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK"
+
+  # The corresponding flags for building for the build platform. This is still an
+  # approximation, we only need something that runs on this machine when cross
+  # compiling the product.
+  OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $PICFLAG $CFLAGS_JDKLIB_EXTRA"
+  OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
+      $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
+  OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
+  OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
+
+
+
+
 
 
 
@@ -46867,6 +48451,9 @@
     LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
   fi
 
+  OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}"
+  LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}"
+
   # Customize LDFLAGS for libs
   LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
 
@@ -46877,28 +48464,37 @@
     JDKLIB_LIBS=""
   else
     LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
-        -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
+        -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)"
 
     # On some platforms (mac) the linker warns about non existing -L dirs.
     # Add server first if available. Linking aginst client does not always produce the same results.
     # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1.
     # Default to server for other variants.
     if test "x$JVM_VARIANT_SERVER" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
     elif test "x$JVM_VARIANT_CLIENT" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/client"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client"
     elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/minimal"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal"
     else
-      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
+      LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
     fi
 
     JDKLIB_LIBS="-ljava -ljvm"
     if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
       JDKLIB_LIBS="$JDKLIB_LIBS -lc"
     fi
+
+    # When building a buildjdk, it's always only the server variant
+    OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \
+        -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
   fi
 
+  OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}"
+  LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}"
+
+
+
 
 
 
@@ -47503,6 +49099,7 @@
 
 
 
+
 # Setup debug symbols (need objcopy from the toolchain for that)
 
   #
@@ -61205,6 +62802,7 @@
     "$OUTPUT_ROOT/spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in" ;;
     "$OUTPUT_ROOT/hotspot-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in" ;;
     "$OUTPUT_ROOT/bootcycle-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in" ;;
+    "$OUTPUT_ROOT/buildjdk-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in" ;;
     "$OUTPUT_ROOT/compare.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in" ;;
     "$OUTPUT_ROOT/Makefile") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in" ;;
 
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index a5b403b..3c677d8 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -405,3 +405,31 @@
 
   AC_SUBST(STATIC_BUILD)
 ])
+
+################################################################################
+#
+# jlink options. 
+# We always keep packaged modules in JDK image.
+#
+AC_DEFUN_ONCE([JDKOPT_SETUP_JLINK_OPTIONS],
+[
+  AC_ARG_ENABLE([keep-packaged-modules], [AS_HELP_STRING([--disable-keep-packaged-modules],
+    [Do not keep packaged modules in jdk image @<:@enable@:>@])])
+
+  if test "x$enable_keep_packaged_modules" = "xyes"; then
+    AC_MSG_CHECKING([if packaged modules are kept])
+    AC_MSG_RESULT([yes])
+    JLINK_KEEP_PACKAGED_MODULES=true
+  elif test "x$enable_keep_packaged_modules" = "xno"; then
+    AC_MSG_CHECKING([if packaged modules are kept])
+    AC_MSG_RESULT([no])
+    JLINK_KEEP_PACKAGED_MODULES=false
+  elif test "x$enable_keep_packaged_modules" = "x"; then
+    AC_MSG_RESULT([yes (default)])
+    JLINK_KEEP_PACKAGED_MODULES=true
+  else
+    AC_MSG_ERROR([--enable-keep-packaged-modules accepts no argument])
+  fi
+
+  AC_SUBST(JLINK_KEEP_PACKAGED_MODULES)
+])
diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4
index 7553dfe..fe5a201 100644
--- a/common/autoconf/platform.m4
+++ b/common/autoconf/platform.m4
@@ -304,6 +304,37 @@
   fi
   AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR)
 
+  # Now do the same for OPENJDK_BUILD_CPU...
+  # Also store the legacy naming of the cpu.
+  # Ie i586 and amd64 instead of x86 and x86_64
+  OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_LEGACY="i586"
+  elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    # On all platforms except MacOSX replace x86_64 with amd64.
+    OPENJDK_BUILD_CPU_LEGACY="amd64"
+  fi
+  AC_SUBST(OPENJDK_BUILD_CPU_LEGACY)
+
+  # And the second legacy naming of the cpu.
+  # Ie i386 and amd64 instead of x86 and x86_64.
+  OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_LEGACY_LIB="i386"
+  elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    OPENJDK_BUILD_CPU_LEGACY_LIB="amd64"
+  fi
+  AC_SUBST(OPENJDK_BUILD_CPU_LEGACY_LIB)
+
+  # This is the name of the cpu (but using i386 and amd64 instead of
+  # x86 and x86_64, respectively), preceeded by a /, to be used when
+  # locating libraries. On macosx, it's empty, though.
+  OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB"
+  if test "x$OPENJDK_BUILD_OS" = xmacosx; then
+    OPENJDK_BUILD_CPU_LIBDIR=""
+  fi
+  AC_SUBST(OPENJDK_BUILD_CPU_LIBDIR)
+
   # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to
   # /amd64 or /sparcv9. This string is appended to some library paths, like this:
   # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so
@@ -346,6 +377,24 @@
   fi
   AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS)
 
+  OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU"
+  if test "x$OPENJDK_BUILD_CPU" = xx86; then
+    OPENJDK_BUILD_CPU_JLI="i386"
+  elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
+    # On all platforms except macosx, we replace x86_64 with amd64.
+    OPENJDK_BUILD_CPU_JLI="amd64"
+  fi
+  # Now setup the -D flags for building libjli.
+  OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'"
+  if test "x$OPENJDK_BUILD_OS" = xsolaris; then
+    if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then
+      OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'"
+    elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then
+      OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'"
+    fi
+  fi
+  AC_SUBST(OPENJDK_BUILD_CPU_JLI_CFLAGS)
+
   if test "x$OPENJDK_TARGET_OS" = xmacosx; then
       OPENJDK_TARGET_OS_EXPORT_DIR=macosx
   else
@@ -362,6 +411,11 @@
     fi
   fi
   AC_SUBST(LP64,$A_LP64)
+  if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then
+    if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then
+      OPENJDK_BUILD_ADD_LP64="-D_LP64=1"
+    fi
+  fi
 
   if test "x$COMPILE_TYPE" = "xcross"; then
     # FIXME: ... or should this include reduced builds..?
diff --git a/common/autoconf/source-dirs.m4 b/common/autoconf/source-dirs.m4
index 56f95dc..fa2f74d 100644
--- a/common/autoconf/source-dirs.m4
+++ b/common/autoconf/source-dirs.m4
@@ -84,3 +84,56 @@
 
   JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
 ])
+
+################################################################################
+# Define a mechanism for importing extra prebuilt modules
+#
+
+AC_DEFUN_ONCE([SRCDIRS_SETUP_IMPORT_MODULES],
+[
+  AC_ARG_WITH(import-modules, [AS_HELP_STRING([--with-import-modules],
+      [import a set of prebuilt modules either as a zip file or an exploded directory])])
+
+  if test "x$with_import_modules" != x \
+      && test "x$with_import_modules" != "xno"; then
+    if test -d "$with_import_modules"; then
+      IMPORT_MODULES_TOPDIR="$with_import_modules"
+      BASIC_FIXUP_PATH([IMPORT_MODULES_TOPDIR])
+    elif test -e "$with_import_modules"; then
+      IMPORT_MODULES_TOPDIR="$CONFIGURESUPPORT_OUTPUTDIR/import-modules"
+      $RM -rf "$IMPORT_MODULES_TOPDIR"
+      $MKDIR -p "$IMPORT_MODULES_TOPDIR"
+      if ! $UNZIP -q "$with_import_modules" -d "$IMPORT_MODULES_TOPDIR"; then
+        AC_MSG_ERROR([--with-import-modules="$with_import_modules" must point to a dir or a zip file])
+      fi
+    else
+      AC_MSG_ERROR([--with-import-modules="$with_import_modules" must point to a dir or a zip file])
+    fi
+  fi
+
+  if test -d "$IMPORT_MODULES_TOPDIR/modules"; then
+    IMPORT_MODULES_CLASSES="$IMPORT_MODULES_TOPDIR/modules"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_cmds"; then
+    IMPORT_MODULES_CMDS="$IMPORT_MODULES_TOPDIR/modules_cmds"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_libs"; then
+    IMPORT_MODULES_LIBS="$IMPORT_MODULES_TOPDIR/modules_libs"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_conf"; then
+    IMPORT_MODULES_CONF="$IMPORT_MODULES_TOPDIR/modules_conf"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
+    IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
+  fi
+  if test -d "$IMPORT_MODULES_TOPDIR/make"; then
+    IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
+  fi
+
+  AC_SUBST(IMPORT_MODULES_CLASSES)
+  AC_SUBST(IMPORT_MODULES_CMDS)
+  AC_SUBST(IMPORT_MODULES_LIBS)
+  AC_SUBST(IMPORT_MODULES_CONF)
+  AC_SUBST(IMPORT_MODULES_SRC)
+  AC_SUBST(IMPORT_MODULES_MAKE)
+])
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index d8322eb..66374c8 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -130,6 +130,14 @@
 JAXWS_TOPDIR:=@JAXWS_TOPDIR@
 HOTSPOT_TOPDIR:=@HOTSPOT_TOPDIR@
 NASHORN_TOPDIR:=@NASHORN_TOPDIR@
+
+IMPORT_MODULES_CLASSES:=@IMPORT_MODULES_CLASSES@
+IMPORT_MODULES_CMDS:=@IMPORT_MODULES_CMDS@
+IMPORT_MODULES_LIBS:=@IMPORT_MODULES_LIBS@
+IMPORT_MODULES_CONF:=@IMPORT_MODULES_CONF@
+IMPORT_MODULES_SRC:=@IMPORT_MODULES_SRC@
+IMPORT_MODULES_MAKE:=@IMPORT_MODULES_MAKE@
+
 COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
 
 # New (JEP-223) version information
@@ -246,6 +254,7 @@
 MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
 # This does not get overridden in a bootcycle build
 CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
+BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
 
 HOTSPOT_DIST=@HOTSPOT_DIST@
 
@@ -255,6 +264,9 @@
 # it in sync.
 BOOT_JDK:=@BOOT_JDK@
 
+BUILD_JDK:=@BUILD_JDK@
+CREATE_BUILDJDK:=@CREATE_BUILDJDK@
+
 # When compiling Java source to be run by the boot jdk
 # use these extra flags, eg -source 6 -target 6
 BOOT_JDK_SOURCETARGET:=@BOOT_JDK_SOURCETARGET@
@@ -405,6 +417,8 @@
 BUILD_AS:=@FIXPATH@ @BUILD_AS@
 BUILD_AR:=@FIXPATH@ @BUILD_AR@
 BUILD_NM:=@FIXPATH@ @BUILD_NM@
+BUILD_OBJCOPY:=@BUILD_OBJCOPY@
+BUILD_STRIP:=@BUILD_STRIP@
 BUILD_SYSROOT_CFLAGS:=@BUILD_SYSROOT_CFLAGS@
 BUILD_SYSROOT_LDFLAGS:=@BUILD_SYSROOT_LDFLAGS@
 
@@ -502,12 +516,40 @@
 # overriding that value by using ?=.
 JAVAC_FLAGS?=@JAVAC_FLAGS@
 
+
+BUILD_JAVA_FLAGS:=-Xms64M -Xmx1100M
+BUILD_JAVA=@FIXPATH@ $(BUILD_JDK)/bin/java $(BUILD_JAVA_FLAGS)
+
+# Use ?= as this can be overridden from bootcycle-spec.gmk
+BOOT_JDK_MODULAR ?= @BOOT_JDK_MODULAR@
+
+ifeq ($(BOOT_JDK_MODULAR), true)
+  INTERIM_OVERRIDE_MODULES_ARGS = -Xpatch:$(BUILDTOOLS_OUTPUTDIR)/override_modules
+  INTERIM_LANGTOOLS_ARGS = $(INTERIM_OVERRIDE_MODULES_ARGS)
+  JAVAC_MAIN_CLASS = -m jdk.compiler/com.sun.tools.javac.Main
+  JAVADOC_MAIN_CLASS = -m jdk.javadoc/jdk.javadoc.internal.tool.Main
+else
+  INTERIM_OVERRIDE_MODULES := java.compiler jdk.compiler \
+      jdk.jdeps jdk.javadoc jdk.rmic
+  INTERIM_OVERRIDE_MODULES_ARGS = \
+      -Xbootclasspath/p:$(call PathList, \
+          $(addprefix $(BUILDTOOLS_OUTPUTDIR)/override_modules/, \
+              $(INTERIM_OVERRIDE_MODULES)))
+  INTERIM_LANGTOOLS_ARGS = $(INTERIM_OVERRIDE_MODULES_ARGS) \
+      -cp $(BUILDTOOLS_OUTPUTDIR)/override_modules/jdk.compiler
+  JAVAC_MAIN_CLASS = com.sun.tools.javac.Main
+  JAVADOC_MAIN_CLASS = jdk.javadoc.internal.tool.Main
+endif
 # You run the new javac using the boot jdk with $(BOOT_JDK)/bin/java $(NEW_JAVAC) ...
 # Use = assignment to be able to override in bootcycle-spec.gmk
-INTERIM_LANGTOOLS_JAR = $(BUILDTOOLS_OUTPUTDIR)/interim_langtools.jar
-INTERIM_LANGTOOLS_ARGS = "-Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR)" -cp $(INTERIM_LANGTOOLS_JAR)
-NEW_JAVAC   = $(INTERIM_LANGTOOLS_ARGS) com.sun.tools.javac.Main
-NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) jdk.javadoc.internal.tool.Main
+NEW_JAVAC   = $(INTERIM_LANGTOOLS_ARGS) $(JAVAC_MAIN_CLASS)
+NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) $(JAVADOC_MAIN_CLASS)
+
+# JLink/Jmod are run using the BUILD_JDK, which is normally the jdk output dir.
+JLINK_KEEP_PACKAGED_MODULES:=@JLINK_KEEP_PACKAGED_MODULES@
+
+JLINK = @FIXPATH@ $(BUILD_JDK)/bin/jlink $(JAVA_TOOL_FLAGS_SMALL)
+JMOD = @FIXPATH@ $(BUILD_JDK)/bin/jmod $(JAVA_TOOL_FLAGS_SMALL)
 
 # Base flags for RC
 # Guarding this against resetting value. Legacy make files include spec multiple
diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4
index 5e26fd1..07a6f83 100644
--- a/common/autoconf/toolchain.m4
+++ b/common/autoconf/toolchain.m4
@@ -797,6 +797,10 @@
     BASIC_FIXUP_EXECUTABLE(BUILD_NM)
     BASIC_PATH_PROGS(BUILD_AR, ar gcc-ar)
     BASIC_FIXUP_EXECUTABLE(BUILD_AR)
+    BASIC_PATH_PROGS(BUILD_OBJCOPY, objcopy)
+    BASIC_FIXUP_EXECUTABLE(BUILD_OBJCOPY)
+    BASIC_PATH_PROGS(BUILD_STRIP, strip)
+    BASIC_FIXUP_EXECUTABLE(BUILD_STRIP)
     # Assume the C compiler is the assembler
     BUILD_AS="$BUILD_CC -c"
     # Just like for the target compiler, use the compiler as linker
@@ -813,6 +817,8 @@
     BUILD_LDCXX="$LDCXX"
     BUILD_NM="$NM"
     BUILD_AS="$AS"
+    BUILD_OBJCOPY="$OBJCOPY"
+    BUILD_STRIP="$STRIP"
     BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
     BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
     BUILD_AR="$AR"
diff --git a/common/bin/compare.sh b/common/bin/compare.sh
index a629ae0..d073fbb 100644
--- a/common/bin/compare.sh
+++ b/common/bin/compare.sh
@@ -290,9 +290,9 @@
 
     GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" \
         ! -name "*.zip" ! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" \
-        ! -name "*.jimage" ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
+        ! -name "modules" ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
         ! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
-        ! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
+        ! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" ! -name "*.jmod" \
         ! -name "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" \
         ! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \
         ! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \
@@ -389,13 +389,13 @@
     $RM -rf $THIS_UNZIPDIR $OTHER_UNZIPDIR
     $MKDIR -p $THIS_UNZIPDIR
     $MKDIR -p $OTHER_UNZIPDIR
-    if [ "$TYPE" = "jimage" ]
+    if [ "$TYPE" = "jar" || "$TYPE" = "war" || "$TYPE" = "zip" || "$TYPE" = "jmod"]
     then
-        (cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
-        (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
-    else
         (cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP)
         (cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP)
+    else
+        (cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
+        (cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
     fi
 
     # Find all archives inside and unzip them as well to compare the contents rather than
@@ -526,7 +526,7 @@
 
     # TODO filter?
     ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.jar" -o -name "*.war" \
-        -o -name "*.jimage" | $SORT | $FILTER)
+        -o -name "modules" -o -name "*.jmod" | $SORT | $FILTER)
 
     if [ -n "$ZIPS" ]; then
         echo Jar files...
diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js
index 48519cf..27fbe1f 100644
--- a/common/conf/jib-profiles.js
+++ b/common/conf/jib-profiles.js
@@ -421,10 +421,10 @@
 
         jtreg: {
             server: "javare",
-            revision: "4.1",
-            build_number: "b12",
+            revision: "4.2",
+            build_number: "b01",
             checksum_file: "MD5_VALUES",
-            file: "jtreg_bin-4.1.zip",
+            file: "jtreg_bin-4.2.zip",
             environment_name: "JT_HOME"
         },
 
diff --git a/corba/.hgtags b/corba/.hgtags
index 5c2b765..9c059fc 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -352,3 +352,4 @@
 49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
 84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108
 b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109
+9666775734fb6028ee86df9972626b3667b6a318 jdk-9+110
diff --git a/corba/make/gensrc/Gensrc-java.corba.gmk b/corba/make/gensrc/Gensrc-java.corba.gmk
index 608267e..2d18690 100644
--- a/corba/make/gensrc/Gensrc-java.corba.gmk
+++ b/corba/make/gensrc/Gensrc-java.corba.gmk
@@ -47,7 +47,7 @@
     BIN := $(BUILDTOOLS_OUTPUTDIR)/idlj_classes, \
     COPY := .prp, \
     INCLUDES := com/sun/tools/corba/se/idl, \
-    EXCLUDE_FILES := ResourceBundleUtil.java))
+    EXCLUDE_FILES := ResourceBundleUtil.java module-info.java))
 
 # Force the language to english for predictable source code generation.
 TOOL_IDLJ_CMD := $(JAVA) -cp $(BUILDTOOLS_OUTPUTDIR)/idlj_classes \
diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java
new file mode 100644
index 0000000..23da4b7
--- /dev/null
+++ b/corba/src/java.corba/share/classes/module-info.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.corba {
+    requires public java.desktop;
+    requires public java.rmi;
+    requires java.logging;
+    requires java.naming;
+    requires java.transaction;
+
+    exports javax.activity;
+    exports javax.rmi;
+    exports javax.rmi.CORBA;
+    exports org.omg.CORBA;
+    exports org.omg.CORBA.DynAnyPackage;
+    exports org.omg.CORBA.ORBPackage;
+    exports org.omg.CORBA.TypeCodePackage;
+    exports org.omg.CORBA.portable;
+    exports org.omg.CORBA_2_3;
+    exports org.omg.CORBA_2_3.portable;
+    exports org.omg.CosNaming;
+    exports org.omg.CosNaming.NamingContextExtPackage;
+    exports org.omg.CosNaming.NamingContextPackage;
+    exports org.omg.Dynamic;
+    exports org.omg.DynamicAny;
+    exports org.omg.DynamicAny.DynAnyFactoryPackage;
+    exports org.omg.DynamicAny.DynAnyPackage;
+    exports org.omg.IOP;
+    exports org.omg.IOP.CodecFactoryPackage;
+    exports org.omg.IOP.CodecPackage;
+    exports org.omg.Messaging;
+    exports org.omg.PortableInterceptor;
+    exports org.omg.PortableInterceptor.ORBInitInfoPackage;
+    exports org.omg.PortableServer;
+    exports org.omg.PortableServer.CurrentPackage;
+    exports org.omg.PortableServer.POAManagerPackage;
+    exports org.omg.PortableServer.POAPackage;
+    exports org.omg.PortableServer.ServantLocatorPackage;
+    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;
+
+    provides javax.naming.spi.InitialContextFactory
+        with com.sun.jndi.cosnaming.CNCtxFactory;
+}
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index cbe0b71..e1c8a7d 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -512,3 +512,4 @@
 c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
 934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108
 7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109
+2f5d1578b24060ea06bd1f340a124db95d1475b2 jdk-9+110
diff --git a/hotspot/make/share/makefiles/mapfile-vers b/hotspot/make/share/makefiles/mapfile-vers
index 28338d0..120103a 100644
--- a/hotspot/make/share/makefiles/mapfile-vers
+++ b/hotspot/make/share/makefiles/mapfile-vers
@@ -168,3 +168,15 @@
                 JVM_TotalMemory;
                 JVM_UnloadLibrary;
                 JVM_Yield;
+
+                # Module related API's
+                JVM_AddModuleExports;
+                JVM_AddModuleExportsToAll;
+                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 bced741..95c6bf2 100644
--- a/hotspot/make/test/JtregNative.gmk
+++ b/hotspot/make/test/JtregNative.gmk
@@ -45,6 +45,7 @@
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
+    $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
     $(HOTSPOT_TOPDIR)/test/runtime/SameObject \
     $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
     $(HOTSPOT_TOPDIR)/test/compiler/calls \
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/module-info.java b/hotspot/src/jdk.hotspot.agent/share/classes/module-info.java
new file mode 100644
index 0000000..85b163b
--- /dev/null
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/module-info.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.hotspot.agent {
+    requires java.datatransfer;
+    requires java.desktop;
+    requires java.rmi;
+    requires java.scripting;
+    requires jdk.jcmd;
+    requires jdk.jdi;
+
+    // RMI needs to serialize types in this package
+    exports sun.jvm.hotspot.debugger.remote to java.rmi;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SACoreAttachingConnector;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SADebugServerAttachingConnector;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SAPIDAttachingConnector;
+
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JStack;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JInfo;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ClassLoaderStats;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.FinalizerInfo;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapDumper;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapSummary;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ObjectHistogram;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.PMap;
+}
+
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java
index a5fac51..34f5bfb 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java
@@ -31,14 +31,14 @@
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.tools.*;
 import sun.jvm.hotspot.utilities.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
 /**
   A command line tool to print class loader statistics.
 */
 
-public class ClassLoaderStats extends Tool {
+public class ClassLoaderStats extends Tool implements ToolProvider {
    boolean verbose = true;
 
    public ClassLoaderStats() {
@@ -49,6 +49,16 @@
       super(d);
    }
 
+   @Override
+   public String getName() {
+      return "classLoaderStats";
+   }
+
+   @Override
+   public void run(String... arguments) {
+      execute(arguments);
+   }
+
    public static void main(String[] args) {
       ClassLoaderStats cls = new ClassLoaderStats();
       cls.execute(args);
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java
index 58819a0..9da8e52 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java
@@ -25,24 +25,21 @@
 package sun.jvm.hotspot.tools;
 
 import sun.jvm.hotspot.debugger.JVMDebugger;
-import sun.jvm.hotspot.tools.*;
 
 import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
-import sun.jvm.hotspot.utilities.ObjectReader;
-import sun.jvm.hotspot.utilities.MarkBits;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 
 /*
  * Iterates over the queue of object pending finalization and prints a
  * summary of these objects in the form of a histogram.
  */
-public class FinalizerInfo extends Tool {
+public class FinalizerInfo extends Tool implements ToolProvider {
 
     public FinalizerInfo() {
         super();
@@ -52,6 +49,16 @@
         super(d);
     }
 
+    @Override
+    public String getName() {
+        return "finalizerInfo";
+    }
+
+    @Override
+    public void run(String... arguments) {
+        execute(arguments);
+    }
+
     public static void main(String[] args) {
         FinalizerInfo finfo = new FinalizerInfo();
         finfo.execute(args);
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java
index 1b93504..d0a11ab 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java
@@ -26,6 +26,8 @@
 
 import sun.jvm.hotspot.utilities.HeapHprofBinWriter;
 import sun.jvm.hotspot.debugger.JVMDebugger;
+import jdk.internal.vm.agent.spi.ToolProvider;
+
 import java.io.IOException;
 
 /*
@@ -33,12 +35,16 @@
  * process/core as a HPROF binary file. It can also be used as a standalone
  * tool if required.
  */
-public class HeapDumper extends Tool {
+public class HeapDumper extends Tool implements ToolProvider {
 
     private static String DEFAULT_DUMP_FILE = "heap.bin";
 
     private String dumpFile;
 
+    public HeapDumper() {
+        this.dumpFile = DEFAULT_DUMP_FILE;
+    }
+
     public HeapDumper(String dumpFile) {
         this.dumpFile = dumpFile;
     }
@@ -48,6 +54,11 @@
         this.dumpFile = dumpFile;
     }
 
+    @Override
+    public String getName() {
+        return "heapDumper";
+    }
+
     protected void printFlagsUsage() {
         System.out.println("    <no option>\tto dump heap to " +
             DEFAULT_DUMP_FILE);
@@ -69,18 +80,22 @@
     // JDK jmap utility will always invoke this tool as:
     //   HeapDumper -f <file> <args...>
     public static void main(String args[]) {
-        String file = DEFAULT_DUMP_FILE;
+        HeapDumper dumper = new HeapDumper();
+        dumper.run(args);
+    }
+
+    @Override
+    public void run(String... args) {
         if (args.length > 2) {
             if (args[0].equals("-f")) {
-                file = args[1];
+                this.dumpFile = args[1];
                 String[] newargs = new String[args.length-2];
                 System.arraycopy(args, 2, newargs, 0, args.length-2);
                 args = newargs;
             }
         }
 
-        HeapDumper dumper = new HeapDumper(file);
-        dumper.execute(args);
+        execute(args);
     }
 
 }
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
index 6012830..5c1012b 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
@@ -33,8 +33,9 @@
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class HeapSummary extends Tool {
+public class HeapSummary extends Tool implements ToolProvider {
 
    public HeapSummary() {
       super();
@@ -49,6 +50,16 @@
       hs.execute(args);
    }
 
+   @Override
+   public String getName() {
+      return "heapSummary";
+   }
+
+   @Override
+   public void run(String... arguments) {
+      execute(arguments);
+   }
+
    public void run() {
       CollectedHeap heap = VM.getVM().getUniverse().heap();
       VM.Flag[] flags = VM.getVM().getCommandLineFlags();
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java
index 7469de2..50f9c30 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java
@@ -27,8 +27,9 @@
 import sun.jvm.hotspot.debugger.JVMDebugger;
 import sun.jvm.hotspot.runtime.Arguments;
 import sun.jvm.hotspot.runtime.VM;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class JInfo extends Tool {
+public class JInfo extends Tool implements ToolProvider {
     public JInfo() {
         super();
     }
@@ -94,13 +95,14 @@
         tool.run();
     }
 
-    public static void main(String[] args) {
+    @Override
+    public void run(String... args) {
         int mode = -1;
         switch (args.length) {
         case 1:
             if (args[0].charAt(0) == '-') {
                 // -h or -help or some invalid flag
-                new JInfo(mode).usage();
+                usage();
             } else {
                 mode = MODE_BOTH;
             }
@@ -114,7 +116,7 @@
                 mode = MODE_SYSPROPS;
             } else if (modeFlag.charAt(0) == '-') {
                 // -h or -help or some invalid flag
-                new JInfo(mode).usage();
+                usage();
             } else {
                 mode = MODE_BOTH;
             }
@@ -131,11 +133,16 @@
         }
 
         default:
-            new JInfo(mode).usage();
+            usage();
         }
 
-        JInfo jinfo = new JInfo(mode);
-        jinfo.execute(args);
+        this.mode = mode;
+        execute(args);
+    }
+
+    public static void main(String[] args) {
+        JInfo jinfo = new JInfo();
+        jinfo.run(args);
     }
 
     private void printVMFlags() {
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java
index b8609bc..821ed38 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java
@@ -25,8 +25,9 @@
 package sun.jvm.hotspot.tools;
 
 import sun.jvm.hotspot.debugger.JVMDebugger;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class JStack extends Tool {
+public class JStack extends Tool implements ToolProvider {
     public JStack(boolean mixedMode, boolean concurrentLocks) {
         this.mixedMode = mixedMode;
         this.concurrentLocks = concurrentLocks;
@@ -66,9 +67,8 @@
         tool.run();
     }
 
-    public static void main(String[] args) {
-        boolean mixedMode = false;
-        boolean concurrentLocks = false;
+    @Override
+    public void run(String... args) {
         int used = 0;
         for (int i = 0; i < args.length; i++) {
             if (args[i].equals("-m")) {
@@ -88,8 +88,12 @@
             args = newArgs;
         }
 
-        JStack jstack = new JStack(mixedMode, concurrentLocks);
-        jstack.execute(args);
+        execute(args);
+    }
+
+    public static void main(String[] args) {
+        JStack jstack = new JStack();
+        jstack.run(args);
     }
 
     private boolean mixedMode;
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java
index ddedcae..0dc100e 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java
@@ -27,11 +27,13 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
+
 import java.io.PrintStream;
 
 /** A sample tool which uses the Serviceability Agent's APIs to obtain
     an object histogram from a remote or crashed VM. */
-public class ObjectHistogram extends Tool {
+public class ObjectHistogram extends Tool implements ToolProvider {
 
     public ObjectHistogram() {
        super();
@@ -41,6 +43,16 @@
        super(d);
     }
 
+    @Override
+    public String getName() {
+       return "objectHistogram";
+    }
+
+    @Override
+    public void run(String... arguments) {
+        execute(arguments);
+    }
+
    public void run() {
       run(System.out, System.err);
    }
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java
index 43bcd59..0c0ccbf 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java
@@ -28,9 +28,9 @@
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class PMap extends Tool {
+public class PMap extends Tool implements ToolProvider {
 
    public PMap() {
        super();
@@ -40,6 +40,16 @@
        super(d);
    }
 
+   @Override
+   public String getName() {
+       return "pmap";
+   }
+
+   @Override
+   public void run(String... arguments) {
+       execute(arguments);
+   }
+
    public void run() {
       run(System.out);
    }
diff --git a/hotspot/src/jdk.vm.ci/share/classes/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory b/hotspot/src/jdk.vm.ci/share/classes/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory
deleted file mode 100644
index fe3a457..0000000
--- a/hotspot/src/jdk.vm.ci/share/classes/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory
+++ /dev/null
@@ -1,3 +0,0 @@
-jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory
-jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory
-jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory
diff --git a/hotspot/src/jdk.vm.ci/share/classes/module-info.java b/hotspot/src/jdk.vm.ci/share/classes/module-info.java
new file mode 100644
index 0000000..a59a37d
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.vm.ci {
+    uses jdk.vm.ci.hotspot.HotSpotVMEventListener;
+    uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+    uses jdk.vm.ci.runtime.JVMCICompilerFactory;
+
+    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.sparc.SPARCHotSpotJVMCIBackendFactory;
+}
diff --git a/hotspot/src/os/posix/dtrace/hotspot_jni.d b/hotspot/src/os/posix/dtrace/hotspot_jni.d
index cca1c51..eb95b7e 100644
--- a/hotspot/src/os/posix/dtrace/hotspot_jni.d
+++ b/hotspot/src/os/posix/dtrace/hotspot_jni.d
@@ -300,6 +300,8 @@
   probe GetLongField__return(uintptr_t);
   probe GetMethodID__entry(void*, void*, const char*, const char*);
   probe GetMethodID__return(uintptr_t);
+  probe GetModule__entry(void*, void*);
+  probe GetModule__return(void*);
   probe GetObjectArrayElement__entry(void*, void*, uintptr_t);
   probe GetObjectArrayElement__return(void*);
   probe GetObjectClass__entry(void*, void*);
diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp
index 92c7215..12b58ad 100644
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp
@@ -661,7 +661,7 @@
   NOT_PRODUCT(_throw_class_cast_exception_count++;)
   ResourceMark rm(thread);
   char* message = SharedRuntime::generate_class_cast_message(
-    thread, object->klass()->external_name());
+    thread, object->klass());
   SharedRuntime::throw_and_post_jvmti_exception(
     thread, vmSymbols::java_lang_ClassCastException(), message);
 JRT_END
diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp
index 2775c67..21e952e 100644
--- a/hotspot/src/share/vm/ci/ciEnv.cpp
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp
@@ -370,9 +370,9 @@
     resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
   }
   if (resolved_klass->is_instance_klass()) {
-    return Reflection::verify_class_access(accessing_klass->get_Klass(),
-                                           resolved_klass,
-                                           true);
+    return (Reflection::verify_class_access(accessing_klass->get_Klass(),
+                                            resolved_klass,
+                                            true) == Reflection::ACCESS_OK);
   }
   return true;
 }
diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
index 97d6bdf..3be9d2f 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/defaultMethods.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verificationType.hpp"
@@ -103,8 +104,6 @@
 
 #define JAVA_9_VERSION                    53
 
-enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
-
 void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
                                                   ConstantPool* cp,
                                                   const int length,
@@ -1965,7 +1964,7 @@
   const vmSymbols::SID sid = vmSymbols::find_sid(name);
   // Privileged code can use all annotations.  Other code silently drops some.
   const bool privileged = loader_data->is_the_null_class_loader_data() ||
-                          loader_data->is_ext_class_loader_data() ||
+                          loader_data->is_platform_class_loader_data() ||
                           loader_data->is_anonymous();
   switch (sid) {
     case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature): {
@@ -4358,17 +4357,29 @@
 static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
   assert(this_klass != NULL, "invariant");
   const Klass* const super = this_klass->super();
-  if ((super != NULL) &&
-      (!Reflection::verify_class_access(this_klass, super, false))) {
-    ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_IllegalAccessError(),
-      "class %s cannot access its superclass %s",
-      this_klass->external_name(),
-      super->external_name()
-    );
-    return;
+  if (super != NULL) {
+    Reflection::VerifyClassAccessResults vca_result =
+      Reflection::verify_class_access(this_klass, super, false);
+    if (vca_result != Reflection::ACCESS_OK) {
+      ResourceMark rm(THREAD);
+      char* msg =  Reflection::verify_class_access_msg(this_klass, super, vca_result);
+      if (msg == NULL) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "class %s cannot access its superclass %s",
+          this_klass->external_name(),
+          super->external_name());
+      } else {
+        // Add additional message content.
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "superclass access check failed: %s",
+          msg);
+      }
+    }
   }
 }
 
@@ -4380,16 +4391,26 @@
   for (int i = lng - 1; i >= 0; i--) {
     Klass* const k = local_interfaces->at(i);
     assert (k != NULL && k->is_interface(), "invalid interface");
-    if (!Reflection::verify_class_access(this_klass, k, false)) {
+    Reflection::VerifyClassAccessResults vca_result =
+      Reflection::verify_class_access(this_klass, k, false);
+    if (vca_result != Reflection::ACCESS_OK) {
       ResourceMark rm(THREAD);
-      Exceptions::fthrow(
-        THREAD_AND_LOCATION,
-        vmSymbols::java_lang_IllegalAccessError(),
-        "class %s cannot access its superinterface %s",
-        this_klass->external_name(),
-        k->external_name()
-      );
-      return;
+      char* msg =  Reflection::verify_class_access_msg(this_klass, k, vca_result);
+      if (msg == NULL) {
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "class %s cannot access its superinterface %s",
+          this_klass->external_name(),
+          k->external_name());
+      } else {
+        // Add additional message content.
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "superinterface check failed: %s",
+          msg);
+      }
     }
   }
 }
@@ -4489,12 +4510,14 @@
   const bool is_super      = (flags & JVM_ACC_SUPER)      != 0;
   const bool is_enum       = (flags & JVM_ACC_ENUM)       != 0;
   const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0;
+  const bool is_module_info= (flags & JVM_ACC_MODULE)     != 0;
   const bool major_gte_15  = _major_version >= JAVA_1_5_VERSION;
 
   if ((is_abstract && is_final) ||
       (is_interface && !is_abstract) ||
       (is_interface && major_gte_15 && (is_super || is_enum)) ||
-      (!is_interface && major_gte_15 && is_annotation)) {
+      (!is_interface && major_gte_15 && is_annotation) ||
+      is_module_info) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
@@ -4650,65 +4673,9 @@
                                         int length,
                                         TRAPS) const {
   assert(_need_verify, "only called when _need_verify is true");
-  int i = 0;
-  const int count = length >> 2;
-  for (int k=0; k<count; k++) {
-    unsigned char b0 = buffer[i];
-    unsigned char b1 = buffer[i+1];
-    unsigned char b2 = buffer[i+2];
-    unsigned char b3 = buffer[i+3];
-    // For an unsigned char v,
-    // (v | v - 1) is < 128 (highest bit 0) for 0 < v < 128;
-    // (v | v - 1) is >= 128 (highest bit 1) for v == 0 or v >= 128.
-    const unsigned char res = b0 | b0 - 1 |
-                              b1 | b1 - 1 |
-                              b2 | b2 - 1 |
-                              b3 | b3 - 1;
-    if (res >= 128) break;
-    i += 4;
+  if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) {
+    classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
   }
-  for(; i < length; i++) {
-    unsigned short c;
-    // no embedded zeros
-    guarantee_property((buffer[i] != 0), "Illegal UTF8 string in constant pool in class file %s", CHECK);
-    if(buffer[i] < 128) {
-      continue;
-    }
-    if ((i + 5) < length) { // see if it's legal supplementary character
-      if (UTF8::is_supplementary_character(&buffer[i])) {
-        c = UTF8::get_supplementary_character(&buffer[i]);
-        i += 5;
-        continue;
-      }
-    }
-    switch (buffer[i] >> 4) {
-      default: break;
-      case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-      case 0xC: case 0xD:  // 110xxxxx  10xxxxxx
-        c = (buffer[i] & 0x1F) << 6;
-        i++;
-        if ((i < length) && ((buffer[i] & 0xC0) == 0x80)) {
-          c += buffer[i] & 0x3F;
-          if (_major_version <= 47 || c == 0 || c >= 0x80) {
-            // for classes with major > 47, c must a null or a character in its shortest form
-            break;
-          }
-        }
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-      case 0xE:  // 1110xxxx 10xxxxxx 10xxxxxx
-        c = (buffer[i] & 0xF) << 12;
-        i += 2;
-        if ((i < length) && ((buffer[i-1] & 0xC0) == 0x80) && ((buffer[i] & 0xC0) == 0x80)) {
-          c += ((buffer[i-1] & 0x3F) << 6) + (buffer[i] & 0x3F);
-          if (_major_version <= 47 || c >= 0x800) {
-            // for classes with major > 47, c must be in its shortest form
-            break;
-          }
-        }
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-    }  // end of switch
-  } // end of for
 }
 
 // Unqualified names may not contain the characters '.', ';', '[', or '/'.
@@ -4716,24 +4683,35 @@
 // or <clinit>.  Note that method names may not be <init> or <clinit> in this
 // method.  Because these names have been checked as special cases before
 // calling this method in verify_legal_method_name.
-static bool verify_unqualified_name(const char* name,
-                                    unsigned int length,
-                                    int type) {
+//
+// This method is also called from the modular system APIs in modules.cpp
+// to verify the validity of module and package names.
+bool ClassFileParser::verify_unqualified_name(const char* name,
+                                              unsigned int length,
+                                              int type) {
   for (const char* p = name; p != name + length;) {
     jchar ch = *p;
     if (ch < 128) {
-      p++;
-      if (ch == '.' || ch == ';' || ch == '[') {
+      if (ch == '.') {
+        // permit '.' in module names unless it's the first char, or
+        // preceding char is also a '.', or last char is a '.'.
+        if ((type != ClassFileParser::LegalModule) ||
+          (p == name) || (*(p-1) == '.') ||
+          (p == name + length - 1)) {
+          return false;
+        }
+      }
+      if (ch == ';' || ch == '[' ) {
         return false;   // do not permit '.', ';', or '['
       }
-      if (type != LegalClass && ch == '/') {
+      if (type != ClassFileParser::LegalClass && ch == '/') {
         return false;   // do not permit '/' unless it's class name
       }
-      if (type == LegalMethod && (ch == '<' || ch == '>')) {
+      if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) {
         return false;   // do not permit '<' or '>' in method names
       }
-    }
-    else {
+      p++;
+    } else {
       char* tmp_p = UTF8::next(p, &ch);
       p = tmp_p;
     }
@@ -5192,7 +5170,7 @@
   }
 }
 
-InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
+InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) {
   if (_klass != NULL) {
     return _klass;
   }
@@ -5200,14 +5178,14 @@
   InstanceKlass* const ik =
     InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);
 
-  fill_instance_klass(ik, CHECK_NULL);
+  fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL);
 
   assert(_klass == ik, "invariant");
 
   return ik;
 }
 
-void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
+void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) {
   assert(ik != NULL, "invariant");
 
   set_klass_to_deallocate(ik);
@@ -5272,6 +5250,12 @@
     ik->set_host_klass(_host_klass);
   }
 
+  // Set PackageEntry for this_klass
+  oop cl = ik->class_loader();
+  Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl));
+  ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh());
+  ik->set_package(cld, CHECK);
+
   const Array<Method*>* const methods = ik->methods();
   assert(methods != NULL, "invariant");
   const int methods_len = methods->length();
@@ -5327,10 +5311,18 @@
     }
   }
 
+  // Obtain this_klass' module entry
+  ModuleEntry* module_entry = ik->module();
+  assert(module_entry != NULL, "module_entry should always be set");
+
+  // Obtain java.lang.reflect.Module
+  Handle module_handle(THREAD, JNIHandles::resolve(module_entry->module()));
+
   // Allocate mirror and initialize static fields
   // The create_mirror() call will also call compute_modifiers()
   java_lang_Class::create_mirror(ik,
                                  _loader_data->class_loader(),
+                                 module_handle,
                                  _protection_domain,
                                  CHECK);
 
@@ -5344,6 +5336,15 @@
                                              CHECK);
   }
 
+  // Add read edges to the unnamed modules of the bootstrap and app class loaders.
+  if (changed_by_loadhook && !module_handle.is_null() && module_entry->is_named() &&
+      !module_entry->has_default_read_edges()) {
+    if (!module_entry->set_has_default_read_edges()) {
+      // We won a potential race
+      JvmtiExport::add_default_read_edges(module_handle, THREAD);
+    }
+  }
+
   // Update the loader_data graph.
   record_defined_class_dependencies(ik, CHECK);
 
@@ -5351,11 +5352,24 @@
 
   if (!is_internal()) {
     if (log_is_enabled(Info, classload)) {
-      ik->print_loading_log(LogLevel::Info, _loader_data, _stream);
-    }
-    // No 'else' here as logging levels are not mutually exclusive
-    if (log_is_enabled(Debug, classload)) {
-      ik->print_loading_log(LogLevel::Debug, _loader_data, _stream);
+      ResourceMark rm;
+      const char* module_name = NULL;
+      static const size_t modules_image_name_len = strlen(MODULES_IMAGE_NAME);
+      size_t stream_len = strlen(_stream->source());
+      // See if _stream->source() ends in "modules"
+      if (module_entry->is_named() && modules_image_name_len < stream_len &&
+        (strncmp(_stream->source() + stream_len - modules_image_name_len,
+                 MODULES_IMAGE_NAME, modules_image_name_len) == 0)) {
+        module_name = module_entry->name()->as_C_string();
+      }
+
+      if (log_is_enabled(Info, classload)) {
+        ik->print_loading_log(LogLevel::Info, _loader_data, module_name, _stream);
+      }
+      // No 'else' here as logging levels are not mutually exclusive
+      if (log_is_enabled(Debug, classload)) {
+        ik->print_loading_log(LogLevel::Debug, _loader_data, module_name, _stream);
+      }
     }
 
     if (log_is_enabled(Info, classresolve))  {
diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp
index d6fd836..3ee99df 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp
@@ -73,6 +73,8 @@
     NOF_PUBLICITY_LEVELS
   };
 
+  enum { LegalClass, LegalField, LegalMethod, LegalModule }; // used to verify unqualified names
+
  private:
   const ClassFileStream* _stream; // Actual input stream
   const Symbol* _requested_name;
@@ -155,7 +157,7 @@
                                   ConstantPool* cp,
                                   TRAPS);
 
-  void fill_instance_klass(InstanceKlass* ik, TRAPS);
+  void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS);
   void set_klass(InstanceKlass* instance);
 
   void set_class_synthetic_flag(bool x)        { _synthetic_flag = x; }
@@ -482,7 +484,7 @@
 
   ~ClassFileParser();
 
-  InstanceKlass* create_instance_klass(TRAPS);
+  InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, TRAPS);
 
   const ClassFileStream* clone_stream() const;
 
@@ -512,6 +514,7 @@
 
   bool is_internal() const { return INTERNAL == _pub_level; }
 
+  static bool verify_unqualified_name(const char* name, unsigned int length, int type);
 };
 
 #endif // SHARE_VM_CLASSFILE_CLASSFILEPARSER_HPP
diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp
index 0a1e20d..d4196c3 100644
--- a/hotspot/src/share/vm/classfile/classLoader.cpp
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp
@@ -29,6 +29,9 @@
 #include "classfile/classLoaderExt.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/jimage.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/klassFactory.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -138,11 +141,14 @@
 ClassPathEntry* ClassLoader::_first_entry         = NULL;
 ClassPathEntry* ClassLoader::_last_entry          = NULL;
 int             ClassLoader::_num_entries         = 0;
-PackageHashtable* ClassLoader::_package_hash_table = NULL;
-
+ClassPathEntry* ClassLoader::_first_append_entry = NULL;
+bool            ClassLoader::_has_jimage = false;
 #if INCLUDE_CDS
+GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
+GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
 SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
 #endif
+
 // helper routines
 bool string_starts_with(const char* str, const char* str_to_find) {
   size_t str_len = strlen(str);
@@ -162,7 +168,7 @@
   return (const char*)version_string;
 }
 
-bool string_ends_with(const char* str, const char* str_to_find) {
+bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
   size_t str_len = strlen(str);
   size_t str_to_find_len = strlen(str_to_find);
   if (str_to_find_len > str_len) {
@@ -356,15 +362,49 @@
   if (location == 0) {
     char package[JIMAGE_MAX_PATH];
     name_to_package(name, package, JIMAGE_MAX_PATH);
+
+#if INCLUDE_CDS
+    if (package[0] == '\0' && DumpSharedSpaces) {
+      return NULL;
+    }
+#endif
     if (package[0] != '\0') {
-        const char* module = (*JImagePackageToModule)(_jimage, package);
-        if (module == NULL) {
-            module = "java.base";
+      if (!Universe::is_module_initialized()) {
+        location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
+#if INCLUDE_CDS
+        // CDS uses the boot class loader to load classes whose packages are in
+        // modules defined for other class loaders.  So, for now, get their module
+        // names from the "modules" jimage file.
+        if (DumpSharedSpaces && location == 0) {
+          const char* module_name = (*JImagePackageToModule)(_jimage, package);
+          if (module_name != NULL) {
+            location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
+          }
         }
-        location = (*JImageFindResource)(_jimage, module, get_jimage_version_string(), name, &size);
+#endif
+
+      } else {
+        // Get boot class loader's package entry table
+        PackageEntryTable* pkgEntryTable =
+          ClassLoaderData::the_null_class_loader_data()->packages();
+        // Get package's package entry
+        TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
+        PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
+
+        if (package_entry != NULL) {
+          ResourceMark rm;
+          // Get the module name
+          ModuleEntry* module = package_entry->module();
+          assert(module != NULL, "Boot classLoader package missing module");
+          assert(module->is_named(), "Boot classLoader package is in unnamed module");
+          const char* module_name = module->name()->as_C_string();
+          if (module_name != NULL) {
+            location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
+          }
+        }
+      }
     }
   }
-
   if (location != 0) {
     if (UsePerfData) {
       ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
@@ -409,11 +449,11 @@
     }
   }
 }
+#endif
 
 bool ClassPathImageEntry::is_jrt() {
-  return string_ends_with(name(), BOOT_IMAGE_NAME);
+  return ClassLoader::is_jrt(name());
 }
-#endif
 
 #if INCLUDE_CDS
 void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
@@ -480,7 +520,7 @@
     _shared_paths_misc_info->add_boot_classpath(sys_class_path);
   }
 #endif
-  setup_search_path(sys_class_path);
+  setup_search_path(sys_class_path, true);
 }
 
 #if INCLUDE_CDS
@@ -500,10 +540,11 @@
 }
 #endif
 
-void ClassLoader::setup_search_path(const char *class_path) {
+void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
   int offset = 0;
   int len = (int)strlen(class_path);
   int end = 0;
+  bool mark_append_entry = false;
 
   // Iterate over class path entries
   for (int start = 0; start < len; start = end) {
@@ -512,10 +553,23 @@
     }
     EXCEPTION_MARK;
     ResourceMark rm(THREAD);
+    mark_append_entry = (mark_append_entry ||
+      (bootstrap_search && (start == Arguments::bootclassloader_append_index())));
     char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
     strncpy(path, &class_path[start], end - start);
     path[end - start] = '\0';
-    update_class_path_entry_list(path, false);
+    update_class_path_entry_list(path, false, mark_append_entry, false);
+
+    // Check on the state of the boot loader's append path
+    if (mark_append_entry && (_first_append_entry == NULL)) {
+      // Failure to mark the first append entry, most likely
+      // due to a non-existent path. Record the next entry
+      // as the first boot loader append entry.
+      mark_append_entry = true;
+    } else {
+      mark_append_entry = false;
+    }
+
 #if INCLUDE_CDS
     if (DumpSharedSpaces) {
       check_shared_classpath(path);
@@ -616,6 +670,18 @@
   return NULL;
 }
 
+// The boot class loader must adhere to specfic visibility rules.
+// Prior to loading a class in a named package, the package is checked
+// to see if it is in a module defined to the boot loader. If the
+// package is not in a module defined to the boot loader, the class
+// must be loaded only in the boot loader's append path, which
+// consists of [-Xbootclasspath/a]; [jvmti appended entries]
+void ClassLoader::set_first_append_entry(ClassPathEntry *new_entry) {
+  if (_first_append_entry == NULL) {
+    _first_append_entry = new_entry;
+  }
+}
+
 // returns true if entry already on class path
 bool ClassLoader::contains_entry(ClassPathEntry *entry) {
   ClassPathEntry* e = _first_entry;
@@ -641,9 +707,31 @@
   _num_entries ++;
 }
 
+void ClassLoader::prepend_to_list(ClassPathEntry *new_entry) {
+  if (new_entry != NULL) {
+    if (_last_entry == NULL) {
+      _first_entry = _last_entry = new_entry;
+    } else {
+      new_entry->set_next(_first_entry);
+      _first_entry = new_entry;
+    }
+  }
+  _num_entries ++;
+}
+
+void ClassLoader::add_to_list(const char *apath) {
+  update_class_path_entry_list((char*)apath, false, false, false);
+}
+
+void ClassLoader::prepend_to_list(const char *apath) {
+  update_class_path_entry_list((char*)apath, false, false, true);
+}
+
 // Returns true IFF the file/dir exists and the entry was successfully created.
 bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
+                                               bool mark_append_entry,
+                                               bool prepend_entry,
                                                bool throw_exception) {
   struct stat st;
   if (os::stat(path, &st) == 0) {
@@ -654,12 +742,20 @@
     if (new_entry == NULL) {
       return false;
     }
-    // The kernel VM adds dynamically to the end of the classloader path and
-    // doesn't reorder the bootclasspath which would break java.lang.Package
-    // (see PackageInfo).
+
+    // Ensure that the first boot loader append entry will always be set correctly.
+    assert((!mark_append_entry ||
+            (mark_append_entry && (!check_for_duplicates || !contains_entry(new_entry)))),
+           "failed to mark boot loader's first append boundary");
+
+    // Do not reorder the bootclasspath which would break get_system_package().
     // Add new entry to linked list
+
     if (!check_for_duplicates || !contains_entry(new_entry)) {
-      ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry);
+      ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry, prepend_entry);
+      if (mark_append_entry) {
+        set_first_append_entry(new_entry);
+      }
     }
     return true;
   } else {
@@ -760,246 +856,205 @@
   return (*Crc32)(crc, (const jbyte*)buf, len);
 }
 
-// PackageInfo data exists in order to support the java.lang.Package
-// class.  A Package object provides information about a java package
-// (version, vendor, etc.) which originates in the manifest of the jar
-// file supplying the package.  For application classes, the ClassLoader
-// object takes care of this.
-
-// For system (boot) classes, the Java code in the Package class needs
-// to be able to identify which source jar file contained the boot
-// class, so that it can extract the manifest from it.  This table
-// identifies java packages with jar files in the boot classpath.
-
-// Because the boot classpath cannot change, the classpath index is
-// sufficient to identify the source jar file or directory.  (Since
-// directories have no manifests, the directory name is not required,
-// but is available.)
-
-// When using sharing -- the pathnames of entries in the boot classpath
-// may not be the same at runtime as they were when the archive was
-// created (NFS, Samba, etc.).  The actual files and directories named
-// in the classpath must be the same files, in the same order, even
-// though the exact name is not the same.
-
-class PackageInfo: public BasicHashtableEntry<mtClass> {
-public:
-  const char* _pkgname;       // Package name
-  int _classpath_index;       // Index of directory or JAR file loaded from
-
-  PackageInfo* next() {
-    return (PackageInfo*)BasicHashtableEntry<mtClass>::next();
-  }
-
-  const char* pkgname()           { return _pkgname; }
-  void set_pkgname(char* pkgname) { _pkgname = pkgname; }
-
-  const char* filename() {
-    return ClassLoader::classpath_entry(_classpath_index)->name();
-  }
-
-  void set_index(int index) {
-    _classpath_index = index;
-  }
-};
-
-
-class PackageHashtable : public BasicHashtable<mtClass> {
-private:
-  inline unsigned int compute_hash(const char *s, int n) {
-    unsigned int val = 0;
-    while (--n >= 0) {
-      val = *s++ + 31 * val;
-    }
-    return val;
-  }
-
-  PackageInfo* bucket(int index) {
-    return (PackageInfo*)BasicHashtable<mtClass>::bucket(index);
-  }
-
-  PackageInfo* get_entry(int index, unsigned int hash,
-                         const char* pkgname, size_t n) {
-    for (PackageInfo* pp = bucket(index); pp != NULL; pp = pp->next()) {
-      if (pp->hash() == hash &&
-          strncmp(pkgname, pp->pkgname(), n) == 0 &&
-          pp->pkgname()[n] == '\0') {
-        return pp;
-      }
-    }
-    return NULL;
-  }
-
-public:
-  PackageHashtable(int table_size)
-    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo)) {}
-
-  PackageHashtable(int table_size, HashtableBucket<mtClass>* t, int number_of_entries)
-    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo), t, number_of_entries) {}
-
-  PackageInfo* get_entry(const char* pkgname, int n) {
-    unsigned int hash = compute_hash(pkgname, n);
-    return get_entry(hash_to_index(hash), hash, pkgname, n);
-  }
-
-  PackageInfo* new_entry(char* pkgname, int n) {
-    unsigned int hash = compute_hash(pkgname, n);
-    PackageInfo* pp;
-    pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
-    pp->set_pkgname(pkgname);
-    return pp;
-  }
-
-  void add_entry(PackageInfo* pp) {
-    int index = hash_to_index(pp->hash());
-    BasicHashtable<mtClass>::add_entry(index, pp);
-  }
-
-  void copy_pkgnames(const char** packages) {
-    int n = 0;
-    for (int i = 0; i < table_size(); ++i) {
-      for (PackageInfo* pp = bucket(i); pp != NULL; pp = pp->next()) {
-        packages[n++] = pp->pkgname();
-      }
-    }
-    assert(n == number_of_entries(), "just checking");
-  }
-
-  CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
-};
-
 #if INCLUDE_CDS
-void PackageHashtable::copy_table(char** top, char* end,
-                                  PackageHashtable* table) {
-  // Copy (relocate) the table to the shared space.
-  BasicHashtable<mtClass>::copy_table(top, end);
-
-  // Calculate the space needed for the package name strings.
-  int i;
-  intptr_t* tableSize = (intptr_t*)(*top);
-  *top += sizeof(intptr_t);  // For table size
-  char* tableStart = *top;
-
-  for (i = 0; i < table_size(); ++i) {
-    for (PackageInfo* pp = table->bucket(i);
-                      pp != NULL;
-                      pp = pp->next()) {
-      int n1 = (int)(strlen(pp->pkgname()) + 1);
-      if (*top + n1 >= end) {
-        report_out_of_shared_space(SharedMiscData);
+void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
+  jlong size;
+  JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
+  if (location == 0) {
+    vm_exit_during_initialization(
+      "Cannot find ModuleLoaderMap location from modules jimage.", NULL);
+  }
+  char* buffer = NEW_RESOURCE_ARRAY(char, size);
+  jlong read = (*JImageGetResource)(jimage, location, buffer, size);
+  if (read != size) {
+    vm_exit_during_initialization(
+      "Cannot find ModuleLoaderMap resource from modules jimage.", NULL);
+  }
+  char* char_buf = (char*)buffer;
+  int buflen = (int)strlen(char_buf);
+  char* begin_ptr = char_buf;
+  char* end_ptr = strchr(begin_ptr, '\n');
+  bool process_boot_modules = false;
+  _boot_modules_array = new (ResourceObj::C_HEAP, mtInternal)
+    GrowableArray<char*>(INITIAL_BOOT_MODULES_ARRAY_SIZE, true);
+  _platform_modules_array = new (ResourceObj::C_HEAP, mtInternal)
+    GrowableArray<char*>(INITIAL_PLATFORM_MODULES_ARRAY_SIZE, true);
+  while (end_ptr != NULL && (end_ptr - char_buf) < buflen) {
+    // Allocate a buffer from the C heap to be appended to the _boot_modules_array
+    // or the _platform_modules_array.
+    char* temp_name = NEW_C_HEAP_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1), mtInternal);
+    strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
+    temp_name[end_ptr - begin_ptr] = '\0';
+    if (strncmp(temp_name, "BOOT", 4) == 0) {
+      process_boot_modules = true;
+      FREE_C_HEAP_ARRAY(char, temp_name);
+    } else if (strncmp(temp_name, "PLATFORM", 8) == 0) {
+      process_boot_modules = false;
+      FREE_C_HEAP_ARRAY(char, temp_name);
+    } else {
+      // module name
+      if (process_boot_modules) {
+        _boot_modules_array->append(temp_name);
+      } else {
+        _platform_modules_array->append(temp_name);
       }
-      pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
-      *top += n1;
     }
+    begin_ptr = ++end_ptr;
+    end_ptr = strchr(begin_ptr, '\n');
   }
-  *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord));
-  if (*top >= end) {
-    report_out_of_shared_space(SharedMiscData);
-  }
-
-  // Write table size
-  intptr_t len = *top - (char*)tableStart;
-  *tableSize = len;
-}
-
-
-void ClassLoader::copy_package_info_buckets(char** top, char* end) {
-  _package_hash_table->copy_buckets(top, end);
-}
-
-void ClassLoader::copy_package_info_table(char** top, char* end) {
-  _package_hash_table->copy_table(top, end, _package_hash_table);
+  FREE_RESOURCE_ARRAY(u1, buffer, size);
 }
 #endif
 
-PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
-  const char *cp = strrchr(pkgname, '/');
+// Function add_package extracts the package from the fully qualified class name
+// and checks if the package is in the boot loader's package entry table.  If so,
+// then it sets the classpath_index in the package entry record.
+//
+// The classpath_index field is used to find the entry on the boot loader class
+// path for packages with classes loaded by the boot loader from -Xbootclasspath/a
+// in an unnamed module.  It is also used to indicate (for all packages whose
+// classes are loaded by the boot loader) that at least one of the package's
+// classes has been loaded.
+bool ClassLoader::add_package(const char *fullq_class_name, s2 classpath_index, TRAPS) {
+  assert(fullq_class_name != NULL, "just checking");
+
+  // Get package name from fully qualified class name.
+  const char *cp = strrchr(fullq_class_name, '/');
   if (cp != NULL) {
-    // Package prefix found
-    int n = cp - pkgname + 1;
-    return _package_hash_table->get_entry(pkgname, n);
+    int len = cp - fullq_class_name;
+    PackageEntryTable* pkg_entry_tbl =
+      ClassLoaderData::the_null_class_loader_data()->packages();
+    TempNewSymbol pkg_symbol =
+      SymbolTable::new_symbol(fullq_class_name, len, CHECK_false);
+    PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(pkg_symbol);
+    if (pkg_entry != NULL) {
+      assert(classpath_index != -1, "Unexpected classpath_index");
+      pkg_entry->set_classpath_index(classpath_index);
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+oop ClassLoader::get_system_package(const char* name, TRAPS) {
+  // Look up the name in the boot loader's package entry table.
+  if (name != NULL) {
+    TempNewSymbol package_sym = SymbolTable::new_symbol(name, (int)strlen(name), CHECK_NULL);
+    // Look for the package entry in the boot loader's package entry table.
+    PackageEntry* package =
+      ClassLoaderData::the_null_class_loader_data()->packages()->lookup_only(package_sym);
+
+    // Return NULL if package does not exist or if no classes in that package
+    // have been loaded.
+    if (package != NULL && package->has_loaded_class()) {
+      ModuleEntry* module = package->module();
+      if (module->location() != NULL) {
+        ResourceMark rm(THREAD);
+        Handle ml = java_lang_String::create_from_str(
+          module->location()->as_C_string(), THREAD);
+        return ml();
+      }
+      // Return entry on boot loader class path.
+      Handle cph = java_lang_String::create_from_str(
+        ClassLoader::classpath_entry(package->classpath_index())->name(), THREAD);
+      return cph();
+    }
   }
   return NULL;
 }
 
-
-bool ClassLoader::add_package(const char *pkgname, int classpath_index, TRAPS) {
-  assert(pkgname != NULL, "just checking");
-  // Bootstrap loader no longer holds system loader lock obj serializing
-  // load_instance_class and thereby add_package
-  {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    // First check for previously loaded entry
-    PackageInfo* pp = lookup_package(pkgname);
-    if (pp != NULL) {
-      // Existing entry found, check source of package
-      pp->set_index(classpath_index);
-      return true;
-    }
-
-    const char *cp = strrchr(pkgname, '/');
-    if (cp != NULL) {
-      // Package prefix found
-      int n = cp - pkgname + 1;
-
-      char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1, mtClass);
-      if (new_pkgname == NULL) {
-        return false;
-      }
-
-      memcpy(new_pkgname, pkgname, n);
-      new_pkgname[n] = '\0';
-      pp = _package_hash_table->new_entry(new_pkgname, n);
-      pp->set_index(classpath_index);
-
-      // Insert into hash table
-      _package_hash_table->add_entry(pp);
-    }
-    return true;
-  }
-}
-
-
-oop ClassLoader::get_system_package(const char* name, TRAPS) {
-  PackageInfo* pp;
-  {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    pp = lookup_package(name);
-  }
-  if (pp == NULL) {
-    return NULL;
-  } else {
-    Handle p = java_lang_String::create_from_str(pp->filename(), THREAD);
-    return p();
-  }
-}
-
-
 objArrayOop ClassLoader::get_system_packages(TRAPS) {
   ResourceMark rm(THREAD);
-  int nof_entries;
-  const char** packages;
+  // List of pointers to PackageEntrys that have loaded classes.
+  GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
   {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    // Allocate resource char* array containing package names
-    nof_entries = _package_hash_table->number_of_entries();
-    if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) {
-      return NULL;
+    MutexLocker ml(Module_lock, THREAD);
+
+    PackageEntryTable* pe_table =
+      ClassLoaderData::the_null_class_loader_data()->packages();
+
+    // Collect the packages that have at least one loaded class.
+    for (int x = 0; x < pe_table->table_size(); x++) {
+      for (PackageEntry* package_entry = pe_table->bucket(x);
+           package_entry != NULL;
+           package_entry = package_entry->next()) {
+        if (package_entry->has_loaded_class()) {
+          loaded_class_pkgs->append(package_entry);
+        }
+      }
     }
-    _package_hash_table->copy_pkgnames(packages);
-  }
-  // Allocate objArray and fill with java.lang.String
-  objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
-                                           nof_entries, CHECK_0);
-  objArrayHandle result(THREAD, r);
-  for (int i = 0; i < nof_entries; i++) {
-    Handle str = java_lang_String::create_from_str(packages[i], CHECK_0);
-    result->obj_at_put(i, str());
   }
 
+
+  // Allocate objArray and fill with java.lang.String
+  objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
+                                           loaded_class_pkgs->length(), CHECK_NULL);
+  objArrayHandle result(THREAD, r);
+  for (int x = 0; x < loaded_class_pkgs->length(); x++) {
+    PackageEntry* package_entry = loaded_class_pkgs->at(x);
+    Handle str = java_lang_String::create_from_symbol(package_entry->name(), CHECK_NULL);
+    result->obj_at_put(x, str());
+  }
   return result();
 }
 
+#if INCLUDE_CDS
+s2 ClassLoader::module_to_classloader(const char* module_name) {
+
+  assert(_boot_modules_array != NULL, "_boot_modules_array is NULL");
+  assert(_platform_modules_array != NULL, "_platform_modules_array is NULL");
+
+  int array_size = _boot_modules_array->length();
+  for (int i = 0; i < array_size; i++) {
+    if (strcmp(module_name, _boot_modules_array->at(i)) == 0) {
+      return BOOT_LOADER;
+    }
+  }
+
+  array_size = _platform_modules_array->length();
+  for (int i = 0; i < array_size; i++) {
+    if (strcmp(module_name, _platform_modules_array->at(i)) == 0) {
+      return PLATFORM_LOADER;
+    }
+  }
+
+  return APP_LOADER;
+}
+#endif
+
+s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
+                                     int classpath_index, TRAPS) {
+#if INCLUDE_CDS
+  // obtain the classloader type based on the class name.
+  // First obtain the package name based on the class name. Then obtain
+  // the classloader type based on the package name from the jimage using
+  // a jimage API. If the classloader type cannot be found from the
+  // jimage, it is determined by the class path entry.
+  jshort loader_type = ClassLoader::APP_LOADER;
+  if (e->is_jrt()) {
+    int length = 0;
+    const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+    if (pkg_string != NULL) {
+      ResourceMark rm;
+      TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, THREAD);
+      const char* pkg_name_C_string = (const char*)(pkg_name->as_C_string());
+      ClassPathImageEntry* cpie = (ClassPathImageEntry*)e;
+      JImageFile* jimage = cpie->jimage();
+      char* module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name_C_string);
+      if (module_name != NULL) {
+        loader_type = ClassLoader::module_to_classloader(module_name);
+      }
+    }
+  } else if (ClassLoaderExt::is_boot_classpath(classpath_index)) {
+    loader_type = ClassLoader::BOOT_LOADER;
+  }
+  return loader_type;
+#endif
+  return ClassLoader::BOOT_LOADER; // the classloader type is ignored in non-CDS cases
+}
+
+
 // caller needs ResourceMark
 const char* ClassLoader::file_name_for_class_name(const char* class_name,
                                                   int class_name_len) {
@@ -1018,7 +1073,7 @@
   return file_name;
 }
 
-instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
+instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
 
   assert(name != NULL, "invariant");
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -1037,24 +1092,54 @@
 
   ClassLoaderExt::Context context(class_name, file_name, THREAD);
 
-  // Lookup stream
+  // Lookup stream for parsing .class file
   ClassFileStream* stream = NULL;
-  int classpath_index = 0;
-  ClassPathEntry* e = _first_entry;
-  {
-    PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
-      ((JavaThread*)THREAD)->get_thread_stat()->perf_timers_addr(),
-      PerfClassTraceTime::CLASS_LOAD);
+  s2 classpath_index = 0;
 
-    for (; e != NULL; e = e->next(), ++classpath_index) {
-      stream = e->open_stream(file_name, CHECK_NULL);
-      if (NULL == stream) {
-        continue;
+  // If DumpSharedSpaces is true, boot loader visibility boundaries are set
+  // to be _first_entry to the end (all path entries).
+  //
+  // If search_append_only is true, boot loader visibility boundaries are
+  // set to be _fist_append_entry to the end. This includes:
+  //   [-Xbootclasspath/a]; [jvmti appended entries]
+  //
+  // If both DumpSharedSpaces and search_append_only are false, boot loader
+  // visibility boundaries are set to be _first_entry to the entry before
+  // the _first_append_entry.  This would include:
+  //   [-Xpatch:<dirs>];  [exploded build | modules]
+  //
+  // DumpSharedSpaces and search_append_only are mutually exclusive and cannot
+  // be true at the same time.
+  ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
+  ClassPathEntry* last_e =
+      (search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
+
+  {
+    if (search_append_only) {
+      // For the boot loader append path search, must calculate
+      // the starting classpath_index prior to attempting to
+      // load the classfile.
+      ClassPathEntry *tmp_e = _first_entry;
+      while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
+        tmp_e = tmp_e->next();
+        ++classpath_index;
       }
+    }
+
+    // Attempt to load the classfile from either:
+    //   - [-Xpatch:dir]; exploded build | modules
+    //     or
+    //   - [-Xbootclasspath/a]; [jvmti appended entries]
+    while ((e != NULL) && (e != last_e)) {
+      stream = e->open_stream(file_name, CHECK_NULL);
       if (!context.check(stream, classpath_index)) {
         return NULL;
       }
-      break;
+      if (NULL != stream) {
+        break;
+      }
+      e = e->next();
+      ++classpath_index;
     }
   }
 
@@ -1085,32 +1170,16 @@
     return NULL;
   }
 
-  return context.record_result(classpath_index, e, result, THREAD);
+  jshort loader_type = classloader_type(name, e, classpath_index, CHECK_NULL);
+  return context.record_result(classpath_index, loader_type, e, result, THREAD);
 }
 
-void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
-                                            int number_of_entries) {
-  assert(_package_hash_table == NULL, "One package info table allowed.");
-  assert(length == package_hash_table_size * sizeof(HashtableBucket<mtClass>),
-         "bad shared package info size.");
-  _package_hash_table = new PackageHashtable(package_hash_table_size, t,
-                                             number_of_entries);
-}
-
-
-void ClassLoader::create_package_info_table() {
-    assert(_package_hash_table == NULL, "shouldn't have one yet");
-    _package_hash_table = new PackageHashtable(package_hash_table_size);
-}
-
-
 // Initialize the class loader's access to methods in libzip.  Parse and
 // process the boot classpath into a list ClassPathEntry objects.  Once
 // this list has been created, it must not change order (see class PackageInfo)
 // it can be appended to and is by jvmti and the kernel vm.
 
 void ClassLoader::initialize() {
-  assert(_package_hash_table == NULL, "should have been initialized by now.");
   EXCEPTION_MARK;
 
   if (UsePerfData) {
@@ -1258,12 +1327,48 @@
   return true;
 }
 
-#ifndef PRODUCT
+void ClassLoader::create_javabase() {
+  Thread* THREAD = Thread::current();
 
-void ClassLoader::verify() {
-  _package_hash_table->verify();
+  // Create java.base's module entry for the boot
+  // class loader prior to loading j.l.Ojbect.
+  ClassLoaderData* null_cld = ClassLoaderData::the_null_class_loader_data();
+
+  // Get module entry table
+  ModuleEntryTable* null_cld_modules = null_cld->modules();
+  if (null_cld_modules == NULL) {
+    vm_exit_during_initialization("No ModuleEntryTable for the boot class loader");
+  }
+
+  {
+    MutexLocker ml(Module_lock, THREAD);
+    ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(NULL), vmSymbols::java_base(), NULL, NULL, null_cld);
+    if (jb_module == NULL) {
+      vm_exit_during_initialization("Unable to create ModuleEntry for java.base");
+    }
+    ModuleEntryTable::set_javabase_module(jb_module);
+  }
+
+  // When looking for the jimage file, only
+  // search the boot loader's module path which
+  // can consist of [-Xpatch]; exploded build | modules
+  // Do not search the boot loader's append path.
+  ClassPathEntry* e = _first_entry;
+  ClassPathEntry* last_e = _first_append_entry;
+  while ((e != NULL) && (e != last_e)) {
+    JImageFile *jimage = e->jimage();
+    if (jimage != NULL && e->is_jrt()) {
+      set_has_jimage(true);
+#if INCLUDE_CDS
+      ClassLoader::initialize_module_loader_map(jimage);
+#endif
+      return;
+    }
+    e = e->next();
+  }
 }
 
+#ifndef PRODUCT
 
 // CompileTheWorld
 //
@@ -1325,10 +1430,6 @@
   tty->cr();
 }
 
-bool ClassPathDirEntry::is_jrt() {
-  return false;
-}
-
 void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
   real_jzfile* zip = (real_jzfile*) _zip;
   tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
@@ -1350,10 +1451,6 @@
   }
 }
 
-bool ClassPathZipEntry::is_jrt() {
-  return false;
-}
-
 void ClassLoader::compile_the_world() {
   EXCEPTION_MARK;
   HandleMark hm(THREAD);
@@ -1366,7 +1463,7 @@
   ClassPathEntry* e = _first_entry;
   jlong start = os::javaTimeMillis();
   while (e != NULL) {
-    // We stop at bootmodules.jimage, unless it is the first bootstrap path entry
+    // We stop at "modules" jimage, unless it is the first bootstrap path entry
     if (e->is_jrt() && e != _first_entry) break;
     e->compile_the_world(system_class_loader, CATCH);
     e = e->next();
diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp
index c2a68c0..4d5d2c9 100644
--- a/hotspot/src/share/vm/classfile/classLoader.hpp
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp
@@ -33,8 +33,17 @@
 // The VM class loader.
 #include <sys/stat.h>
 
-// Name of boot module image
-#define  BOOT_IMAGE_NAME "bootmodules.jimage"
+// Name of boot "modules" image
+#define  MODULES_IMAGE_NAME "modules"
+
+// Name of the resource containing mapping from module names to defining class loader type
+#define MODULE_LOADER_MAP "jdk/internal/vm/cds/resources/ModuleLoaderMap.dat"
+
+// Initial sizes of the following arrays are based on the generated ModuleLoaderMap.dat
+#define INITIAL_BOOT_MODULES_ARRAY_SIZE 30
+#define INITIAL_PLATFORM_MODULES_ARRAY_SIZE  15
+
+// Class path entry (directory or zip file)
 
 class JImageFile;
 class ClassFileStream;
@@ -49,6 +58,7 @@
     // may have unlocked readers, so write atomically.
     OrderAccess::release_store_ptr(&_next, next);
   }
+  virtual bool is_jrt() = 0;
   virtual bool is_jar_file() const = 0;
   virtual const char* name() const = 0;
   virtual JImageFile* jimage() const = 0;
@@ -59,13 +69,13 @@
   virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
   // Debugging
   NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
-    NOT_PRODUCT(virtual bool is_jrt() = 0;)
 };
 
 class ClassPathDirEntry: public ClassPathEntry {
  private:
   const char* _dir;           // Name of directory
  public:
+  bool is_jrt()            { return false; }
   bool is_jar_file() const { return false;  }
   const char* name() const { return _dir; }
   JImageFile* jimage() const { return NULL; }
@@ -73,7 +83,6 @@
   ClassFileStream* open_stream(const char* name, TRAPS);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -96,6 +105,7 @@
   jzfile* _zip;              // The zip archive
   const char*   _zip_name;   // Name of zip archive
  public:
+  bool is_jrt()            { return false; }
   bool is_jar_file() const { return true;  }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
@@ -106,7 +116,6 @@
   void contents_do(void f(const char* name, void* context), void* context);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -116,29 +125,28 @@
   JImageFile* _jimage;
   const char* _name;
 public:
+  bool is_jrt();
   bool is_jar_file() const { return false; }
   bool is_open() const { return _jimage != NULL; }
   const char* name() const { return _name == NULL ? "" : _name; }
   JImageFile* jimage() const { return _jimage; }
   ClassPathImageEntry(JImageFile* jimage, const char* name);
   ~ClassPathImageEntry();
-  static void name_to_package(const char* name, char* buffer, int length);
+  void name_to_package(const char* name, char* package, int length);
   ClassFileStream* open_stream(const char* name, TRAPS);
 
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
-class PackageHashtable;
-class PackageInfo;
 class SharedPathsMiscInfo;
-template <MEMFLAGS F> class HashtableBucket;
 
 class ClassLoader: AllStatic {
  public:
-  enum SomeConstants {
-    package_hash_table_size = 31  // Number of buckets
+  enum ClassLoaderType {
+    BOOT_LOADER = 1,      /* boot loader */
+    PLATFORM_LOADER  = 2, /* PlatformClassLoader */
+    APP_LOADER  = 3       /* AppClassLoader */
   };
  protected:
 
@@ -177,41 +185,60 @@
   static PerfCounter* _isUnsyncloadClass;
   static PerfCounter* _load_instance_class_failCounter;
 
-  // First entry in linked list of ClassPathEntry instances
+  // First entry in linked list of ClassPathEntry instances.
+  // This consists of entries made up by:
+  //   - boot loader modules
+  //     [-Xpatch]; exploded build | modules;
+  //   - boot loader append path
+  //     [-Xbootclasspath/a]; [jvmti appended entries]
   static ClassPathEntry* _first_entry;
   // Last entry in linked list of ClassPathEntry instances
   static ClassPathEntry* _last_entry;
   static int _num_entries;
 
-  // Hash table used to keep track of loaded packages
-  static PackageHashtable* _package_hash_table;
+  // Pointer into the linked list of ClassPathEntry instances.
+  // Marks the start of:
+  //   - the boot loader's append path
+  //     [-Xbootclasspath/a]; [jvmti appended entries]
+  static ClassPathEntry* _first_append_entry;
+
   static const char* _shared_archive;
 
+  // True if the boot path has a "modules" jimage
+  static bool _has_jimage;
+
+  // Array of module names associated with the boot class loader
+  CDS_ONLY(static GrowableArray<char*>* _boot_modules_array;)
+
+  // Array of module names associated with the platform class loader
+  CDS_ONLY(static GrowableArray<char*>* _platform_modules_array;)
+
   // Info used by CDS
   CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
 
-  // Hash function
-  static unsigned int hash(const char *s, int n);
-  // Returns the package file name corresponding to the specified package
-  // or class name, or null if not found.
-  static PackageInfo* lookup_package(const char *pkgname);
-  // Adds a new package entry for the specified class or package name and
-  // corresponding directory or jar file name.
-  static bool add_package(const char *pkgname, int classpath_index, TRAPS);
-
   // Initialization
   static void setup_bootstrap_search_path();
-  static void setup_search_path(const char *class_path);
+  static void setup_search_path(const char *class_path, bool setting_bootstrap);
 
   static void load_zip_library();
   static void load_jimage_library();
   static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                  bool throw_exception, TRAPS);
 
+ public:
+
+  // If the package for the fully qualified class name is in the boot
+  // loader's package entry table then add_package() sets the classpath_index
+  // field so that get_system_package() will know to return a non-null value
+  // for the package's location.  And, so that the package will be added to
+  // the list of packages returned by get_system_packages().
+  // For packages whose classes are loaded from the boot loader class path, the
+  // classpath_index indicates which entry on the boot loader class path.
+  static bool add_package(const char *fullq_class_name, s2 classpath_index, TRAPS);
+
   // Canonicalizes path names, so strcmp will work properly. This is mainly
   // to avoid confusing the zip library
   static bool get_canonical_path(const char* orig, char* out, int len);
-
   static const char* file_name_for_class_name(const char* class_name,
                                               int class_name_len);
 
@@ -220,6 +247,8 @@
   static int crc32(int crc, const char* buf, int len);
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
+                                           bool mark_append_entry,
+                                           bool prepend_entry,
                                            bool throw_exception=true);
   static void print_bootclasspath();
 
@@ -284,8 +313,18 @@
     return _load_instance_class_failCounter;
   }
 
+  // Sets _has_jimage to TRUE if "modules" jimage file exists
+  static void set_has_jimage(bool val) {
+    _has_jimage = val;
+  }
+
+  static bool has_jimage() { return _has_jimage; }
+
+  // Create the ModuleEntry for java.base
+  static void create_javabase();
+
   // Load individual .class file
-  static instanceKlassHandle load_class(Symbol* class_name, TRAPS);
+  static instanceKlassHandle load_class(Symbol* class_name, bool search_append_only, TRAPS);
 
   // If the specified package has been loaded by the system, then returns
   // the name of the directory or ZIP file that the package was loaded from.
@@ -304,9 +343,7 @@
   // Initialization
   static void initialize();
   CDS_ONLY(static void initialize_shared_path();)
-  static void create_package_info_table();
-  static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
-                                        int number_of_entries);
+
   static int compute_Object_vtable();
 
   static ClassPathEntry* classpath_entry(int n) {
@@ -320,8 +357,6 @@
 
 #if INCLUDE_CDS
   // Sharing dump and restore
-  static void copy_package_info_buckets(char** top, char* end);
-  static void copy_package_info_table(char** top, char* end);
 
   static void  check_shared_classpath(const char *path);
   static void  finalize_shared_paths_misc_info();
@@ -329,7 +364,12 @@
   static void* get_shared_paths_misc_info();
   static bool  check_shared_paths_misc_info(void* info, int size);
   static void  exit_with_path_failure(const char* error, const char* message);
+
+  static s2 module_to_classloader(const char* module_name);
+  static void initialize_module_loader_map(JImageFile* jimage);
 #endif
+  static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
+                                 int classpath_index, TRAPS);
 
   static void  trace_class_path(const char* msg, const char* name = NULL);
 
@@ -342,15 +382,30 @@
   static jlong class_link_count();
   static jlong class_link_time_ms();
 
+  static void set_first_append_entry(ClassPathEntry* entry);
+
   // indicates if class path already contains a entry (exact match by name)
   static bool contains_entry(ClassPathEntry* entry);
 
   // adds a class path list
   static void add_to_list(ClassPathEntry* new_entry);
 
+  // prepends a class path list
+  static void prepend_to_list(ClassPathEntry* new_entry);
+
   // creates a class path zip entry (returns NULL if JAR file cannot be opened)
   static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
 
+  // add a path to class path list
+  static void add_to_list(const char* apath);
+
+  // prepend a path to class path list
+  static void prepend_to_list(const char* apath);
+
+  static bool string_ends_with(const char* str, const char* str_to_find);
+
+  static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
+
   // Debugging
   static void verify()              PRODUCT_RETURN;
 
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp
index 9543a1f..f3278a7 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp
@@ -31,7 +31,7 @@
 //
 // Class loaders that implement a deterministic name resolution strategy
 // (including with respect to their delegation behavior), such as the boot, the
-// extension, and the system loaders of the JDK's built-in class loader
+// platform, and the system loaders of the JDK's built-in class loader
 // hierarchy, always produce the same linkset for a given configuration.
 //
 // ClassLoaderData carries information related to a linkset (e.g.,
@@ -51,6 +51,8 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/metadataOnStackMark.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/shared/gcLocker.hpp"
@@ -83,6 +85,7 @@
   // The null-class-loader should always be kept alive.
   _keep_alive(is_anonymous || h_class_loader.is_null()),
   _metaspace(NULL), _unloading(false), _klasses(NULL),
+  _modules(NULL), _packages(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
   _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
@@ -168,6 +171,30 @@
   }
 }
 
+void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
+  if (_modules != NULL) {
+    for (int i = 0; i < _modules->table_size(); i++) {
+      for (ModuleEntry* entry = _modules->bucket(i);
+                              entry != NULL;
+                              entry = entry->next()) {
+        f(entry);
+      }
+    }
+  }
+}
+
+void ClassLoaderData::packages_do(void f(PackageEntry*)) {
+  if (_packages != NULL) {
+    for (int i = 0; i < _packages->table_size(); i++) {
+      for (PackageEntry* entry = _packages->bucket(i);
+                              entry != NULL;
+                              entry = entry->next()) {
+        f(entry);
+      }
+    }
+  }
+}
+
 void ClassLoaderData::record_dependency(const Klass* k, TRAPS) {
   assert(k != NULL, "invariant");
 
@@ -341,6 +368,46 @@
   }
 }
 
+PackageEntryTable* ClassLoaderData::packages() {
+  // Lazily create the package entry table at first request.
+  if (_packages == NULL) {
+    MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+    // Check again if _packages has been allocated while we were getting this lock.
+    if (_packages != NULL) {
+      return _packages;
+    }
+    // Ensure _packages is stable, since it is examined without a lock
+    OrderAccess::storestore();
+    _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
+  }
+  return _packages;
+}
+
+ModuleEntryTable* ClassLoaderData::modules() {
+  // Lazily create the module entry table at first request.
+  if (_modules == NULL) {
+    MutexLocker m1(Module_lock);
+    // Check again if _modules has been allocated while we were getting this lock.
+    if (_modules != NULL) {
+      return _modules;
+    }
+
+    ModuleEntryTable* temp_table = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size);
+    // Each loader has one unnamed module entry. Create it before
+    // any classes, loaded by this loader, are defined in case
+    // they end up being defined in loader's unnamed module.
+    temp_table->create_unnamed_module(this);
+
+    {
+      MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+      // Ensure _modules is stable, since it is examined without a lock
+      OrderAccess::storestore();
+      _modules = temp_table;
+    }
+  }
+  return _modules;
+}
+
 oop ClassLoaderData::keep_alive_object() const {
   assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
   return is_anonymous() ? _klasses->java_mirror() : class_loader();
@@ -358,16 +425,30 @@
   // Release C heap structures for all the classes.
   classes_do(InstanceKlass::release_C_heap_structures);
 
+  // Release C heap allocated hashtable for all the packages.
+  if (_packages != NULL) {
+    // Destroy the table itself
+    delete _packages;
+    _packages = NULL;
+  }
+
+  // Release C heap allocated hashtable for all the modules.
+  if (_modules != NULL) {
+    // Destroy the table itself
+    delete _modules;
+    _modules = NULL;
+  }
+
+  // release the metaspace
   Metaspace *m = _metaspace;
   if (m != NULL) {
     _metaspace = NULL;
-    // release the metaspace
     delete m;
-    // release the handles
-    if (_handles != NULL) {
-      JNIHandleBlock::release_block(_handles);
-      _handles = NULL;
-    }
+  }
+  // release the handles
+  if (_handles != NULL) {
+    JNIHandleBlock::release_block(_handles);
+    _handles = NULL;
   }
 
   // Clear all the JNI handles for methods
@@ -389,10 +470,10 @@
 }
 
 /**
- * Returns true if this class loader data is for the extension class loader.
+ * Returns true if this class loader data is for the platform class loader.
  */
-bool ClassLoaderData::is_ext_class_loader_data() const {
-  return SystemDictionary::is_ext_class_loader(class_loader());
+bool ClassLoaderData::is_platform_class_loader_data() const {
+  return SystemDictionary::is_platform_class_loader(class_loader());
 }
 
 Metaspace* ClassLoaderData::metaspace_non_null() {
@@ -438,6 +519,10 @@
   return handles()->allocate_handle(h());
 }
 
+void ClassLoaderData::remove_handle(jobject h) {
+  _handles->release_handle(h);
+}
+
 // Add this metadata pointer to be freed when it's safe.  This is only during
 // class unloading because Handles might point to this metadata field.
 void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
@@ -712,6 +797,40 @@
   }
 }
 
+void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
+  assert_locked_or_safepoint(Module_lock);
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->modules_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  // Only walk the head until any clds not purged from prior unloading
+  // (CMS doesn't purge right away).
+  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
+    cld->modules_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
+  assert_locked_or_safepoint(Module_lock);
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->packages_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  // Only walk the head until any clds not purged from prior unloading
+  // (CMS doesn't purge right away).
+  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
+    cld->packages_do(f);
+  }
+}
+
 void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     cld->loaded_classes_do(klass_closure);
@@ -723,6 +842,7 @@
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
     cld->classes_do(f);
   }
 }
@@ -800,6 +920,12 @@
   data = _head;
   while (data != NULL) {
     if (data->is_alive(is_alive_closure)) {
+      if (data->packages_defined()) {
+        data->packages()->purge_all_package_exports();
+      }
+      if (data->modules_defined()) {
+        data->modules()->purge_all_module_reads();
+      }
       // clean metaspace
       if (walk_all_metadata) {
         data->classes_do(InstanceKlass::purge_previous_versions);
@@ -992,6 +1118,7 @@
 Ticks ClassLoaderDataGraph::_class_unload_time;
 
 void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
+  assert(k != NULL, "invariant");
 
   // post class unload event
   EventClassUnload event(UNTIMED);
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index f6e82fa..4b6d247 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -53,6 +53,10 @@
 class JNIMethodBlock;
 class JNIHandleBlock;
 class Metadebug;
+class ModuleEntry;
+class PackageEntry;
+class ModuleEntryTable;
+class PackageEntryTable;
 
 // GC root for walking class loader data created
 
@@ -92,6 +96,10 @@
   static void classes_do(KlassClosure* klass_closure);
   static void classes_do(void f(Klass* const));
   static void methods_do(void f(Method*));
+  static void modules_do(void f(ModuleEntry*));
+  static void modules_unloading_do(void f(ModuleEntry*));
+  static void packages_do(void f(PackageEntry*));
+  static void packages_unloading_do(void f(PackageEntry*));
   static void loaded_classes_do(KlassClosure* klass_closure);
   static void classes_unloading_do(void f(Klass* const));
   static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
@@ -172,9 +180,12 @@
   volatile int _claimed;   // true if claimed, for example during GC traces.
                            // To avoid applying oop closure more than once.
                            // Has to be an int because we cas it.
-  Klass* _klasses;         // The classes defined by the class loader.
+  JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which
+                            // have the same life cycle of the corresponding ClassLoader.
 
-  JNIHandleBlock* _handles; // Handles to constant pool arrays
+  Klass* _klasses;         // The classes defined by the class loader.
+  PackageEntryTable* _packages; // The packages defined by the class loader.
+  ModuleEntryTable* _modules;   // The modules defined by the class loader.
 
   // These method IDs are created for the class loader and set to NULL when the
   // class loader is unloaded.  They are rarely freed, only for redefine classes
@@ -218,6 +229,8 @@
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
   void methods_do(void f(Method*));
+  void modules_do(void f(ModuleEntry*));
+  void packages_do(void f(PackageEntry*));
 
   // Deallocate free list during class unloading.
   void free_deallocate_list();
@@ -256,7 +269,7 @@
   bool is_the_null_class_loader_data() const {
     return this == _the_null_class_loader_data;
   }
-  bool is_ext_class_loader_data() const;
+  bool is_platform_class_loader_data() const;
 
   // The Metaspace is created lazily so may be NULL.  This
   // method will allocate a Metaspace if needed.
@@ -293,11 +306,16 @@
   const char* loader_name();
 
   jobject add_handle(Handle h);
+  void remove_handle(jobject h);
   void add_class(Klass* k, bool publicize = true);
   void remove_class(Klass* k);
   bool contains_klass(Klass* k);
   void record_dependency(const Klass* to, TRAPS);
   void init_dependencies(TRAPS);
+  PackageEntryTable* packages();
+  bool packages_defined() { return (_packages != NULL); }
+  ModuleEntryTable* modules();
+  bool modules_defined() { return (_modules != NULL); }
 
   void add_to_deallocate_list(Metadata* m);
 
diff --git a/hotspot/src/share/vm/classfile/classLoaderExt.hpp b/hotspot/src/share/vm/classfile/classLoaderExt.hpp
index 990a8b6..7fa11b2 100644
--- a/hotspot/src/share/vm/classfile/classLoaderExt.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp
@@ -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
@@ -49,12 +49,14 @@
       return false;
     }
 
-    instanceKlassHandle record_result(const int classpath_index,
+    instanceKlassHandle record_result(const s2 classpath_index,
+                                      const jshort classloader_type,
                                       const ClassPathEntry* e,
                                       instanceKlassHandle result, TRAPS) {
       if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
         if (DumpSharedSpaces) {
           result->set_shared_classpath_index(classpath_index);
+          result->set_class_loader_type(classloader_type);
         }
         return result;
       } else {
@@ -65,13 +67,27 @@
 
 
   static void add_class_path_entry(const char* path, bool check_for_duplicates,
-                                   ClassPathEntry* new_entry) {
-    ClassLoader::add_to_list(new_entry);
+                                   ClassPathEntry* new_entry, bool prepend_entry) {
+    if (prepend_entry) {
+      ClassLoader::prepend_to_list(new_entry);
+    } else {
+      ClassLoader::add_to_list(new_entry);
+    }
   }
   static void append_boot_classpath(ClassPathEntry* new_entry) {
     ClassLoader::add_to_list(new_entry);
+    // During jvmti live phase an entry can be appended to the boot
+    // loader's ClassPathEntry instances.  Need to mark the start
+    // of the boot loader's append path in case there was no reason
+    // to mark it initially in setup_bootstrap_search_path.
+    if (ClassLoader::_first_append_entry == NULL) {
+      ClassLoader::set_first_append_entry(new_entry);
+    }
   }
   static void setup_search_paths() {}
+  static bool is_boot_classpath(int classpath_index) {
+   return true;
+ }
   static Klass* load_one_class(ClassListParser* parser, TRAPS);
 };
 
diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp
index 2df6a47..a69b87e 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp
@@ -24,7 +24,9 @@
 
 #include "precompiled.hpp"
 #include "classfile/altHashing.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/debugInfo.hpp"
@@ -768,7 +770,7 @@
       }
     }
   }
-  create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
+  create_mirror(k, Handle(NULL), Handle(NULL), Handle(NULL), CHECK);
 }
 
 void java_lang_Class::initialize_mirror_fields(KlassHandle k,
@@ -789,7 +791,7 @@
 }
 
 void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
-                                    Handle protection_domain, TRAPS) {
+                                    Handle module, Handle protection_domain, TRAPS) {
   assert(k->java_mirror() == NULL, "should only assign mirror once");
   // Use this moment of initialization to cache modifier_flags also,
   // to support Class.getModifiers().  Instance classes recalculate
@@ -849,11 +851,25 @@
     assert(class_loader() == k->class_loader(), "should be same");
     set_class_loader(mirror(), class_loader());
 
+    // set the module field in the java_lang_Class instance
+    // This may be null during bootstrap but will get fixed up later on.
+    set_module(mirror(), module());
+
     // Setup indirection from klass->mirror last
     // after any exceptions can happen during allocations.
     if (!k.is_null()) {
       k->set_java_mirror(mirror());
     }
+
+    // Keep list of classes needing java.base module fixup.
+    if (!ModuleEntryTable::javabase_defined()) {
+      if (fixup_module_field_list() == NULL) {
+        GrowableArray<Klass*>* list =
+          new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(500, true);
+        set_fixup_module_field_list(list);
+      }
+      fixup_module_field_list()->push(k());
+    }
   } else {
     if (fixup_mirror_list() == NULL) {
       GrowableArray<Klass*>* list =
@@ -864,6 +880,10 @@
   }
 }
 
+void java_lang_Class::fixup_module_field(KlassHandle k, Handle module) {
+  assert(_module_offset != 0, "must have been computed already");
+  java_lang_Class::set_module(k->java_mirror(), module());
+}
 
 int  java_lang_Class::oop_size(oop java_class) {
   assert(_oop_size_offset != 0, "must be set");
@@ -931,6 +951,16 @@
   return java_class->obj_field(_class_loader_offset);
 }
 
+oop java_lang_Class::module(oop java_class) {
+  assert(_module_offset != 0, "must be set");
+  return java_class->obj_field(_module_offset);
+}
+
+void java_lang_Class::set_module(oop java_class, oop module) {
+  assert(_module_offset != 0, "must be set");
+  java_class->obj_field_put(_module_offset, module);
+}
+
 oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
   // This should be improved by adding a field at the Java level or by
   // introducing a new VM klass (see comment in ClassFileParser)
@@ -1116,6 +1146,10 @@
                  k, vmSymbols::componentType_name(),
                  vmSymbols::class_signature());
 
+  compute_offset(_module_offset,
+                 k, vmSymbols::module_name(),
+                 vmSymbols::module_signature());
+
   // Init lock is a C union with component_mirror.  Only instanceKlass mirrors have
   // init_lock and only ArrayKlass mirrors have component_mirror.  Since both are oops
   // GC treats them the same.
@@ -1668,28 +1702,48 @@
     buf_len += (int)strlen(source_file_name);
   }
 
+  char *module_name = NULL, *module_version = NULL;
+  ModuleEntry* module = holder->module();
+  if (module->is_named()) {
+    module_name = module->name()->as_C_string();
+    buf_len += (int)strlen(module_name);
+    if (module->version() != NULL) {
+      module_version = module->version()->as_C_string();
+      buf_len += (int)strlen(module_version);
+    }
+  }
+
   // Allocate temporary buffer with extra space for formatting and line number
   char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
 
   // Print stack trace line in buffer
-  sprintf(buf, "\tat %s.%s", klass_name, method_name);
+  sprintf(buf, "\tat %s.%s(", klass_name, method_name);
+
+  // Print module information
+  if (module_name != NULL) {
+    if (module_version != NULL) {
+      sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version);
+    } else {
+      sprintf(buf + (int)strlen(buf), "%s/", module_name);
+    }
+  }
 
   if (!version_matches(method, version)) {
-    strcat(buf, "(Redefined)");
+    strcat(buf, "Redefined)");
   } else {
     int line_number = Backtrace::get_line_number(method, bci);
     if (line_number == -2) {
-      strcat(buf, "(Native Method)");
+      strcat(buf, "Native Method)");
     } else {
       if (source_file_name != NULL && (line_number != -1)) {
         // Sourcename and linenumber
-        sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
+        sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number);
       } else if (source_file_name != NULL) {
         // Just sourcename
-        sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
+        sprintf(buf + (int)strlen(buf), "%s)", source_file_name);
       } else {
         // Neither sourcename nor linenumber
-        sprintf(buf + (int)strlen(buf), "(Unknown Source)");
+        sprintf(buf + (int)strlen(buf), "Unknown Source)");
       }
       nmethod* nm = method->code();
       if (WizardMode && nm != NULL) {
@@ -2094,6 +2148,20 @@
   oop methodname = StringTable::intern(sym, CHECK_0);
   java_lang_StackTraceElement::set_methodName(element(), methodname);
 
+  // Fill in module name and version
+  ModuleEntry* module = holder->module();
+  if (module->is_named()) {
+    oop module_name = StringTable::intern(module->name(), CHECK_0);
+    java_lang_StackTraceElement::set_moduleName(element(), module_name);
+    oop module_version;
+    if (module->version() != NULL) {
+      module_version = StringTable::intern(module->version(), CHECK_0);
+    } else {
+      module_version = NULL;
+    }
+    java_lang_StackTraceElement::set_moduleVersion(element(), module_version);
+  }
+
   if (!version_matches(method, version)) {
     // The method was redefined, accurate line number information isn't available
     java_lang_StackTraceElement::set_fileName(element(), NULL);
@@ -2753,6 +2821,80 @@
 }
 
 
+int java_lang_reflect_Module::loader_offset;
+int java_lang_reflect_Module::name_offset;
+int java_lang_reflect_Module::_module_entry_offset = -1;
+
+Handle java_lang_reflect_Module::create(Handle loader, Handle module_name, TRAPS) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+
+  Symbol* name = vmSymbols::java_lang_reflect_Module();
+  Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
+  instanceKlassHandle klass (THREAD, k);
+
+  Handle jlrmh = klass->allocate_instance_handle(CHECK_NH);
+  JavaValue result(T_VOID);
+  JavaCalls::call_special(&result, jlrmh, KlassHandle(THREAD, klass()),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::java_lang_reflect_module_init_signature(),
+                          loader, module_name, CHECK_NH);
+  return jlrmh;
+}
+
+void java_lang_reflect_Module::compute_offsets() {
+  Klass* k = SystemDictionary::reflect_Module_klass();
+  if(NULL != k) {
+    compute_offset(loader_offset,  k, vmSymbols::loader_name(),  vmSymbols::classloader_signature());
+    compute_offset(name_offset,    k, vmSymbols::name_name(),    vmSymbols::string_signature());
+    MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
+  }
+}
+
+
+oop java_lang_reflect_Module::loader(oop module) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  return module->obj_field(loader_offset);
+}
+
+void java_lang_reflect_Module::set_loader(oop module, oop value) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  module->obj_field_put(loader_offset, value);
+}
+
+oop java_lang_reflect_Module::name(oop module) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  return module->obj_field(name_offset);
+}
+
+void java_lang_reflect_Module::set_name(oop module, oop value) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  module->obj_field_put(name_offset, value);
+}
+
+ModuleEntry* java_lang_reflect_Module::module_entry(oop module, TRAPS) {
+  assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
+  assert(module != NULL, "module can't be null");
+  assert(module->is_oop(), "module must be oop");
+
+  ModuleEntry* module_entry = (ModuleEntry*)module->address_field(_module_entry_offset);
+  if (module_entry == NULL) {
+    // If the inject field containing the ModuleEntry* is null then return the
+    // class loader's unnamed module.
+    oop loader = java_lang_reflect_Module::loader(module);
+    Handle h_loader = Handle(THREAD, loader);
+    ClassLoaderData* loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+    return loader_cld->modules()->unnamed_module();
+  }
+  return module_entry;
+}
+
+void java_lang_reflect_Module::set_module_entry(oop module, ModuleEntry* module_entry) {
+  assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
+  assert(module != NULL, "module can't be null");
+  assert(module->is_oop(), "module must be oop");
+  module->address_field_put(_module_entry_offset, (address)module_entry);
+}
+
 Handle sun_reflect_ConstantPool::create(TRAPS) {
   assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
   Klass* k = SystemDictionary::reflect_ConstantPool_klass();
@@ -3352,6 +3494,7 @@
 bool java_lang_ClassLoader::offsets_computed = false;
 int  java_lang_ClassLoader::_loader_data_offset = -1;
 int  java_lang_ClassLoader::parallelCapable_offset = -1;
+int  java_lang_ClassLoader::unnamedModule_offset = -1;
 
 ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
     assert(loader != NULL && loader->is_oop(), "loader must be oop");
@@ -3371,6 +3514,9 @@
   compute_optional_offset(parallelCapable_offset,
     k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
 
+  compute_offset(unnamedModule_offset,
+    k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
+
   CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
 }
 
@@ -3438,6 +3584,10 @@
   return loader;
 }
 
+oop java_lang_ClassLoader::unnamedModule(oop loader) {
+  assert(is_instance(loader), "loader must be oop");
+  return loader->obj_field(unnamedModule_offset);
+}
 
 // Support for java_lang_System
 int java_lang_System::in_offset_in_bytes() {
@@ -3470,11 +3620,13 @@
 int java_lang_Class::_oop_size_offset;
 int java_lang_Class::_static_oop_field_count_offset;
 int java_lang_Class::_class_loader_offset;
+int java_lang_Class::_module_offset;
 int java_lang_Class::_protection_domain_offset;
 int java_lang_Class::_component_mirror_offset;
 int java_lang_Class::_init_lock_offset;
 int java_lang_Class::_signers_offset;
 GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = NULL;
+GrowableArray<Klass*>* java_lang_Class::_fixup_module_field_list = NULL;
 int java_lang_Throwable::backtrace_offset;
 int java_lang_Throwable::detailMessage_offset;
 int java_lang_Throwable::cause_offset;
@@ -3534,6 +3686,8 @@
 int java_lang_StackTraceElement::methodName_offset;
 int java_lang_StackTraceElement::fileName_offset;
 int java_lang_StackTraceElement::lineNumber_offset;
+int java_lang_StackTraceElement::moduleName_offset;
+int java_lang_StackTraceElement::moduleVersion_offset;
 int java_lang_StackFrameInfo::_declaringClass_offset;
 int java_lang_StackFrameInfo::_memberName_offset;
 int java_lang_StackFrameInfo::_bci_offset;
@@ -3575,6 +3729,14 @@
   element->int_field_put(lineNumber_offset, value);
 }
 
+void java_lang_StackTraceElement::set_moduleName(oop element, oop value) {
+  element->obj_field_put(moduleName_offset, value);
+}
+
+void java_lang_StackTraceElement::set_moduleVersion(oop element, oop value) {
+  element->obj_field_put(moduleVersion_offset, value);
+}
+
 // Support for java_lang_StackFrameInfo
 void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
   element->obj_field_put(_declaringClass_offset, value);
@@ -3713,6 +3875,8 @@
   java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
 
   // java_lang_StackTraceElement
+  java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header;
+  java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header;
   java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset  * x + header;
   java_lang_StackTraceElement::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
   java_lang_StackTraceElement::fileName_offset   = java_lang_StackTraceElement::hc_fileName_offset   * x + header;
@@ -3752,6 +3916,7 @@
   sun_reflect_ConstantPool::compute_offsets();
   sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
   java_lang_reflect_Parameter::compute_offsets();
+  java_lang_reflect_Module::compute_offsets();
   java_lang_StackFrameInfo::compute_offsets();
   java_lang_LiveStackFrameInfo::compute_offsets();
 
@@ -3899,7 +4064,7 @@
 
   // java.lang.ClassLoader
 
-  CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent,      "Ljava/lang/ClassLoader;");
+  CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent,        "Ljava/lang/ClassLoader;");
 
   // java.lang.System
 
diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp
index 9f7c2d1..6c48753 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp
@@ -210,12 +210,14 @@
   static int _init_lock_offset;
   static int _signers_offset;
   static int _class_loader_offset;
+  static int _module_offset;
   static int _component_mirror_offset;
 
   static bool offsets_computed;
   static int classRedefinedCount_offset;
 
   static GrowableArray<Klass*>* _fixup_mirror_list;
+  static GrowableArray<Klass*>* _fixup_module_field_list;
 
   static void set_init_lock(oop java_class, oop init_lock);
   static void set_protection_domain(oop java_class, oop protection_domain);
@@ -226,10 +228,13 @@
   static void compute_offsets();
 
   // Instance creation
-  static void create_mirror(KlassHandle k, Handle class_loader,
+  static void create_mirror(KlassHandle k, Handle class_loader, Handle module,
                             Handle protection_domain, TRAPS);
   static void fixup_mirror(KlassHandle k, TRAPS);
   static oop  create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
+
+  static void fixup_module_field(KlassHandle k, Handle module);
+
   // Conversion
   static Klass* as_Klass(oop java_class);
   static void set_klass(oop java_class, Klass* klass);
@@ -267,18 +272,29 @@
   static void set_signers(oop java_class, objArrayOop signers);
 
   static oop class_loader(oop java_class);
+  static void set_module(oop java_class, oop module);
+  static oop module(oop java_class);
 
   static int oop_size(oop java_class);
   static void set_oop_size(oop java_class, int size);
   static int static_oop_field_count(oop java_class);
   static void set_static_oop_field_count(oop java_class, int size);
 
+
   static GrowableArray<Klass*>* fixup_mirror_list() {
     return _fixup_mirror_list;
   }
   static void set_fixup_mirror_list(GrowableArray<Klass*>* v) {
     _fixup_mirror_list = v;
   }
+
+  static GrowableArray<Klass*>* fixup_module_field_list() {
+    return _fixup_module_field_list;
+  }
+  static void set_fixup_module_field_list(GrowableArray<Klass*>* v) {
+    _fixup_module_field_list = v;
+  }
+
   // Debugging
   friend class JavaClasses;
   friend class InstanceKlass;   // verification code accesses offsets
@@ -758,6 +774,39 @@
   friend class JavaClasses;
 };
 
+#define MODULE_INJECTED_FIELDS(macro)                            \
+  macro(java_lang_reflect_Module, module_entry, intptr_signature, false)
+
+class java_lang_reflect_Module {
+  private:
+    static int loader_offset;
+    static int name_offset;
+    static int _module_entry_offset;
+    static void compute_offsets();
+
+  public:
+    // Allocation
+    static Handle create(Handle loader, Handle module_name, TRAPS);
+
+    // Testers
+    static bool is_subclass(Klass* klass) {
+      return klass->is_subclass_of(SystemDictionary::reflect_Module_klass());
+    }
+    static bool is_instance(oop obj);
+
+    // Accessors
+    static oop loader(oop module);
+    static void set_loader(oop module, oop value);
+
+    static oop name(oop module);
+    static void set_name(oop module, oop value);
+
+    static ModuleEntry* module_entry(oop module, TRAPS);
+    static void set_module_entry(oop module, ModuleEntry* module_entry);
+
+  friend class JavaClasses;
+};
+
 // Interface to sun.reflect.ConstantPool objects
 class sun_reflect_ConstantPool {
  private:
@@ -1203,6 +1252,7 @@
   static bool offsets_computed;
   static int parent_offset;
   static int parallelCapable_offset;
+  static int unnamedModule_offset;
 
  public:
   static void compute_offsets();
@@ -1227,6 +1277,8 @@
   }
   static bool is_instance(oop obj);
 
+  static oop unnamedModule(oop loader);
+
   // Debugging
   friend class JavaClasses;
   friend class ClassFileParser; // access to number_of_fake_fields
@@ -1266,12 +1318,16 @@
 class java_lang_StackTraceElement: AllStatic {
  private:
   enum {
-    hc_declaringClass_offset  = 0,
-    hc_methodName_offset = 1,
-    hc_fileName_offset   = 2,
-    hc_lineNumber_offset = 3
+    hc_moduleName_offset = 0,
+    hc_moduleVersion_offset = 1,
+    hc_declaringClass_offset = 2,
+    hc_methodName_offset = 3,
+    hc_fileName_offset   = 4,
+    hc_lineNumber_offset = 5
   };
 
+  static int moduleName_offset;
+  static int moduleVersion_offset;
   static int declaringClass_offset;
   static int methodName_offset;
   static int fileName_offset;
@@ -1279,6 +1335,8 @@
 
  public:
   // Setters
+  static void set_moduleName(oop element, oop value);
+  static void set_moduleVersion(oop element, oop value);
   static void set_declaringClass(oop element, oop value);
   static void set_methodName(oop element, oop value);
   static void set_fileName(oop element, oop value);
@@ -1456,8 +1514,8 @@
   CLASSLOADER_INJECTED_FIELDS(macro)        \
   MEMBERNAME_INJECTED_FIELDS(macro)         \
   CALLSITECONTEXT_INJECTED_FIELDS(macro)    \
-  STACKFRAMEINFO_INJECTED_FIELDS(macro)
-
+  STACKFRAMEINFO_INJECTED_FIELDS(macro)     \
+  MODULE_INJECTED_FIELDS(macro)
 
 // Interface to hard-coded offset checking
 
diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
index 05deb98..1aba5b8 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
@@ -171,6 +171,10 @@
 
 
 
+inline bool java_lang_reflect_Module::is_instance(oop obj) {
+  return obj != NULL && is_subclass(obj->klass());
+}
+
 inline int Backtrace::merge_bci_and_version(int bci, int version) {
   // only store u2 for version, checking for overflow.
   if (version > USHRT_MAX || version < 0) version = USHRT_MAX;
diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp
index 90f6dad..e538ac8 100644
--- a/hotspot/src/share/vm/classfile/jimage.hpp
+++ b/hotspot/src/share/vm/classfile/jimage.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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
@@ -22,7 +22,7 @@
  *
  */
 
-#include "jni.h"
+#include "prims/jni.h"
 
 // Opaque reference to a JImage file.
 class JImageFile;
@@ -35,6 +35,8 @@
 
 // JImage Error Codes
 
+// Resource was not found
+#define JIMAGE_NOT_FOUND (0)
 // The image file is not prefixed with 0xCAFEDADA
 #define JIMAGE_BAD_MAGIC (-1)
 // The image file does not have a compatible (translatable) version
@@ -55,7 +57,7 @@
  *
  *  Ex.
  *   jint error;
- *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
+ *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
  *   if (image == NULL) {
  *     tty->print_cr("JImage failed to open: %d", error);
  *     ...
diff --git a/hotspot/src/share/vm/classfile/klassFactory.cpp b/hotspot/src/share/vm/classfile/klassFactory.cpp
index 033d9bf..11b07f6 100644
--- a/hotspot/src/share/vm/classfile/klassFactory.cpp
+++ b/hotspot/src/share/vm/classfile/klassFactory.cpp
@@ -103,11 +103,15 @@
   assert(loader_data != NULL, "invariant");
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
 
+  bool changed_by_loadhook = false;
+
   ResourceMark rm;
   HandleMark hm;
 
   JvmtiCachedClassFileData* cached_class_file = NULL;
 
+  ClassFileStream* old_stream = stream;
+
   stream = prologue(stream,
                     name,
                     loader_data,
@@ -125,8 +129,8 @@
                          ClassFileParser::BROADCAST, // publicity level
                          CHECK_NULL);
 
-  instanceKlassHandle result = parser.create_instance_klass(CHECK_NULL);
-  assert(result == parser.create_instance_klass(THREAD), "invariant");
+  instanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
+  assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant");
 
   if (result.is_null()) {
     return NULL;
diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp
new file mode 100644
index 0000000..e86ed6a
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp
@@ -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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/symbol.hpp"
+#include "prims/jni.h"
+#include "runtime/handles.inline.hpp"
+#include "runtime/safepoint.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.inline.hpp"
+
+ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
+
+
+void ModuleEntry::set_location(Symbol* location) {
+  if (_location != NULL) {
+    // _location symbol's refcounts are managed by ModuleEntry,
+    // must decrement the old one before updating.
+    _location->decrement_refcount();
+  }
+
+  _location = location;
+
+  if (location != NULL) {
+    location->increment_refcount();
+  }
+}
+
+void ModuleEntry::set_version(Symbol* version) {
+  if (_version != NULL) {
+    // _version symbol's refcounts are managed by ModuleEntry,
+    // must decrement the old one before updating.
+    _version->decrement_refcount();
+  }
+
+  _version = version;
+
+  if (version != NULL) {
+    version->increment_refcount();
+  }
+}
+
+// Returns the shared ProtectionDomain
+Handle ModuleEntry::shared_protection_domain() {
+  return Handle(JNIHandles::resolve(_pd));
+}
+
+// Set the shared ProtectionDomain atomically
+void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data,
+                                               Handle pd_h) {
+  // Create a JNI handle for the shared ProtectionDomain and save it atomically.
+  // If someone beats us setting the _pd cache, the created JNI handle is destroyed.
+  jobject obj = loader_data->add_handle(pd_h);
+  if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) {
+    loader_data->remove_handle(obj);
+  }
+}
+
+// Returns true if this module can read module m
+bool ModuleEntry::can_read(ModuleEntry* m) const {
+  assert(m != NULL, "No module to lookup in this module's reads list");
+
+  // Unnamed modules read everyone and all modules
+  // read java.base.  If either of these conditions
+  // hold, readability has been established.
+  if (!this->is_named() ||
+      (m == ModuleEntryTable::javabase_module())) {
+    return true;
+  }
+
+  MutexLocker m1(Module_lock);
+  if (!has_reads()) {
+    return false;
+  } else {
+    return _reads->contains(m);
+  }
+}
+
+// Add a new module to this module's reads list
+void ModuleEntry::add_read(ModuleEntry* m) {
+  MutexLocker m1(Module_lock);
+  if (m == NULL) {
+    set_can_read_all_unnamed();
+  } else {
+    if (_reads == NULL) {
+      // Lazily create a module's reads list
+      _reads = new (ResourceObj::C_HEAP, mtClass)GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, true);
+    }
+    _reads->append_if_missing(m);
+  }
+}
+
+bool ModuleEntry::has_reads() const {
+  assert_locked_or_safepoint(Module_lock);
+  return ((_reads != NULL) && !_reads->is_empty());
+}
+
+// Purge dead module entries out of reads list.
+void ModuleEntry::purge_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (has_reads()) {
+    // Go backwards because this removes entries that are dead.
+    int len = _reads->length();
+    for (int idx = len - 1; idx >= 0; idx--) {
+      ModuleEntry* module_idx = _reads->at(idx);
+      ClassLoaderData* cld = module_idx->loader();
+      if (cld->is_unloading()) {
+        _reads->delete_at(idx);
+      }
+    }
+  }
+}
+
+void ModuleEntry::module_reads_do(ModuleClosure* const f) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(f != NULL, "invariant");
+
+  if (has_reads()) {
+    int reads_len = _reads->length();
+    for (int i = 0; i < reads_len; ++i) {
+      f->do_module(_reads->at(i));
+    }
+  }
+}
+
+void ModuleEntry::delete_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  delete _reads;
+  _reads = NULL;
+}
+
+ModuleEntryTable::ModuleEntryTable(int table_size)
+  : Hashtable<Symbol*, mtClass>(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL)
+{
+}
+
+ModuleEntryTable::~ModuleEntryTable() {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Walk through all buckets and all entries in each bucket,
+  // freeing each entry.
+  for (int i = 0; i < table_size(); ++i) {
+    for (ModuleEntry* m = bucket(i); m != NULL;) {
+      ModuleEntry* to_remove = m;
+      // read next before freeing.
+      m = m->next();
+
+      ResourceMark rm;
+      log_debug(modules)("ModuleEntryTable: deleting module: %s", to_remove->name() != NULL ?
+                         to_remove->name()->as_C_string() : UNNAMED_MODULE);
+
+      // Clean out the C heap allocated reads list first before freeing the entry
+      to_remove->delete_reads();
+      if (to_remove->name() != NULL) {
+        to_remove->name()->decrement_refcount();
+      }
+      if (to_remove->version() != NULL) {
+        to_remove->version()->decrement_refcount();
+      }
+      if (to_remove->location() != NULL) {
+        to_remove->location()->decrement_refcount();
+      }
+
+      // Unlink from the Hashtable prior to freeing
+      unlink_entry(to_remove);
+      FREE_C_HEAP_ARRAY(char, to_remove);
+    }
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list");
+  free_buckets();
+}
+
+void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Each ModuleEntryTable has exactly one unnamed module
+  if (loader_data->is_the_null_class_loader_data()) {
+    // For the boot loader, the java.lang.reflect.Module for the unnamed module
+    // is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At
+    // this point initially create the ModuleEntry for the unnamed module.
+    _unnamed_module = new_entry(0, Handle(NULL), NULL, NULL, NULL, loader_data);
+  } else {
+    // For all other class loaders the java.lang.reflect.Module for their
+    // corresponding unnamed module can be found in the java.lang.ClassLoader object.
+    oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader());
+    _unnamed_module = new_entry(0, Handle(module), NULL, NULL, NULL, loader_data);
+
+    // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module
+    // object.
+    java_lang_reflect_Module::set_module_entry(module, _unnamed_module);
+  }
+
+  // Add to bucket 0, no name to hash on
+  add_entry(0, _unnamed_module);
+}
+
+ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle, Symbol* name,
+                                         Symbol* version, Symbol* location,
+                                         ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+  ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass);
+
+  // Initialize everything BasicHashtable would
+  entry->set_next(NULL);
+  entry->set_hash(hash);
+  entry->set_literal(name);
+
+  // Initialize fields specific to a ModuleEntry
+  entry->init();
+  if (name != NULL) {
+    name->increment_refcount();
+  } else {
+    // Unnamed modules can read all other unnamed modules.
+    entry->set_can_read_all_unnamed();
+  }
+
+  if (!module_handle.is_null()) {
+    entry->set_module(loader_data->add_handle(module_handle));
+  }
+
+  entry->set_loader(loader_data);
+  entry->set_version(version);
+  entry->set_location(location);
+
+  TRACE_INIT_MODULE_ID(entry);
+
+  return entry;
+}
+
+void ModuleEntryTable::add_entry(int index, ModuleEntry* new_entry) {
+  assert_locked_or_safepoint(Module_lock);
+  Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
+}
+
+ModuleEntry* ModuleEntryTable::locked_create_entry_or_null(Handle module_handle,
+                                                           Symbol* module_name,
+                                                           Symbol* module_version,
+                                                           Symbol* module_location,
+                                                           ClassLoaderData* loader_data) {
+  assert(module_name != NULL, "ModuleEntryTable locked_create_entry_or_null should never be called for unnamed module.");
+  assert_locked_or_safepoint(Module_lock);
+  // Check if module already exists.
+  if (lookup_only(module_name) != NULL) {
+    return NULL;
+  } else {
+    ModuleEntry* entry = new_entry(compute_hash(module_name), module_handle, module_name,
+                                   module_version, module_location, loader_data);
+    add_entry(index_for(module_name), entry);
+    return entry;
+  }
+}
+
+// lookup_only by Symbol* to find a ModuleEntry.
+ModuleEntry* ModuleEntryTable::lookup_only(Symbol* name) {
+  if (name == NULL) {
+    // Return this table's unnamed module
+    return unnamed_module();
+  }
+  int index = index_for(name);
+  for (ModuleEntry* m = bucket(index); m != NULL; m = m->next()) {
+    if (m->name()->fast_compare(name) == 0) {
+      return m;
+    }
+  }
+  return NULL;
+}
+
+// Remove dead modules from all other alive modules' reads list.
+// This should only occur at class unloading.
+void ModuleEntryTable::purge_all_module_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* entry = bucket(i);
+                      entry != NULL;
+                      entry = entry->next()) {
+      entry->purge_reads();
+    }
+  }
+}
+
+void ModuleEntryTable::finalize_javabase(Handle module_handle, Symbol* version, Symbol* location) {
+  assert_locked_or_safepoint(Module_lock);
+  ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data();
+  ModuleEntryTable* module_table = boot_loader_data->modules();
+
+  assert(module_table != NULL, "boot loader's ModuleEntryTable not defined");
+
+  if (module_handle.is_null()) {
+    fatal("Unable to finalize module definition for java.base");
+  }
+
+  // Set java.lang.reflect.Module, version and location for java.base
+  ModuleEntry* jb_module = javabase_module();
+  assert(jb_module != NULL, "java.base ModuleEntry not defined");
+  jb_module->set_module(boot_loader_data->add_handle(module_handle));
+  jb_module->set_version(version);
+  jb_module->set_location(location);
+  // Store pointer to the ModuleEntry for java.base in the java.lang.reflect.Module object.
+  java_lang_reflect_Module::set_module_entry(module_handle(), jb_module);
+}
+
+void ModuleEntryTable::patch_javabase_entries(Handle module_handle) {
+  if (module_handle.is_null()) {
+    fatal("Unable to patch the module field of classes loaded prior to java.base's definition, invalid java.lang.reflect.Module");
+  }
+
+  // Do the fixups for the basic primitive types
+  java_lang_Class::set_module(Universe::int_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::float_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::double_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::byte_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::bool_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::char_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::long_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::short_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::void_mirror(), module_handle());
+
+  // Do the fixups for classes that have already been created.
+  GrowableArray <Klass*>* list = java_lang_Class::fixup_module_field_list();
+  int list_length = list->length();
+  for (int i = 0; i < list_length; i++) {
+    Klass* k = list->at(i);
+    assert(k->is_klass(), "List should only hold classes");
+    Thread* THREAD = Thread::current();
+    KlassHandle kh(THREAD, k);
+    java_lang_Class::fixup_module_field(kh, module_handle);
+  }
+
+  delete java_lang_Class::fixup_module_field_list();
+  java_lang_Class::set_fixup_module_field_list(NULL);
+}
+
+#ifndef PRODUCT
+void ModuleEntryTable::print() {
+  tty->print_cr("Module Entry Table (table_size=%d, entries=%d)",
+                table_size(), number_of_entries());
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* probe = bucket(i);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->print();
+    }
+  }
+}
+
+void ModuleEntry::print() {
+  ResourceMark rm;
+  tty->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
+                p2i(this),
+                name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
+                p2i(module()),
+                loader()->loader_name(),
+                version() != NULL ? version()->as_C_string() : "NULL",
+                location() != NULL ? location()->as_C_string() : "NULL",
+                BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
+}
+#endif
+
+void ModuleEntryTable::verify() {
+  int element_count = 0;
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* probe = bucket(i);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->verify();
+      element_count++;
+    }
+  }
+  guarantee(number_of_entries() == element_count,
+            "Verify of Module Entry Table failed");
+  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
+}
+
+void ModuleEntry::verify() {
+  guarantee(loader() != NULL, "A module entry must be associated with a loader.");
+}
diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp
new file mode 100644
index 0000000..d67251c
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_MODULEENTRY_HPP
+#define SHARE_VM_CLASSFILE_MODULEENTRY_HPP
+
+#include "classfile/classLoaderData.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "oops/symbol.hpp"
+#include "prims/jni.h"
+#include "runtime/mutexLocker.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.hpp"
+
+#define UNNAMED_MODULE "Unnamed Module"
+
+class ModuleClosure;
+
+// A ModuleEntry describes a module that has been defined by a call to JVM_DefineModule.
+// It contains:
+//   - Symbol* containing the module's name.
+//   - pointer to the java.lang.reflect.Module for this module.
+//   - ClassLoaderData*, class loader of this module.
+//   - a growable array containg other module entries that this module can read.
+//   - a flag indicating if this module can read all unnamed modules.
+//
+// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
+// data structure.
+class ModuleEntry : public HashtableEntry<Symbol*, mtClass> {
+private:
+  jobject _module;                     // java.lang.reflect.Module
+  jobject _pd;                         // java.security.ProtectionDomain, cached
+                                       // for shared classes from this module
+  ClassLoaderData* _loader;
+  GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
+  Symbol* _version;                    // module version number
+  Symbol* _location;                   // module location
+  bool _can_read_all_unnamed;
+  bool _has_default_read_edges;        // JVMTI redefine/retransform support
+  TRACE_DEFINE_TRACE_ID_FIELD;
+  enum {MODULE_READS_SIZE = 101};      // Initial size of list of modules that the module can read.
+
+public:
+  void init() {
+    _module = NULL;
+    _loader = NULL;
+    _pd = NULL;
+    _reads = NULL;
+    _version = NULL;
+    _location = NULL;
+    _can_read_all_unnamed = false;
+    _has_default_read_edges = false;
+  }
+
+  Symbol*            name() const          { return literal(); }
+  void               set_name(Symbol* n)   { set_literal(n); }
+
+  jobject            module() const        { return _module; }
+  void               set_module(jobject j) { _module = j; }
+
+  // The shared ProtectionDomain reference is set once the VM loads a shared class
+  // originated from the current Module. The referenced ProtectionDomain object is
+  // created by the ClassLoader when loading a class (shared or non-shared) from the
+  // Module for the first time. This ProtectionDomain object is used for all
+  // classes from the Module loaded by the same ClassLoader.
+  Handle             shared_protection_domain();
+  void               set_shared_protection_domain(ClassLoaderData *loader_data,
+                                                  Handle pd);
+
+  ClassLoaderData*   loader() const                 { return _loader; }
+  void               set_loader(ClassLoaderData* l) { _loader = l; }
+
+  Symbol*            version() const                { return _version; }
+  void               set_version(Symbol* version);
+
+  Symbol*            location() const               { return _location; }
+  void               set_location(Symbol* location);
+
+  bool               can_read(ModuleEntry* m) const;
+  bool               has_reads() const;
+  void               add_read(ModuleEntry* m);
+
+  bool               is_named() const               { return (literal() != NULL); }
+
+  bool can_read_all_unnamed() const {
+    assert(is_named() || _can_read_all_unnamed == true,
+           "unnamed modules can always read all unnamed modules");
+    return _can_read_all_unnamed;
+  }
+
+  // Modules can only go from strict to loose.
+  void set_can_read_all_unnamed() { _can_read_all_unnamed = true; }
+
+  bool has_default_read_edges() const {
+    return _has_default_read_edges;
+  }
+
+  // Sets true and returns the previous value.
+  bool set_has_default_read_edges() {
+    MutexLocker ml(Module_lock);
+    bool prev = _has_default_read_edges;
+    _has_default_read_edges = true;
+    return prev;
+  }
+
+  ModuleEntry* next() const {
+    return (ModuleEntry*)HashtableEntry<Symbol*, mtClass>::next();
+  }
+  ModuleEntry** next_addr() {
+    return (ModuleEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
+  }
+
+  // iteration support for readability
+  void module_reads_do(ModuleClosure* const f);
+
+  TRACE_DEFINE_TRACE_ID_METHODS;
+
+  // Purge dead weak references out of reads list when any given class loader is unloaded.
+  void purge_reads();
+  void delete_reads();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+// Iterator interface
+class ModuleClosure: public StackObj {
+ public:
+  virtual void do_module(ModuleEntry* const module) = 0;
+};
+
+
+// The ModuleEntryTable is a Hashtable containing a list of all modules defined
+// by a particular class loader.  Each module is represented as a ModuleEntry node.
+//
+// Each ModuleEntryTable contains a _javabase_module field which allows for the
+// creation of java.base's ModuleEntry very early in bootstrapping before the
+// corresponding JVM_DefineModule call for java.base occurs during module system
+// initialization.  Setting up java.base's ModuleEntry early enables classes,
+// loaded prior to the module system being initialized to be created with their
+// PackageEntry node's correctly pointing at java.base's ModuleEntry.  No class
+// outside of java.base is allowed to be loaded pre-module system initialization.
+//
+// The ModuleEntryTable's lookup is lock free.
+//
+class ModuleEntryTable : public Hashtable<Symbol*, mtClass> {
+  friend class VMStructs;
+public:
+  enum Constants {
+    _moduletable_entry_size  = 109 // number of entries in module entry table
+  };
+
+private:
+  static ModuleEntry* _javabase_module;
+  ModuleEntry* _unnamed_module;
+
+  ModuleEntry* new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version,
+                         Symbol* location, ClassLoaderData* class_loader);
+  void add_entry(int index, ModuleEntry* new_entry);
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  ModuleEntry** bucket_addr(int i) {
+    return (ModuleEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
+  }
+
+  static unsigned int compute_hash(Symbol* name) { return ((name == NULL) ? 0 : (unsigned int)(name->identity_hash())); }
+  int index_for(Symbol* name) const              { return hash_to_index(compute_hash(name)); }
+
+public:
+  ModuleEntryTable(int table_size);
+  ~ModuleEntryTable();
+
+  ModuleEntry* bucket(int i) {
+    return (ModuleEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+
+  // Create module in loader's module entry table, if already exists then
+  // return null.  Assume Module_lock has been locked by caller.
+  ModuleEntry* locked_create_entry_or_null(Handle module_handle,
+                                           Symbol* module_name,
+                                           Symbol* module_version,
+                                           Symbol* module_location,
+                                           ClassLoaderData* loader_data);
+
+  // Only lookup module within loader's module entry table.  The table read is lock-free.
+  ModuleEntry* lookup_only(Symbol* name);
+
+  // purge dead weak references out of reads list
+  void purge_all_module_reads();
+
+  // Special handling for unnamed module, one per class loader's ModuleEntryTable
+  void create_unnamed_module(ClassLoaderData* loader_data);
+  ModuleEntry* unnamed_module()                           { return _unnamed_module; }
+
+  // Special handling for java.base
+  static ModuleEntry* javabase_module()                   { return _javabase_module; }
+  static void set_javabase_module(ModuleEntry* java_base) { _javabase_module = java_base; }
+  static bool javabase_defined()                          { return ((_javabase_module != NULL) &&
+                                                                    (_javabase_module->module() != NULL)); }
+  static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
+  static void patch_javabase_entries(Handle module_handle);
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+#endif // SHARE_VM_CLASSFILE_MODULEENTRY_HPP
diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp
new file mode 100644
index 0000000..a4a23d4
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/modules.cpp
@@ -0,0 +1,964 @@
+/*
+* 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 "precompiled.hpp"
+#include "classfile/classFileParser.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
+#include "classfile/javaAssertions.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
+#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "logging/log.hpp"
+#include "oops/instanceKlass.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/reflection.hpp"
+#include "utilities/utf8.hpp"
+
+static bool verify_module_name(char *module_name) {
+  if (module_name == NULL) return false;
+  int len = (int)strlen(module_name);
+  return (len > 0 && len <= Symbol::max_length() &&
+    UTF8::is_legal_utf8((unsigned char *)module_name, len, false) &&
+    ClassFileParser::verify_unqualified_name(module_name, len,
+    ClassFileParser::LegalModule));
+}
+
+bool Modules::verify_package_name(char *package_name) {
+  if (package_name == NULL) return false;
+  int len = (int)strlen(package_name);
+  return (len > 0 && len <= Symbol::max_length() &&
+    UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
+    ClassFileParser::verify_unqualified_name(package_name, len,
+    ClassFileParser::LegalClass));
+}
+
+static char* get_module_name(oop module, TRAPS) {
+  oop name_oop = java_lang_reflect_Module::name(module);
+  if (name_oop == NULL) {
+    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "Null module name");
+  }
+  char* module_name = java_lang_String::as_utf8_string(name_oop);
+  if (!verify_module_name(module_name)) {
+    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
+                   err_msg("Invalid module name: %s",
+                           module_name != NULL ? module_name : "NULL"));
+  }
+  return module_name;
+}
+
+static const char* get_module_version(jstring version) {
+  if (version == NULL) {
+    return NULL;
+  }
+  return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
+}
+
+static ModuleEntryTable* get_module_entry_table(Handle h_loader, TRAPS) {
+  // This code can be called during start-up, before the classLoader's classLoader data got
+  // created.  So, call register_loader() to make sure the classLoader data gets created.
+  ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+  return loader_cld->modules();
+}
+
+static PackageEntryTable* get_package_entry_table(Handle h_loader, TRAPS) {
+  // This code can be called during start-up, before the classLoader's classLoader data got
+  // created.  So, call register_loader() to make sure the classLoader data gets created.
+  ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+  return loader_cld->packages();
+}
+
+static ModuleEntry* get_module_entry(jobject module, TRAPS) {
+  Handle module_h(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(module_h())) {
+    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Bad module object");
+  }
+  return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
+}
+
+static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
+  ResourceMark rm(THREAD);
+  if (package == NULL) return NULL;
+  const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  if (package_name == NULL) return NULL;
+  TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
+  PackageEntryTable* package_entry_table = module_entry->loader()->packages();
+  assert(package_entry_table != NULL, "Unexpected null package entry table");
+  return package_entry_table->lookup_only(pkg_symbol);
+}
+
+static PackageEntry* get_package_entry_by_name(Symbol* package,
+                                               Handle h_loader,
+                                               TRAPS) {
+  if (package != NULL) {
+    ResourceMark rm(THREAD);
+    if (Modules::verify_package_name(package->as_C_string())) {
+      PackageEntryTable* const package_entry_table =
+        get_package_entry_table(h_loader, CHECK_NULL);
+      assert(package_entry_table != NULL, "Unexpected null package entry table");
+      return package_entry_table->lookup_only(package);
+    }
+  }
+  return NULL;
+}
+
+// Check if -Xpatch:<dirs> was specified.  If so, prepend each <dir>/module_name,
+// if it exists, to bootpath so boot loader can find the class files.  Also, if
+// using exploded modules, append <java.home>/modules/module_name, if it exists,
+// to bootpath so that its class files can be found by the boot loader.
+static void add_to_boot_loader_list(char *module_name, TRAPS) {
+  // java.base should be handled by argument parsing.
+  assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
+  char file_sep = os::file_separator()[0];
+  size_t module_len = strlen(module_name);
+
+  // If -Xpatch is set then add <patch-dir>/module_name paths.
+  char** patch_dirs = Arguments::patch_dirs();
+  if (patch_dirs != NULL) {
+    int dir_count = Arguments::patch_dirs_count();
+    for (int x = 0; x < dir_count; x++) {
+      // Really shouldn't be NULL, but check can't hurt
+      if (patch_dirs[x] != NULL) {
+        size_t len = strlen(patch_dirs[x]);
+        if (len != 0) { // Ignore empty strings.
+          len = len + module_len + 2;
+          char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+          jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
+
+          // See if Xpatch module path exists.
+          struct stat st;
+          if ((os::stat(prefix_path, &st) != 0)) {
+            FREE_C_HEAP_ARRAY(char, prefix_path);
+          } else {
+            {
+              HandleMark hm;
+              Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
+              ObjectLocker ol(loader_lock, THREAD);
+              ClassLoader::prepend_to_list(prefix_path);
+            }
+            log_info(classload)("opened: -Xpatch %s", prefix_path);
+          }
+        }
+      }
+    }
+  }
+
+  // If "modules" jimage does not exist then assume exploded form
+  // ${java.home}/modules/<module-name>
+  char* path = NULL;
+  if (!ClassLoader::has_jimage()) {
+    const char* home = Arguments::get_java_home();
+    size_t len = strlen(home) + module_len + 32;
+    path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+    jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
+    struct stat st;
+    // See if exploded module path exists.
+    if ((os::stat(path, &st) != 0)) {
+      FREE_C_HEAP_ARRAY(char, path);
+      path = NULL;
+    }
+  }
+
+  if (path != NULL) {
+    HandleMark hm;
+    Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
+    ObjectLocker ol(loader_lock, THREAD);
+
+    log_info(classload)("opened: %s", path);
+    ClassLoader::add_to_list(path);
+  }
+}
+
+bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
+  PackageEntry* res = get_package_entry_by_name(package, h_loader, CHECK_false);
+  return res != NULL;
+}
+
+static void define_javabase_module(jobject module, jstring version,
+                                   jstring location, jobjectArray packages, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  Handle module_handle(THREAD, JNIHandles::resolve(module));
+
+  // Obtain java.base's module version
+  const char* module_version = get_module_version(version);
+  TempNewSymbol version_symbol;
+  if (module_version != NULL) {
+    version_symbol = SymbolTable::new_symbol(module_version, CHECK);
+  } else {
+    version_symbol = NULL;
+  }
+
+  // Obtain java.base's location
+  const char* module_location = NULL;
+  TempNewSymbol location_symbol = NULL;
+  if (location != NULL) {
+    module_location =
+      java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
+    if (module_location != NULL) {
+      location_symbol = SymbolTable::new_symbol(module_location, CHECK);
+    }
+  }
+
+  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+  objArrayHandle packages_h(THREAD, packages_oop);
+  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+  // Check that the list of packages has no duplicates and that the
+  // packages are syntactically ok.
+  GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
+  for (int x = 0; x < num_packages; x++) {
+    oop string_obj = packages_h->obj_at(x);
+
+    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "Bad package name for module: java.base");
+    }
+    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    if (!Modules::verify_package_name(package_name)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Invalid package name: %s for module: java.base", package_name));
+    }
+    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)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Duplicate package name: %s for module java.base",
+                        package_name));
+    }
+  }
+
+  // Validate java_base's loader is the boot loader.
+  oop loader = java_lang_reflect_Module::loader(module_handle());
+  if (loader != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader must be the boot class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
+  // Ensure the boot loader's PackageEntryTable has been created
+  PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK);
+  assert(pkg_list->length() == 0 || package_table != NULL, "Bad package_table");
+
+  // Ensure java.base's ModuleEntry has been created
+  assert(ModuleEntryTable::javabase_module() != NULL, "No ModuleEntry for java.base");
+
+  {
+    MutexLocker m1(Module_lock, THREAD);
+
+    // Verify that all java.base packages created during bootstrapping are in
+    // pkg_list.  If any are not in pkg_list, than a non-java.base class was
+    // loaded erroneously pre java.base module definition.
+    package_table->verify_javabase_packages(pkg_list);
+
+    // loop through and add any new packages for java.base
+    PackageEntry* pkg;
+    for (int x = 0; x < pkg_list->length(); x++) {
+      // Some of java.base's packages were added early in bootstrapping, ignore duplicates.
+      if (package_table->lookup_only(pkg_list->at(x)) == NULL) {
+        pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_module());
+        assert(pkg != NULL, "Unable to create a java.base package entry");
+      }
+      // Unable to have a GrowableArray of TempNewSymbol.  Must decrement the refcount of
+      // the Symbol* that was created above for each package. The refcount was incremented
+      // by SymbolTable::new_symbol and as well by the PackageEntry creation.
+      pkg_list->at(x)->decrement_refcount();
+    }
+
+    // Finish defining java.base's ModuleEntry
+    ModuleEntryTable::finalize_javabase(module_handle, version_symbol, location_symbol);
+  }
+
+  log_debug(modules)("define_javabase_module(): Definition of module: java.base,"
+                     " version: %s, location: %s, package #: %d",
+                     module_version != NULL ? module_version : "NULL",
+                     module_location != NULL ? module_location : "NULL",
+                     pkg_list->length());
+
+  // packages defined to java.base
+  for (int x = 0; x < pkg_list->length(); x++) {
+    log_trace(modules)("define_javabase_module(): creation of package %s for module java.base",
+                       (pkg_list->at(x))->as_C_string());
+  }
+
+  // Patch any previously loaded classes' module field with java.base's jlr.Module.
+  ModuleEntryTable::patch_javabase_entries(module_handle);
+}
+
+void Modules::define_module(jobject module, jstring version,
+                            jstring location, jobjectArray packages, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle module_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(module_handle->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is not a subclass of java.lang.reflect.Module");
+  }
+
+  char* module_name = get_module_name(module_handle(), CHECK);
+  if (module_name == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Module name cannot be null");
+  }
+
+  // Special handling of java.base definition
+  if (strcmp(module_name, "java.base") == 0) {
+    define_javabase_module(module, version, location, packages, CHECK);
+    return;
+  }
+
+  const char* module_version = get_module_version(version);
+
+  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+  objArrayHandle packages_h(THREAD, packages_oop);
+  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+  // Check that the list of packages has no duplicates and that the
+  // packages are syntactically ok.
+  GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
+  for (int x = 0; x < num_packages; x++) {
+    oop string_obj = packages_h->obj_at(x);
+
+    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Bad package name for module: %s", module_name));
+    }
+    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    if (!verify_package_name(package_name)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Invalid package name: %s for module: %s",
+                        package_name, module_name));
+    }
+    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)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Duplicate package name: %s for module %s",
+                        package_name, module_name));
+    }
+  }
+
+  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");
+
+  // Create symbol* entry for module name.
+  TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
+
+  int dupl_pkg_index = -1;
+  bool dupl_modules = false;
+
+  // Create symbol* entry for module version.
+  TempNewSymbol version_symbol;
+  if (module_version != NULL) {
+    version_symbol = SymbolTable::new_symbol(module_version, CHECK);
+  } else {
+    version_symbol = NULL;
+  }
+
+  // Create symbol* entry for module location.
+  const char* module_location = NULL;
+  TempNewSymbol location_symbol = NULL;
+  if (location != NULL) {
+    module_location =
+      java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
+    if (module_location != NULL) {
+      location_symbol = SymbolTable::new_symbol(module_location, CHECK);
+    }
+  }
+
+  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(h_loader());
+  assert(loader_data != NULL, "class loader data shouldn't be null");
+
+  PackageEntryTable* package_table = NULL;
+  {
+    MutexLocker ml(Module_lock, THREAD);
+
+    if (num_packages > 0) {
+      package_table = get_package_entry_table(h_loader, CHECK);
+      assert(package_table != NULL, "Missing package_table");
+
+      // Check that none of the packages exist in the class loader's package table.
+      for (int x = 0; x < pkg_list->length(); x++) {
+        if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
+          // This could be because the module was already defined.  If so,
+          // report that error instead of the package error.
+          if (module_table->lookup_only(module_symbol) != NULL) {
+            dupl_modules = true;
+          } else {
+            dupl_pkg_index = x;
+          }
+          break;
+        }
+      }
+    }  // if (num_packages > 0)...
+
+    // Add the module and its packages.
+    if (!dupl_modules && dupl_pkg_index == -1) {
+      // Create the entry for this module in the class loader's module entry table.
+
+      ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
+                                    version_symbol, location_symbol, loader_data);
+
+      if (module_entry == NULL) {
+        dupl_modules = true;
+      } else {
+        // Add the packages.
+        assert(pkg_list->length() == 0 || package_table != NULL, "Bad package table");
+        PackageEntry* pkg;
+        for (int y = 0; y < pkg_list->length(); y++) {
+          pkg = package_table->locked_create_entry_or_null(pkg_list->at(y), module_entry);
+          assert(pkg != NULL, "Unable to create a module's package entry");
+
+          // Unable to have a GrowableArray of TempNewSymbol.  Must decrement the refcount of
+          // the Symbol* that was created above for each package. The refcount was incremented
+          // by SymbolTable::new_symbol and as well by the PackageEntry creation.
+          pkg_list->at(y)->decrement_refcount();
+        }
+
+        // Store pointer to ModuleEntry record in java.lang.reflect.Module object.
+        java_lang_reflect_Module::set_module_entry(module_handle(), module_entry);
+      }
+    }
+  }  // Release the lock
+
+  // any errors ?
+  if (dupl_modules) {
+     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+               err_msg("Module %s is already defined", module_name));
+  }
+  if (dupl_pkg_index != -1) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s for module %s already exists for class loader",
+                      pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
+  }
+
+  if (log_is_enabled(Debug, modules)) {
+    outputStream* logst = LogHandle(modules)::debug_stream();
+    logst->print("define_module(): creation of module: %s, version: %s, location: %s, ",
+                 module_name, module_version != NULL ? module_version : "NULL",
+                 module_location != NULL ? module_location : "NULL");
+    loader_data->print_value_on(logst);
+    logst->print_cr(", package #: %d", pkg_list->length());
+    for (int y = 0; y < pkg_list->length(); y++) {
+      log_trace(modules)("define_module(): creation of package %s for module %s",
+                         (pkg_list->at(y))->as_C_string(), module_name);
+    }
+  }
+
+  if (loader == NULL && !Universe::is_module_initialized()) {
+    // Now that the module is defined, if it is in the bootloader, make sure that
+    // its classes can be found.  Check if -Xpatch:<path> was specified.  If
+    // so prepend <path>/module_name, if it exists, to bootpath.  Also, if using
+    // exploded modules, prepend <java.home>/modules/module_name, if it exists,
+    // to bootpath.
+    add_to_boot_loader_list(module_name, CHECK);
+  }
+}
+
+void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle module_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(module_handle->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is not a subclass of java.lang.reflect.Module");
+  }
+
+  // Ensure that this is an unnamed module
+  oop name = java_lang_reflect_Module::name(module_handle());
+  if (name != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "boot loader's unnamed module's java.lang.reflect.Module has a name");
+  }
+
+  // Validate java_base's loader is the boot loader.
+  oop loader = java_lang_reflect_Module::loader(module_handle());
+  if (loader != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader must be the boot class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
+  log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
+
+  // Ensure the boot loader's PackageEntryTable has been created
+  ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
+
+  // Set java.lang.reflect.Module for the boot loader's unnamed module
+  ModuleEntry* unnamed_module = module_table->unnamed_module();
+  assert(unnamed_module != NULL, "boot loader's unnamed ModuleEntry not defined");
+  unnamed_module->set_module(ClassLoaderData::the_null_class_loader_data()->add_handle(module_handle));
+  // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module object.
+  java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
+}
+
+void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  if (from_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "from_module is null");
+  }
+  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
+  if (from_module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "from_module cannot be found");
+  }
+
+  // All packages in unnamed are exported by default.
+  if (!from_module_entry->is_named()) return;
+
+  ModuleEntry* to_module_entry;
+  if (to_module == NULL) {
+    to_module_entry = NULL;  // It's an unqualified export.
+  } else {
+    to_module_entry = get_module_entry(to_module, CHECK);
+    if (to_module_entry == NULL) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "to_module is invalid");
+    }
+  }
+
+  PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
+  ResourceMark rm(THREAD);
+  if (package_entry == NULL) {
+    const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s not found in from_module %s",
+                      package_name != NULL ? package_name : "",
+                      from_module_entry->name()->as_C_string()));
+  }
+  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()->name()->as_C_string(),
+                      from_module_entry->name()->as_C_string()));
+  }
+
+  log_debug(modules)("add_module_exports(): package %s in module %s is exported to module %s",
+                     package_entry->name()->as_C_string(),
+                     from_module_entry->name()->as_C_string(),
+                     to_module_entry == NULL ? "NULL" :
+                      to_module_entry->is_named() ?
+                        to_module_entry->name()->as_C_string() : UNNAMED_MODULE);
+
+  // Do nothing if modules are the same or if package is already exported unqualifiedly.
+  if (from_module_entry != to_module_entry && !package_entry->is_unqual_exported()) {
+    package_entry->set_exported(to_module_entry);
+  }
+}
+
+
+void Modules::add_module_exports_qualified(jobject from_module, jstring package,
+                                           jobject to_module, TRAPS) {
+  if (to_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "to_module is null");
+  }
+  add_module_exports(from_module, package, to_module, CHECK);
+}
+
+void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) {
+  if (from_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "from_module is null");
+  }
+
+  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
+  if (from_module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "from_module is not valid");
+  }
+
+  ModuleEntry* to_module_entry;
+  if (to_module != NULL) {
+    to_module_entry = get_module_entry(to_module, CHECK);
+    if (to_module_entry == NULL) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "to_module is invalid");
+    }
+  } else {
+    to_module_entry = NULL;
+  }
+
+  ResourceMark rm(THREAD);
+  log_debug(modules)("add_reads_module(): Adding read from module %s to module %s",
+                     from_module_entry->is_named() ?
+                     from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                     to_module_entry == NULL ? "all unnamed" :
+                       (to_module_entry->is_named() ?
+                        to_module_entry->name()->as_C_string() : UNNAMED_MODULE));
+
+  // if modules are the same or if from_module is unnamed then no need to add the read.
+  if (from_module_entry != to_module_entry && from_module_entry->is_named()) {
+    from_module_entry->add_read(to_module_entry);
+  }
+}
+
+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");
+
+  if (clazz == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "class is null", JNI_FALSE);
+  }
+  oop mirror = JNIHandles::resolve_non_null(clazz);
+  if (mirror == NULL) {
+    log_debug(modules)("get_module(): no mirror, returning NULL");
+    return NULL;
+  }
+  if (!java_lang_Class::is_instance(mirror)) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "Invalid class", JNI_FALSE);
+  }
+
+  oop module = java_lang_Class::module(mirror);
+
+  assert(module != NULL, "java.lang.Class module field not set");
+  assert(java_lang_reflect_Module::is_subclass(module->klass()), "Module is not a java.lang.reflect.Module");
+
+  if (log_is_enabled(Debug, modules)) {
+    ResourceMark rm(THREAD);
+    outputStream* logst = LogHandle(modules)::debug_stream();
+    Klass* klass = java_lang_Class::as_Klass(mirror);
+    oop module_name = java_lang_reflect_Module::name(module);
+    if (module_name != NULL) {
+      logst->print("get_module(): module ");
+      java_lang_String::print(module_name, tty);
+    } else {
+      logst->print("get_module(): Unamed Module");
+    }
+    if (klass != NULL) {
+      logst->print_cr(" for class %s", klass->external_name());
+    } else {
+      logst->print_cr(" for primitive class");
+    }
+  }
+
+  return JNIHandles::make_local(THREAD, module);
+}
+
+
+jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
+  ResourceMark rm(THREAD);
+  assert(ModuleEntryTable::javabase_defined(),
+         "Attempt to call get_module_from_pkg before java.base is defined");
+
+  if (NULL == package) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "package is null", JNI_FALSE);
+  }
+  const char* package_str =
+    java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  if (NULL == package_str) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "Invalid package", JNI_FALSE);
+  }
+
+  Handle h_loader (THREAD, JNIHandles::resolve(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", JNI_FALSE);
+  }
+
+  if (strlen(package_str) == 0) {
+    // Return the unnamed module
+    ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
+    if (NULL == module_table) return NULL;
+    const ModuleEntry* const unnamed_module = module_table->unnamed_module();
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
+
+  } else {
+    TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+    return get_module(package_sym, h_loader, CHECK_NULL);
+  }
+  return NULL;
+}
+
+
+// This method is called by JFR and by the above method.
+jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
+  const PackageEntry* const pkg_entry =
+    get_package_entry_by_name(package_name, h_loader, THREAD);
+  const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
+
+  if (module_entry != NULL &&
+      module_entry->module() != NULL) {
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
+  }
+
+  return NULL;
+}
+
+void Modules::add_module_package(jobject module, jstring package, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "module is null");
+  }
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  ModuleEntry* module_entry = get_module_entry(module, CHECK);
+  if (module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is invalid");
+  }
+  if (!module_entry->is_named()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module cannot be an unnamed module");
+  }
+  char *package_name = java_lang_String::as_utf8_string(
+    JNIHandles::resolve_non_null(package));
+  if (package_name == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
+  }
+  if (!verify_package_name(package_name)) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Invalid package name: %s", package_name));
+  }
+
+  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()->packages();
+  assert(package_table != NULL, "Missing package_table");
+
+  bool pkg_exists = false;
+  {
+    MutexLocker ml(Module_lock, THREAD);
+
+    // Check that the package does not exist in the class loader's package table.
+    if (!package_table->lookup_only(pkg_symbol)) {
+      PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
+      assert(pkg != NULL, "Unable to create a module's package entry");
+    } else {
+      pkg_exists = true;
+    }
+  }
+  if (pkg_exists) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s already exists for class loader", package_name));
+  }
+}
+
+// Export package in module to all unnamed modules.
+void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "module is null");
+  }
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  ModuleEntry* module_entry = get_module_entry(module, CHECK);
+  if (module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is invalid");
+  }
+
+  if (module_entry->is_named()) { // No-op for unnamed module.
+    PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+    ResourceMark rm(THREAD);
+    if (package_entry == NULL) {
+      const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Package %s not found in module %s",
+                        package_name != NULL ? package_name : "",
+                        module_entry->name()->as_C_string()));
+    }
+    if (package_entry->module() != module_entry) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Package: %s found in module %s, not in module: %s",
+                        package_entry->name()->as_C_string(),
+                        package_entry->module()->name()->as_C_string(),
+                        module_entry->name()->as_C_string()));
+    }
+
+    log_debug(modules)("add_module_exports_to_all_unnamed(): package %s in module"
+                       " %s is exported to all unnamed modules",
+                       package_entry->name()->as_C_string(),
+                       module_entry->name()->as_C_string());
+
+    // Mark package as exported to all unnamed modules, unless already
+    // unqualifiedly exported.
+    if (!package_entry->is_unqual_exported()) {
+      package_entry->set_is_exported_allUnnamed();
+    }
+  }
+}
diff --git a/hotspot/src/share/vm/classfile/modules.hpp b/hotspot/src/share/vm/classfile/modules.hpp
new file mode 100644
index 0000000..d8abd75
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/modules.hpp
@@ -0,0 +1,151 @@
+/*
+* 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.
+*
+*/
+
+#ifndef SHARE_VM_CLASSFILE_MODULES_HPP
+#define SHARE_VM_CLASSFILE_MODULES_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/handles.hpp"
+
+class Symbol;
+
+class Modules : AllStatic {
+
+public:
+  // define_module defines a module containing the specified packages. It binds the
+  // module to its class loader by creating the ModuleEntry record in the
+  // ClassLoader's ModuleEntry table, and creates PackageEntry records in the class
+  // loader's PackageEntry table.  As in JVM_DefineClass the jstring format for all
+  // package names must use "/" and not "."
+  //
+  //  IllegalArgumentExceptions are thrown for the following :
+  // * Module's Class loader is not a subclass of java.lang.ClassLoader
+  // * Module's Class loader already has a module with that name
+  // * Module's Class loader has already defined types for any of the module's packages
+  // * Module_name is syntactically bad
+  // * Packages contains an illegal package name
+  // * Packages contains a duplicate package name
+  // * A package already exists in another module for this class loader
+  // * Module is an unnamed module
+  //  NullPointerExceptions are thrown if module is null.
+  static void define_module(jobject module, jstring version,
+                            jstring location, jobjectArray packages, TRAPS);
+
+  // Provides the java.lang.reflect.Module for the unnamed module defined
+  // to the boot loader.
+  //
+  //  IllegalArgumentExceptions are thrown for the following :
+  //  * Module has a name
+  //  * Module is not a subclass of java.lang.reflect.Module
+  //  * Module's class loader is not the boot loader
+  //  NullPointerExceptions are thrown if module is null.
+  static void set_bootloader_unnamed_module(jobject module, TRAPS);
+
+  // This either does a qualified export of package in module from_module to module
+  // to_module or, if to_module is null, does an unqualified export of package.
+  // The format for the package name must use "/' not ".".
+  //
+  // Error conditions causing IlegalArgumentException to be throw :
+  // * Module from_module does not exist
+  // * Module to_module is not null and does not exist
+  // * Package is not syntactically correct
+  // * Package is not defined for from_module's class loader
+  // * Package is not in module from_module.
+  static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
+
+  // This does a qualified export of package in module from_module to module
+  // to_module.  The format for the package name must use "/' not ".".
+  //
+  // Error conditions causing IlegalArgumentException to be throw :
+  // * Module from_module does not exist
+  // * Module to_module does not exist
+  // * Package is not syntactically correct
+  // * Package is not defined for from_module's class loader
+  // * Package is not in module from_module.
+  static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
+
+  // add_reads_module adds module to_module to the list of modules that from_module
+  // can read.  If from_module is the same as to_module then this is a no-op.
+  // If to_module is null then from_module is marked as a loose module (meaning that
+  // from_module can read all current and future unnamed  modules).
+  // An IllegalArgumentException is thrown if from_module is null or either (non-null)
+  // 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);
+
+  // Return the java.lang.reflect.Module object for this class loader and package.
+  // Returns NULL if the class loader has not loaded any classes in the package.
+  // The package should contain /'s, not .'s, as in java/lang, not java.lang.
+  // NullPointerException is thrown if package is null.
+  // IllegalArgumentException is thrown if loader is neither null nor a subtype of
+  // java/lang/ClassLoader.
+  static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+
+  // If package is defined by loader, return the
+  // java.lang.reflect.Module object for the module in which the package is defined.
+  // Returns NULL if package is invalid or not defined by loader.
+  static jobject get_module(Symbol* package_name, Handle h_loader, TRAPS);
+
+  // This adds package to module.
+  // It throws IllegalArgumentException if:
+  // * Module is bad
+  // * Module is unnamed
+  // * Package is not syntactically correct
+  // * Package is already defined for module's class loader.
+  static void add_module_package(jobject module, jstring package, TRAPS);
+
+  // Marks the specified package as exported to all unnamed modules.
+  // If either module or package is null then NullPointerException is thrown.
+  // If module or package is bad, or module is unnamed, or package is not in
+  // module then IllegalArgumentException is thrown.
+  static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
+
+  // Return TRUE if package_name is syntactically valid, false otherwise.
+  static bool verify_package_name(char *package_name);
+
+  // Return TRUE iff package is defined by loader
+  static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
+};
+
+#endif // SHARE_VM_CLASSFILE_MODULES_HPP
diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp
new file mode 100644
index 0000000..b3117d4
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp
@@ -0,0 +1,322 @@
+/*
+ * 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 "precompiled.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/symbol.hpp"
+#include "runtime/handles.inline.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.inline.hpp"
+
+// Return true if this package is exported to m.
+bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
+  assert(m != NULL, "No module to lookup in this package's qualified exports list");
+  MutexLocker m1(Module_lock);
+  if (!_is_exported) {
+    return false;
+  } else if (_is_exported_allUnnamed && !m->is_named()) {
+    return true;
+  } else if (_qualified_exports == NULL) {
+    return false;
+  } else {
+    return _qualified_exports->contains(m);
+  }
+}
+
+// Add a module to the package's qualified export list.
+void PackageEntry::add_qexport(ModuleEntry* m) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(_is_exported == true, "Adding a qualified export to a package that is not exported");
+  if (_qualified_exports == NULL) {
+    // Lazily create a package's qualified exports list.
+    // Initial size is small, do not anticipate export lists to be large.
+    _qualified_exports =
+      new (ResourceObj::C_HEAP, mtClass) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
+  }
+  _qualified_exports->append_if_missing(m);
+}
+
+// Set the package's exported state based on the value of the ModuleEntry.
+void PackageEntry::set_exported(ModuleEntry* m) {
+  MutexLocker m1(Module_lock);
+  if (is_unqual_exported()) {
+    // An exception could be thrown, but choose to simply ignore.
+    // Illegal to convert an unqualified exported package to be qualifiedly exported
+    return;
+  }
+
+  if (m == NULL) {
+    // NULL indicates the package is being unqualifiedly exported
+    if (_is_exported && _qualified_exports != NULL) {
+      // Legit to transition a package from being qualifiedly exported
+      // to unqualified.  Clean up the qualified lists at the next
+      // safepoint.
+      _exported_pending_delete = _qualified_exports;
+    }
+
+    // Mark package as unqualifiedly exported
+    set_unqual_exported();
+
+  } else {
+    // Add the exported module
+    _is_exported = true;
+    add_qexport(m);
+  }
+}
+
+// Remove dead module entries within the package's exported list.
+void PackageEntry::purge_qualified_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (_qualified_exports != NULL) {
+    // Go backwards because this removes entries that are dead.
+    int len = _qualified_exports->length();
+    for (int idx = len - 1; idx >= 0; idx--) {
+      ModuleEntry* module_idx = _qualified_exports->at(idx);
+      ClassLoaderData* cld = module_idx->loader();
+      if (cld->is_unloading()) {
+        _qualified_exports->delete_at(idx);
+      }
+    }
+  }
+}
+
+void PackageEntry::delete_qualified_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (_exported_pending_delete != NULL) {
+    // If a transition occurred from qualified to unqualified, the _qualified_exports
+    // field should have been NULL'ed out.
+    assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
+    delete _exported_pending_delete;
+  }
+
+  if (_qualified_exports != NULL) {
+    delete _qualified_exports;
+  }
+
+  _exported_pending_delete = NULL;
+  _qualified_exports = NULL;
+}
+
+PackageEntryTable::PackageEntryTable(int table_size)
+  : Hashtable<Symbol*, mtClass>(table_size, sizeof(PackageEntry))
+{
+}
+
+PackageEntryTable::~PackageEntryTable() {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Walk through all buckets and all entries in each bucket,
+  // freeing each entry.
+  for (int i = 0; i < table_size(); ++i) {
+    for (PackageEntry* p = bucket(i); p != NULL;) {
+      PackageEntry* to_remove = p;
+      // read next before freeing.
+      p = p->next();
+
+      // Clean out the C heap allocated qualified exports list first before freeing the entry
+      to_remove->delete_qualified_exports();
+      to_remove->name()->decrement_refcount();
+
+      // Unlink from the Hashtable prior to freeing
+      unlink_entry(to_remove);
+      FREE_C_HEAP_ARRAY(char, to_remove);
+    }
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
+  free_buckets();
+}
+
+PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
+  assert_locked_or_safepoint(Module_lock);
+  PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass);
+
+  // Initialize everything BasicHashtable would
+  entry->set_next(NULL);
+  entry->set_hash(hash);
+  entry->set_literal(name);
+
+  TRACE_INIT_PACKAGE_ID(entry);
+
+  // Initialize fields specific to a PackageEntry
+  entry->init();
+  entry->name()->increment_refcount();
+  if (!module->is_named()) {
+    // Set the exported state to true because all packages
+    // within the unnamed module are unqualifiedly exported
+    entry->set_exported(true);
+  }
+  entry->set_module(module);
+  return entry;
+}
+
+void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) {
+  assert_locked_or_safepoint(Module_lock);
+  Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
+}
+
+// Create package in loader's package entry table and return the entry.
+// If entry already exists, return null.  Assume Module lock was taken by caller.
+PackageEntry* PackageEntryTable::locked_create_entry_or_null(Symbol* name, ModuleEntry* module) {
+  assert_locked_or_safepoint(Module_lock);
+  // Check if package already exists.  Return NULL if it does.
+  if (lookup_only(name) != NULL) {
+    return NULL;
+  } else {
+    PackageEntry* entry = new_entry(compute_hash(name), name, module);
+    add_entry(index_for(name), entry);
+    return entry;
+  }
+}
+
+PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
+  PackageEntry* p = lookup_only(name);
+  if (p != NULL) {
+    return p;
+  } else {
+    // If not found, add to table. Grab the PackageEntryTable lock first.
+    MutexLocker ml(Module_lock);
+
+    // Since look-up was done lock-free, we need to check if another thread beat
+    // us in the race to insert the package.
+    PackageEntry* test = lookup_only(name);
+    if (test != NULL) {
+      // A race occurred and another thread introduced the package.
+      return test;
+    } else {
+      assert(module != NULL, "module should never be null");
+      PackageEntry* entry = new_entry(compute_hash(name), name, module);
+      add_entry(index_for(name), entry);
+      return entry;
+    }
+  }
+}
+
+PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
+  int index = index_for(name);
+  for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
+    if (p->name()->fast_compare(name) == 0) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+// Called when a define module for java.base is being processed.
+// Verify the packages loaded thus far are in java.base's package list.
+void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* entry = bucket(i);
+                       entry != NULL;
+                       entry = entry->next()) {
+      ModuleEntry* m = entry->module();
+      Symbol* module_name = (m == NULL ? NULL : m->name());
+      if (module_name != NULL &&
+          (module_name->fast_compare(vmSymbols::java_base()) == 0) &&
+          !pkg_list->contains(entry->name())) {
+        ResourceMark rm;
+        vm_exit_during_initialization("A non-java.base package was loaded prior to module system initialization", entry->name()->as_C_string());
+      }
+    }
+  }
+
+}
+
+// Remove dead entries from all packages' exported list
+void PackageEntryTable::purge_all_package_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* entry = bucket(i);
+                       entry != NULL;
+                       entry = entry->next()) {
+      if (entry->exported_pending_delete()) {
+        // exported list is pending deletion due to a transition
+        // from qualified to unqualified
+        entry->delete_qualified_exports();
+      } else if (entry->is_qual_exported()) {
+        entry->purge_qualified_exports();
+      }
+    }
+  }
+}
+
+#ifndef PRODUCT
+void PackageEntryTable::print() {
+  tty->print_cr("Package Entry Table (table_size=%d, entries=%d)",
+                table_size(), number_of_entries());
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* probe = bucket(i);
+                       probe != NULL;
+                       probe = probe->next()) {
+      probe->print();
+    }
+  }
+}
+
+void PackageEntry::print() {
+  ResourceMark rm;
+  tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
+                INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
+                p2i(this), name()->as_C_string(),
+                (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
+                _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next()));
+}
+#endif
+
+void PackageEntryTable::verify() {
+  int element_count = 0;
+  for (int index = 0; index < table_size(); index++) {
+    for (PackageEntry* probe = bucket(index);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->verify();
+      element_count++;
+    }
+  }
+  guarantee(number_of_entries() == element_count,
+            "Verify of Package Entry Table failed");
+  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
+}
+
+void PackageEntry::verify() {
+  guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
+}
+
+// iteration of qualified exports
+void PackageEntry::package_exports_do(ModuleClosure* const f) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(f != NULL, "invariant");
+
+  if (is_qual_exported()) {
+    int qe_len = _qualified_exports->length();
+
+    for (int i = 0; i < qe_len; ++i) {
+      f->do_module(_qualified_exports->at(i));
+    }
+  }
+}
diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp
new file mode 100644
index 0000000..368609c
--- /dev/null
+++ b/hotspot/src/share/vm/classfile/packageEntry.hpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
+#define SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
+
+#include "classfile/moduleEntry.hpp"
+#include "oops/symbol.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.hpp"
+
+// A PackageEntry basically represents a Java package.  It contains:
+//   - Symbol* containing the package's name.
+//   - ModuleEntry* for this package's containing module.
+//   - a flag indicating if package is exported, either qualifiedly or
+//     unqualifiedly.
+//   - a flag indicating if this package is exported to all unnamed modules.
+//   - a growable array containing other module entries that this
+//     package is exported to.
+//
+// Packages that are:
+//   - not exported:        _qualified_exports = NULL  && _is_exported is false
+//   - qualified exports:   (_qualified_exports != NULL || _is_exported_allUnnamed is true) && _is_exported is true
+//   - unqualified exports: (_qualified_exports = NULL && _is_exported_allUnnamed is false) && _is_exported is true
+//
+// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
+// data structure.
+class PackageEntry : public HashtableEntry<Symbol*, mtClass> {
+private:
+  ModuleEntry* _module;
+  // Used to indicate for packages with classes loaded by the boot loader that
+  // a class in that package has been loaded.  And, for packages with classes
+  // loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
+  // indicates from which class path entry.
+  s2 _classpath_index;
+  bool _is_exported;
+  bool _is_exported_allUnnamed;
+  GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
+  GrowableArray<ModuleEntry*>* _qualified_exports;
+  TRACE_DEFINE_TRACE_ID_FIELD;
+
+  // Initial size of a package entry's list of qualified exports.
+  enum {QUAL_EXP_SIZE = 43};
+
+public:
+  void init() {
+    _module = NULL;
+    _classpath_index = -1;
+    _is_exported = false;
+    _is_exported_allUnnamed = false;
+    _exported_pending_delete = NULL;
+    _qualified_exports = NULL;
+  }
+
+  // package name
+  Symbol*            name() const               { return literal(); }
+  void               set_name(Symbol* n)        { set_literal(n); }
+
+  // the module containing the package definition
+  ModuleEntry*       module() const             { return _module; }
+  void               set_module(ModuleEntry* m) { _module = m; }
+
+  // package's export state
+  bool is_exported() const { return _is_exported; } // qualifiedly or unqualifiedly exported
+  bool is_qual_exported() const {
+    return (_is_exported && (_qualified_exports != NULL || _is_exported_allUnnamed));
+  }
+  bool is_unqual_exported() const {
+    return (_is_exported && (_qualified_exports == NULL && !_is_exported_allUnnamed));
+  }
+  void set_unqual_exported() {
+    _is_exported = true;
+    _is_exported_allUnnamed = false;
+    _qualified_exports = NULL;
+  }
+  bool exported_pending_delete() const     { return (_exported_pending_delete != NULL); }
+
+  void set_exported(bool e)                { _is_exported = e; }
+  void set_exported(ModuleEntry* m);
+
+  void set_is_exported_allUnnamed() {
+    if (!is_unqual_exported()) {
+     _is_exported_allUnnamed = true;
+     _is_exported = true;
+    }
+  }
+  bool is_exported_allUnnamed() const {
+    assert(_is_exported || !_is_exported_allUnnamed,
+           "is_allUnnamed set without is_exported being set");
+    return _is_exported_allUnnamed;
+  }
+
+  void set_classpath_index(s2 classpath_index) {
+    _classpath_index = classpath_index;
+  }
+  s2 classpath_index() const { return _classpath_index; }
+
+  bool has_loaded_class() const { return _classpath_index != -1; }
+
+  // returns true if the package is defined in the unnamed module
+  bool in_unnamed_module() const  { return !_module->is_named(); }
+
+  // returns true if the package specifies m as a qualified export
+  bool is_qexported_to(ModuleEntry* m) const;
+
+  // add the module to the package's qualified exports
+  void add_qexport(ModuleEntry* m);
+
+  PackageEntry* next() const {
+    return (PackageEntry*)HashtableEntry<Symbol*, mtClass>::next();
+  }
+
+  PackageEntry** next_addr() {
+    return (PackageEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
+  }
+
+  // iteration of qualified exports
+  void package_exports_do(ModuleClosure* const f);
+
+  TRACE_DEFINE_TRACE_ID_METHODS;
+
+  // Purge dead weak references out of exported list when any given class loader is unloaded.
+  void purge_qualified_exports();
+  void delete_qualified_exports();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+// The PackageEntryTable is a Hashtable containing a list of all packages defined
+// by a particular class loader.  Each package is represented as a PackageEntry node.
+// The PackageEntryTable's lookup is lock free.
+//
+class PackageEntryTable : public Hashtable<Symbol*, mtClass> {
+  friend class VMStructs;
+public:
+  enum Constants {
+    _packagetable_entry_size = 1009  // number of entries in package entry table
+  };
+
+private:
+  PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
+  void add_entry(int index, PackageEntry* new_entry);
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  PackageEntry** bucket_addr(int i) {
+    return (PackageEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
+  }
+
+  static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); }
+  int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
+
+public:
+  PackageEntryTable(int table_size);
+  ~PackageEntryTable();
+
+  PackageEntry* bucket(int i) {
+    return (PackageEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+
+  // Create package in loader's package entry table and return the entry.
+  // If entry already exists, return null.  Assume Module lock was taken by caller.
+  PackageEntry* locked_create_entry_or_null(Symbol* name, ModuleEntry* module);
+
+  // lookup Package with loader's package entry table, if not found add
+  PackageEntry* lookup(Symbol* name, ModuleEntry* module);
+
+  // Only lookup Package within loader's package entry table.  The table read is lock-free.
+  PackageEntry* lookup_only(Symbol* Package);
+
+  void verify_javabase_packages(GrowableArray<Symbol*> *pkg_list);
+
+  // purge dead weak references out of exported list
+  void purge_all_package_exports();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+#endif // SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp
index 4084370..939e136 100644
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp
@@ -77,7 +77,7 @@
   outputStream* out = LogHandle(classpath)::info_stream();
   switch (type) {
   case BOOT:
-    out->print("Expecting -Dsun.boot.class.path=%s", path);
+    out->print("Expecting BOOT path=%s", path);
     break;
   case NON_EXIST:
     out->print("Expecting that %s does not exist", path);
@@ -126,7 +126,7 @@
   switch (type) {
   case BOOT:
     if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
-      return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath());
+      return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath());
     }
     break;
   case NON_EXIST: // fall-through
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp
index 549182e..71f176b 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp
@@ -32,6 +32,7 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/klassFactory.hpp"
 #include "classfile/loaderConstraints.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/placeholders.hpp"
 #include "classfile/resolutionErrors.hpp"
 #include "classfile/stringTable.hpp"
@@ -51,6 +52,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "prims/jvmtiEnvBase.hpp"
 #include "prims/methodHandles.hpp"
@@ -171,13 +173,13 @@
 }
 
 /**
- * Returns true if the passed class loader is the extension class loader.
+ * Returns true if the passed class loader is the platform class loader.
  */
-bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
+bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
   if (class_loader.is_null()) {
     return false;
   }
-  return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
+  return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
 }
 
 // ----------------------------------------------------------------------------
@@ -1144,6 +1146,7 @@
   const char* pkg = "java/";
   if (!HAS_PENDING_EXCEPTION &&
       !class_loader.is_null() &&
+      !SystemDictionary::is_platform_class_loader(class_loader) &&
       parsed_name != NULL &&
       !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
     // It is illegal to define classes in the "java." package from
@@ -1236,13 +1239,88 @@
   instanceKlassHandle ik (THREAD, find_shared_class(class_name));
   // Make sure we only return the boot class for the NULL classloader.
   if (ik.not_null() &&
-      SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
+      ik->is_shared_boot_class() && class_loader.is_null()) {
     Handle protection_domain;
     return load_shared_class(ik, class_loader, protection_domain, THREAD);
   }
   return instanceKlassHandle();
 }
 
+// Check if a shared class can be loaded by the specific classloader:
+//
+// NULL classloader:
+//   - Module class from "modules" jimage. ModuleEntry must be defined in the classloader.
+//   - Class from -Xbootclasspath/a. The class has no defined PackageEntry, or must
+//     be defined in an unnamed module.
+bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
+                                               instanceKlassHandle ik,
+                                               Handle class_loader, TRAPS) {
+  int path_index = ik->shared_classpath_index();
+  SharedClassPathEntry* ent =
+            (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+  if (!Universe::is_module_initialized()) {
+    assert(ent->is_jrt(),
+           "Loading non-bootstrap classes before the module system is initialized");
+    assert(class_loader.is_null(), "sanity");
+    return true;
+  }
+  // Get the pkg_entry from the classloader
+  TempNewSymbol pkg_name = NULL;
+  PackageEntry* pkg_entry = NULL;
+  ModuleEntry* mod_entry = NULL;
+  int length = 0;
+  ClassLoaderData* loader_data = class_loader_data(class_loader);
+  const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+  if (pkg_string != NULL) {
+    pkg_name = SymbolTable::new_symbol((const char*)pkg_string,
+                                       length, CHECK_(false));
+    if (loader_data != NULL) {
+      pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+    }
+    if (pkg_entry != NULL) {
+      mod_entry = pkg_entry->module();
+    }
+  }
+
+  if (class_loader.is_null()) {
+    // The NULL classloader can load archived class originated from the
+    // "modules" jimage and the -Xbootclasspath/a. For class from the
+    // "modules" jimage, the PackageEntry/ModuleEntry must be defined
+    // by the NULL classloader.
+    if (mod_entry != NULL) {
+      // PackageEntry/ModuleEntry is found in the classloader. Check if the
+      // ModuleEntry's location agrees with the archived class' origination.
+      if (ent->is_jrt() && mod_entry->location()->starts_with("jrt:")) {
+        return true; // Module class from the "module" jimage
+      }
+    }
+
+    // If the archived class is not from the "module" jimage, the class can be
+    // loaded by the NULL classloader if
+    //
+    // 1. the class is from the unamed package
+    // 2. or, the class is not from a module defined in the NULL classloader
+    // 3. or, the class is from an unamed module
+    if (!ent->is_jrt() && ik->is_shared_boot_class()) {
+      // the class is from the -Xbootclasspath/a
+      if (pkg_string == NULL ||
+          pkg_entry == NULL ||
+          pkg_entry->in_unnamed_module()) {
+        assert(mod_entry == NULL ||
+               mod_entry == loader_data->modules()->unnamed_module(),
+               "the unnamed module is not defined in the classloader");
+        return true;
+      }
+    }
+    return false;
+  } else {
+    bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
+              ik, class_loader, pkg_string, pkg_name,
+              pkg_entry, mod_entry, CHECK_(false));
+    return res;
+  }
+}
+
 instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
                                                         Handle class_loader,
                                                         Handle protection_domain, TRAPS) {
@@ -1250,6 +1328,12 @@
     instanceKlassHandle nh = instanceKlassHandle(); // null Handle
     Symbol* class_name = ik->name();
 
+    bool visible = is_shared_class_visible(
+                            class_name, ik, class_loader, CHECK_(nh));
+    if (!visible) {
+      return nh;
+    }
+
     // Found the class, now load the superclass and interfaces.  If they
     // are shared, add them to the main system dictionary and reset
     // their hierarchy references (supers, subs, and interfaces).
@@ -1303,12 +1387,20 @@
     }
 
     if (log_is_enabled(Info, classload)) {
-      ik()->print_loading_log(LogLevel::Info, loader_data, NULL);
+      ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);
     }
     // No 'else' here as logging levels are not mutually exclusive
 
     if (log_is_enabled(Debug, classload)) {
-      ik()->print_loading_log(LogLevel::Debug, loader_data, NULL);
+      ik()->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL);
+    }
+
+    // For boot loader, ensure that GetSystemPackage knows that a class in this
+    // package was loaded.
+    if (class_loader.is_null()) {
+      int path_index = ik->shared_classpath_index();
+      ResourceMark rm;
+      ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
     }
 
     if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
@@ -1329,7 +1421,68 @@
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
+
   if (class_loader.is_null()) {
+    int length = 0;
+    PackageEntry* pkg_entry = NULL;
+    bool search_only_bootloader_append = false;
+    ClassLoaderData *loader_data = class_loader_data(class_loader);
+
+    // Find the package in the boot loader's package entry table.
+    const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+    if (pkg_string != NULL) {
+      TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, CHECK_(nh));
+      pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+    }
+
+    // Prior to attempting to load the class, enforce the boot loader's
+    // visibility boundaries.
+    if (!Universe::is_module_initialized()) {
+      // During bootstrapping, prior to module initialization, any
+      // class attempting to be loaded must be checked against the
+      // java.base packages in the boot loader's PackageEntryTable.
+      // No class outside of java.base is allowed to be loaded during
+      // this bootstrapping window.
+      if (!DumpSharedSpaces) {
+        if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+          // Class is either in the unnamed package or in
+          // a named package within the unnamed module.  Either
+          // case is outside of java.base, do not attempt to
+          // load the class post java.base definition.  If
+          // java.base has not been defined, let the class load
+          // and its package will be checked later by
+          // ModuleEntryTable::verify_javabase_packages.
+          if (ModuleEntryTable::javabase_defined()) {
+            return nh;
+          }
+        } else {
+          // Check that the class' package is defined within java.base.
+          ModuleEntry* mod_entry = pkg_entry->module();
+          Symbol* mod_entry_name = mod_entry->name();
+          if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {
+            return nh;
+          }
+        }
+      }
+    } else {
+      assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
+      // After the module system has been initialized, check if the class'
+      // package is in a module defined to the boot loader.
+      if (pkg_string == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+        // Class is either in the unnamed package, in a named package
+        // within a module not defined to the boot loader or in a
+        // a named package within the unnamed module.  In all cases,
+        // limit visibility to search for the class only in the boot
+        // loader's append path.
+        search_only_bootloader_append = true;
+      }
+    }
+
+    // Prior to bootstrapping's module initialization, never load a class outside
+    // of the boot loader's module path
+    assert(Universe::is_module_initialized() || DumpSharedSpaces ||
+           !search_only_bootloader_append,
+           "Attempt to load a class outside of boot loader's module path");
 
     // Search the shared system dictionary for classes preloaded into the
     // shared spaces.
@@ -1344,7 +1497,7 @@
     if (k.is_null()) {
       // Use VM class loader
       PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
-      k = ClassLoader::load_class(class_name, CHECK_(nh));
+      k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh));
     }
 
     // find_or_define_instance_class may return a different InstanceKlass
@@ -1669,7 +1822,7 @@
 }
 
 
-// Get the next class in the diictionary.
+// Get the next class in the dictionary.
 Klass* SystemDictionary::try_get_next_class() {
   return dictionary()->try_get_next_class();
 }
@@ -1940,6 +2093,11 @@
 
 void SystemDictionary::initialize_preloaded_classes(TRAPS) {
   assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
+
+  // Create the ModuleEntry for java.base.  This call needs to be done here,
+  // after vmSymbols::initialize() is called but before any classes are pre-loaded.
+  ClassLoader::create_javabase();
+
   // Preload commonly used klasses
   WKID scan = FIRST_WKID;
   // first do Object, then String, Class
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp
index 628895f..1e14832 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp
@@ -135,6 +135,7 @@
   do_klass(Properties_klass,                            java_util_Properties,                      Pre                 ) \
   do_klass(reflect_AccessibleObject_klass,              java_lang_reflect_AccessibleObject,        Pre                 ) \
   do_klass(reflect_Field_klass,                         java_lang_reflect_Field,                   Pre                 ) \
+  do_klass(reflect_Module_klass,                        java_lang_reflect_Module,                  Pre                 ) \
   do_klass(reflect_Parameter_klass,                     java_lang_reflect_Parameter,               Opt                 ) \
   do_klass(reflect_Method_klass,                        java_lang_reflect_Method,                  Pre                 ) \
   do_klass(reflect_Constructor_klass,                   java_lang_reflect_Constructor,             Pre                 ) \
@@ -167,15 +168,17 @@
   do_klass(StringBuffer_klass,                          java_lang_StringBuffer,                    Pre                 ) \
   do_klass(StringBuilder_klass,                         java_lang_StringBuilder,                   Pre                 ) \
   do_klass(internal_Unsafe_klass,                       jdk_internal_misc_Unsafe,                  Pre                 ) \
+  do_klass(module_Modules_klass,                        jdk_internal_module_Modules,               Pre                 ) \
                                                                                                                          \
   /* support for CDS */                                                                                                  \
   do_klass(ByteArrayInputStream_klass,                  java_io_ByteArrayInputStream,              Pre                 ) \
   do_klass(File_klass,                                  java_io_File,                              Pre                 ) \
-  do_klass(URLClassLoader_klass,                        java_net_URLClassLoader,                   Pre                 ) \
   do_klass(URL_klass,                                   java_net_URL,                              Pre                 ) \
   do_klass(Jar_Manifest_klass,                          java_util_jar_Manifest,                    Pre                 ) \
-  do_klass(sun_misc_Launcher_klass,                     sun_misc_Launcher,                         Pre                 ) \
+  do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass,      jdk_internal_loader_ClassLoaders_AppClassLoader,       Pre ) \
+  do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader,  Pre ) \
   do_klass(CodeSource_klass,                            java_security_CodeSource,                  Pre                 ) \
+  do_klass(ParseUtil_klass,                             sun_net_www_ParseUtil,                     Pre                 ) \
                                                                                                                          \
   do_klass(StackTraceElement_klass,                     java_lang_StackTraceElement,               Opt                 ) \
                                                                                                                          \
@@ -639,6 +642,8 @@
   static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
                                                 Handle class_loader,
                                                 instanceKlassHandle k, TRAPS);
+  static bool is_shared_class_visible(Symbol* class_name, instanceKlassHandle ik,
+                                      Handle class_loader, TRAPS);
   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
                                                Handle class_loader,
                                                Handle protection_domain,
@@ -653,7 +658,7 @@
   static instanceKlassHandle load_shared_class(Symbol* class_name,
                                                Handle class_loader,
                                                TRAPS);
-  static bool is_ext_class_loader(Handle class_loader);
+  static bool is_platform_class_loader(Handle class_loader);
 
 protected:
   static Klass* find_shared_class(Symbol* class_name);
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
index 8ada714..50b5dd8 100644
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
@@ -44,6 +44,16 @@
     oop class_loader = loader_data->class_loader();
     return (class_loader == NULL);
   }
+  static bool is_shared_class_visible_for_classloader(
+                                      instanceKlassHandle ik,
+                                      Handle class_loader,
+                                      const jbyte* pkg_string,
+                                      Symbol* pkg_name,
+                                      PackageEntry* pkg_entry,
+                                      ModuleEntry* mod_entry,
+                                      TRAPS) {
+    return false;
+  }
 
   static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
                                                 Symbol* class_name,
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 9323389..1119894 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -49,10 +49,12 @@
 // Mapping function names to values. New entries should be added below.
 
 #define VM_SYMBOLS_DO(template, do_alias)                                                         \
-  /* commonly used class names */                                                                 \
+  /* commonly used class, package, module names */                                                \
+  template(java_base,                                 "java.base")                                \
   template(java_lang_System,                          "java/lang/System")                         \
   template(java_lang_Object,                          "java/lang/Object")                         \
   template(java_lang_Class,                           "java/lang/Class")                          \
+  template(java_lang_Package,                         "java/lang/Package")                        \
   template(java_lang_String,                          "java/lang/String")                         \
   template(java_lang_StringLatin1,                    "java/lang/StringLatin1")                   \
   template(java_lang_StringUTF16,                     "java/lang/StringUTF16")                    \
@@ -87,6 +89,7 @@
   template(java_lang_reflect_Method,                  "java/lang/reflect/Method")                 \
   template(java_lang_reflect_Constructor,             "java/lang/reflect/Constructor")            \
   template(java_lang_reflect_Field,                   "java/lang/reflect/Field")                  \
+  template(java_lang_reflect_Module,                  "java/lang/reflect/Module")                 \
   template(java_lang_reflect_Parameter,               "java/lang/reflect/Parameter")              \
   template(java_lang_reflect_Array,                   "java/lang/reflect/Array")                  \
   template(java_lang_StringBuffer,                    "java/lang/StringBuffer")                   \
@@ -97,7 +100,6 @@
   template(java_security_CodeSource,                  "java/security/CodeSource")                 \
   template(java_security_ProtectionDomain,            "java/security/ProtectionDomain")           \
   template(java_security_SecureClassLoader,           "java/security/SecureClassLoader")          \
-  template(java_net_URLClassLoader,                   "java/net/URLClassLoader")                  \
   template(java_net_URL,                              "java/net/URL")                             \
   template(java_util_jar_Manifest,                    "java/util/jar/Manifest")                   \
   template(impliesCreateAccessControlContext_name,    "impliesCreateAccessControlContext")        \
@@ -116,17 +118,25 @@
   template(java_util_Hashtable,                       "java/util/Hashtable")                      \
   template(java_lang_Compiler,                        "java/lang/Compiler")                       \
   template(jdk_internal_misc_Signal,                  "jdk/internal/misc/Signal")                 \
-  template(sun_misc_Launcher,                         "sun/misc/Launcher")                        \
   template(java_lang_AssertionStatusDirectives,       "java/lang/AssertionStatusDirectives")      \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
   template(sun_misc_PostVMInitHook,                   "sun/misc/PostVMInitHook")                  \
-  template(sun_misc_Launcher_ExtClassLoader,          "sun/misc/Launcher$ExtClassLoader")         \
+  template(sun_net_www_ParseUtil,                     "sun/net/www/ParseUtil")                    \
+                                                                                                  \
+  template(jdk_internal_loader_ClassLoaders_AppClassLoader,      "jdk/internal/loader/ClassLoaders$AppClassLoader")      \
+  template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \
                                                                                                   \
   /* Java runtime version access */                                                               \
   template(java_lang_VersionProps,                    "java/lang/VersionProps")                   \
   template(java_runtime_name_name,                    "java_runtime_name")                        \
   template(java_runtime_version_name,                 "java_runtime_version")                     \
                                                                                                   \
+  /* system initialization */                                                                     \
+  template(initPhase1_name,                           "initPhase1")                               \
+  template(initPhase2_name,                           "initPhase2")                               \
+  template(initPhase3_name,                           "initPhase3")                               \
+  template(java_lang_reflect_module_init_signature,   "(Ljava/lang/ClassLoader;Ljava/lang/String;)V") \
+                                                                                                  \
   /* class file format tags */                                                                    \
   template(tag_source_file,                           "SourceFile")                               \
   template(tag_inner_classes,                         "InnerClasses")                             \
@@ -360,7 +370,6 @@
   template(run_finalization_name,                     "runFinalization")                          \
   template(run_finalizers_on_exit_name,               "runFinalizersOnExit")                      \
   template(dispatchUncaughtException_name,            "dispatchUncaughtException")                \
-  template(initializeSystemClass_name,                "initializeSystemClass")                    \
   template(loadClass_name,                            "loadClass")                                \
   template(loadClassInternal_name,                    "loadClassInternal")                        \
   template(get_name,                                  "get")                                      \
@@ -446,14 +455,22 @@
   template(signers_name,                              "signers_name")                             \
   template(loader_data_name,                          "loader_data")                              \
   template(vmdependencies_name,                       "vmdependencies")                           \
+  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(getFileURL_name,                           "getFileURL")                               \
-  template(getFileURL_signature,                      "(Ljava/io/File;)Ljava/net/URL;")           \
-  template(definePackageInternal_name,                "definePackageInternal")                    \
-  template(definePackageInternal_signature,           "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
+  template(definePackage_name,                        "definePackage")                            \
+  template(definePackage_signature,                   "(Ljava/lang/String;Ljava/lang/reflect/Module;)Ljava/lang/Package;") \
+  template(defineOrCheckPackage_name,                 "defineOrCheckPackage")                     \
+  template(defineOrCheckPackage_signature,            "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \
+  template(fileToEncodedURL_name,                     "fileToEncodedURL")                         \
+  template(fileToEncodedURL_signature,                "(Ljava/io/File;)Ljava/net/URL;")           \
   template(getProtectionDomain_name,                  "getProtectionDomain")                      \
   template(getProtectionDomain_signature,             "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
   template(url_code_signer_array_void_signature,      "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
+  template(module_entry_name,                         "module_entry")                             \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -531,6 +548,7 @@
   template(void_class_signature,                      "()Ljava/lang/Class;")                                      \
   template(void_class_array_signature,                "()[Ljava/lang/Class;")                                     \
   template(void_string_signature,                     "()Ljava/lang/String;")                                     \
+  template(void_module_signature,                     "()Ljava/lang/reflect/Module;")                             \
   template(object_array_object_signature,             "([Ljava/lang/Object;)Ljava/lang/Object;")                  \
   template(object_object_array_object_signature,      "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
   template(exception_void_signature,                  "(Ljava/lang/Exception;)V")                                 \
@@ -550,6 +568,7 @@
   template(reference_signature,                       "Ljava/lang/ref/Reference;")                                \
   template(sun_misc_Cleaner_signature,                "Lsun/misc/Cleaner;")                                       \
   template(executable_signature,                      "Ljava/lang/reflect/Executable;")                           \
+  template(module_signature,                          "Ljava/lang/reflect/Module;")                               \
   template(concurrenthashmap_signature,               "Ljava/util/concurrent/ConcurrentHashMap;")                 \
   template(String_StringBuilder_signature,            "(Ljava/lang/String;)Ljava/lang/StringBuilder;")            \
   template(int_StringBuilder_signature,               "(I)Ljava/lang/StringBuilder;")                             \
@@ -574,6 +593,9 @@
   /* used to identify class loaders handling parallel class loading */                                            \
   template(parallelCapable_name,                      "parallelLockMap")                                          \
                                                                                                                   \
+  /* used to return a class loader's unnamed module */                                                            \
+  template(unnamedModule_name,                        "unnamedModule")                                            \
+                                                                                                                  \
   /* JVM monitoring and management support */                                                                     \
   template(java_lang_StackTraceElement_array,          "[Ljava/lang/StackTraceElement;")                          \
   template(java_lang_management_ThreadState,           "java/lang/management/ThreadState")                        \
@@ -632,7 +654,10 @@
   template(addThreadDumpForSynchronizers_signature,    "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V")   \
                                                                                                                   \
   /* JVMTI/java.lang.instrument support and VM Attach mechanism */                                                \
+  template(jdk_internal_module_Modules,                "jdk/internal/module/Modules")                             \
   template(sun_misc_VMSupport,                         "sun/misc/VMSupport")                                      \
+  template(transformedByAgent_name,                    "transformedByAgent")                                      \
+  template(transformedByAgent_signature,               "(Ljava/lang/reflect/Module;)V")                           \
   template(appendToClassPathForInstrumentation_name,   "appendToClassPathForInstrumentation")                     \
   do_alias(appendToClassPathForInstrumentation_signature, string_void_signature)                                  \
   template(serializePropertiesToByteArray_name,        "serializePropertiesToByteArray")                          \
@@ -1063,11 +1088,6 @@
    do_name(     isCompileConstant_name,                          "isCompileConstant")                                   \
    do_alias(    isCompileConstant_signature,                      object_boolean_signature)                             \
                                                                                                                         \
-  do_class(sun_hotspot_WhiteBox,                                 "sun/hotspot/WhiteBox")                                \
-  do_intrinsic(_deoptimize,          sun_hotspot_WhiteBox,        deoptimize_name, deoptimize_signature, F_R)           \
-   do_name(     deoptimize_name,                                 "deoptimize")                                          \
-   do_alias(    deoptimize_signature,                             void_method_signature)                                \
-                                                                                                                        \
   /* unsafe memory references (there are a lot of them...) */                                                           \
   do_signature(getObject_signature,       "(Ljava/lang/Object;J)Ljava/lang/Object;")                                    \
   do_signature(putObject_signature,       "(Ljava/lang/Object;JLjava/lang/Object;)V")                                   \
diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
index 83e6a21..983b0b7 100644
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
@@ -2258,10 +2258,8 @@
               // Decrement counter at checkcast.
               BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
               ResourceMark rm(THREAD);
-              const char* objName = objKlass->external_name();
-              const char* klassName = klassOf->external_name();
               char* message = SharedRuntime::generate_class_cast_message(
-                objName, klassName);
+                objKlass, klassOf);
               VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
             }
             // Profile checkcast with null_seen and receiver.
diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
index 839eec6..acc4533 100644
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
@@ -384,7 +384,7 @@
 
   ResourceMark rm(thread);
   char* message = SharedRuntime::generate_class_cast_message(
-    thread, obj->klass()->external_name());
+    thread, obj->klass());
 
   if (ProfileTraps) {
     note_trap(thread, Deoptimization::Reason_class_check, CHECK);
diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp
index 7e3c60b..5c7e9b1 100644
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp
@@ -273,18 +273,25 @@
 // Klass resolution
 
 void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
-  if (!Reflection::verify_class_access(ref_klass(),
-                                       sel_klass(),
-                                       true)) {
+  Reflection::VerifyClassAccessResults vca_result =
+    Reflection::verify_class_access(ref_klass(), sel_klass(), true);
+  if (vca_result != Reflection::ACCESS_OK) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_IllegalAccessError(),
-      "tried to access class %s from class %s",
-      sel_klass->external_name(),
-      ref_klass->external_name()
-    );
-    return;
+    char* msg = Reflection::verify_class_access_msg(ref_klass(), sel_klass(), vca_result);
+    if (msg == NULL) {
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IllegalAccessError(),
+        "failed to access class %s from class %s",
+        sel_klass->external_name(),
+        ref_klass->external_name());
+    } else {
+      // Use module specific message returned by verify_class_access_msg().
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IllegalAccessError(),
+        "%s", msg);
+    }
   }
 }
 
diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
index b19a396..68d4a05 100644
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
@@ -77,7 +77,9 @@
     resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
   }
   if (resolved_klass->is_instance_klass()) {
-    return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+    Reflection::VerifyClassAccessResults result =
+      Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+    return result == Reflection::ACCESS_OK;
   }
   return true;
 }
diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp
index d292c83..c7fb0a0 100644
--- a/hotspot/src/share/vm/logging/logTag.hpp
+++ b/hotspot/src/share/vm/logging/logTag.hpp
@@ -62,6 +62,7 @@
   LOG_TAG(logging) \
   LOG_TAG(marking) \
   LOG_TAG(metaspace) \
+  LOG_TAG(modules) \
   LOG_TAG(monitorinflation) \
   LOG_TAG(os) \
   LOG_TAG(phases) \
diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp
index 1b21736..0f6415e 100644
--- a/hotspot/src/share/vm/memory/filemap.cpp
+++ b/hotspot/src/share/vm/memory/filemap.cpp
@@ -226,12 +226,21 @@
           SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
         } else {
           struct stat st;
-          if ((os::stat(name, &st) == 0) && ((st.st_mode & S_IFDIR) == S_IFDIR)) {
-            if (!os::dir_is_empty(name)) {
-              ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
+          if (os::stat(name, &st) == 0) {
+            if (cpe->is_jrt()) {
+              // it's the "modules" jimage
+              ent->_timestamp = st.st_mtime;
+              ent->_filesize = st.st_size;
+            } else if ((st.st_mode & S_IFDIR) == S_IFDIR) {
+              if (!os::dir_is_empty(name)) {
+                ClassLoader::exit_with_path_failure(
+                  "Cannot have non-empty directory in archived classpaths", name);
+              }
+              ent->_filesize = -1;
             }
-            ent->_filesize = -1;
-          } else {
+          }
+          if (ent->_filesize == 0) {
+            // unknown
             ent->_filesize = -2;
           }
         }
@@ -282,7 +291,7 @@
         fail_continue("directory is not empty: %s", name);
         ok = false;
       }
-    } else if (ent->is_jar()) {
+    } else if (ent->is_jar_or_bootimage()) {
       if (ent->_timestamp != st.st_mtime ||
           ent->_filesize != st.st_size) {
         ok = false;
@@ -291,7 +300,7 @@
                         "Timestamp mismatch" :
                         "File size mismatch");
         } else {
-          fail_continue("A jar file is not the one used while building"
+          fail_continue("A jar/jimage file is not the one used while building"
                         " the shared archive file: %s", name);
         }
       }
@@ -871,6 +880,11 @@
     return false;
   }
 
+  if (Arguments::patch_dirs() != NULL) {
+    FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
+    return false;
+  }
+
   if (_version != current_version()) {
     FileMapInfo::fail_continue("The shared archive file is the wrong version.");
     return false;
diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp
index 9752e5d..7cb1794 100644
--- a/hotspot/src/share/vm/memory/filemap.hpp
+++ b/hotspot/src/share/vm/memory/filemap.hpp
@@ -44,14 +44,20 @@
 class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
 public:
   const char *_name;
-  time_t _timestamp;          // jar timestamp,  0 if is directory or other
-  long   _filesize;           // jar file size, -1 if is directory, -2 if other
-  bool is_jar() {
+  time_t _timestamp;          // jar/jimage timestamp,  0 if is directory or other
+  long   _filesize;           // jar/jimage file size, -1 if is directory, -2 if other
+
+  // The _timestamp only gets set for jar files and "modules" jimage.
+  bool is_jar_or_bootimage() {
     return _timestamp != 0;
   }
   bool is_dir() {
     return _filesize == -1;
   }
+
+  bool is_jrt() {
+    return ClassLoader::is_jrt(_name);
+  }
 };
 
 class FileMapInfo : public CHeapObj<mtInternal> {
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index 3f10488..dc4fc08 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -603,14 +603,7 @@
   SystemDictionary::reverse();
   SystemDictionary::copy_buckets(&md_top, md_end);
 
-  ClassLoader::verify();
-  ClassLoader::copy_package_info_buckets(&md_top, md_end);
-  ClassLoader::verify();
-
   SystemDictionary::copy_table(&md_top, md_end);
-  ClassLoader::verify();
-  ClassLoader::copy_package_info_table(&md_top, md_end);
-  ClassLoader::verify();
 
   // Write the other data to the output array.
   WriteClosure wc(md_top, md_end);
@@ -716,8 +709,7 @@
 }
 
 
-void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
-  Klass* k = obj;
+void MetaspaceShared::link_one_shared_class(Klass* k, TRAPS) {
   if (k->is_instance_klass()) {
     InstanceKlass* ik = InstanceKlass::cast(k);
     // Link the class to cause the bytecodes to be rewritten and the
@@ -734,6 +726,16 @@
   }
 }
 
+void MetaspaceShared::check_shared_class_loader_type(Klass* k) {
+  if (k->is_instance_klass()) {
+    InstanceKlass* ik = InstanceKlass::cast(k);
+    u2 loader_type = ik->loader_type();
+    ResourceMark rm;
+    guarantee(loader_type != 0,
+              "Class loader type is not set for this class %s", ik->name()->as_C_string());
+  }
+}
+
 void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
   // We need to iterate because verification may cause additional classes
   // to be loaded.
@@ -765,6 +767,7 @@
 }
 
 void MetaspaceShared::prepare_for_dumping() {
+  Arguments::check_unsupported_dumping_properties();
   ClassLoader::initialize_shared_path();
   FileMapInfo::allocate_classpath_entry_table();
 }
@@ -901,7 +904,7 @@
   assert(DumpSharedSpaces, "should only be called during dumping");
   if (ik->init_state() < InstanceKlass::linked) {
     bool saved = BytecodeVerificationLocal;
-    if (!SharedClassUtil::is_shared_boot_class(ik)) {
+    if (!(ik->is_shared_boot_class())) {
       // The verification decision is based on BytecodeVerificationRemote
       // for non-system classes. Since we are using the NULL classloader
       // to load non-system classes during dumping, we need to temporarily
@@ -1089,36 +1092,14 @@
                                           number_of_entries);
   buffer += sharedDictionaryLen;
 
-  // Create the package info table using the bucket array at this spot in
-  // the misc data space.  Since the package info table is never
-  // modified, this region (of mapped pages) will be (effectively, if
-  // not explicitly) read-only.
-
-  int pkgInfoLen = *(intptr_t*)buffer;
-  buffer += sizeof(intptr_t);
-  number_of_entries = *(intptr_t*)buffer;
-  buffer += sizeof(intptr_t);
-  ClassLoader::create_package_info_table((HashtableBucket<mtClass>*)buffer, pkgInfoLen,
-                                         number_of_entries);
-  buffer += pkgInfoLen;
-  ClassLoader::verify();
-
   // The following data in the shared misc data region are the linked
   // list elements (HashtableEntry objects) for the shared dictionary
-  // and package info table.
+  // table.
 
   int len = *(intptr_t*)buffer;     // skip over shared dictionary entries
   buffer += sizeof(intptr_t);
   buffer += len;
 
-  len = *(intptr_t*)buffer;     // skip over package info table entries
-  buffer += sizeof(intptr_t);
-  buffer += len;
-
-  len = *(intptr_t*)buffer;     // skip over package info table char[] arrays.
-  buffer += sizeof(intptr_t);
-  buffer += len;
-
   intptr_t* array = (intptr_t*)buffer;
   ReadClosure rc(&array);
   serialize(&rc);
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp
index dac447c..c78f781 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp
@@ -208,6 +208,7 @@
   static bool try_link_class(InstanceKlass* ik, TRAPS);
   static void link_one_shared_class(Klass* obj, TRAPS);
   static void check_one_shared_class(Klass* obj);
+  static void check_shared_class_loader_type(Klass* obj);
   static void link_and_cleanup_shared_classes(TRAPS);
 
   static int count_class(const char* classlist_file);
diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp
index 3a79457..60a60e2 100644
--- a/hotspot/src/share/vm/memory/universe.cpp
+++ b/hotspot/src/share/vm/memory/universe.cpp
@@ -155,6 +155,7 @@
 
 int             Universe::_base_vtable_size = 0;
 bool            Universe::_bootstrapping = false;
+bool            Universe::_module_initialized = false;
 bool            Universe::_fully_initialized = false;
 
 size_t          Universe::_heap_capacity_at_last_gc;
@@ -667,7 +668,6 @@
   } else {
     SymbolTable::create_table();
     StringTable::create_table();
-    ClassLoader::create_package_info_table();
 
     if (DumpSharedSpaces) {
       MetaspaceShared::prepare_for_dumping();
@@ -886,6 +886,10 @@
   Universe::genesis(CATCH);
 }
 
+// Set after initialization of the module runtime, call_initModuleRuntime
+void universe_post_module_init() {
+  Universe::_module_initialized = true;
+}
 
 bool universe_post_init() {
   assert(!is_init_completed(), "Error: initialization not yet completed!");
diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp
index fe10e84..340e87f 100644
--- a/hotspot/src/share/vm/memory/universe.hpp
+++ b/hotspot/src/share/vm/memory/universe.hpp
@@ -111,6 +111,7 @@
   friend jint  universe_init();
   friend void  universe2_init();
   friend bool  universe_post_init();
+  friend void  universe_post_module_init();
 
  private:
   // Known classes in the VM
@@ -205,6 +206,7 @@
 
   // Initialization
   static bool _bootstrapping;                         // true during genesis
+  static bool _module_initialized;                    // true after call_initPhase2 called
   static bool _fully_initialized;                     // true after universe_init and initialize_vtables called
 
   // the array of preallocated errors with backtraces
@@ -436,6 +438,7 @@
 
   // Testers
   static bool is_bootstrapping()                      { return _bootstrapping; }
+  static bool is_module_initialized()                 { return _module_initialized; }
   static bool is_fully_initialized()                  { return _fully_initialized; }
 
   static inline bool element_type_should_be_aligned(BasicType type);
diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp
index 2278ce9..50d5e04 100644
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp
@@ -95,11 +95,18 @@
 
 // Initialization of vtables and mirror object is done separatly from base_create_array_klass,
 // since a GC can happen. At this point all instance variables of the ArrayKlass must be setup.
-void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS) {
+void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module_entry, TRAPS) {
   ResourceMark rm(THREAD);
   k->initialize_supers(super_klass(), CHECK);
   k->vtable()->initialize_vtable(false, CHECK);
-  java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(NULL), CHECK);
+
+  // During bootstrapping, before java.base is defined, the module_entry may not be present yet.
+  // These classes will be put on a fixup list and their module fields will be patched once
+  // java.base is defined.
+  assert((module_entry != NULL) || ((module_entry == NULL) && !ModuleEntryTable::javabase_defined()),
+         "module entry not available post java.base definition");
+  oop module = (module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL;
+  java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(NULL), CHECK);
 }
 
 GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp
index b98a092..3761229 100644
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp
@@ -113,7 +113,7 @@
   void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
 
   // Return a handle.
-  static void     complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS);
+  static void     complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module, TRAPS);
 
 
   // jvm support
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index d1297af..f526756 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1972,8 +1972,9 @@
 }
 
 void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
-  Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
   instanceKlassHandle ik(THREAD, this);
+  ik->set_package(loader_data, CHECK);
+  Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
 
   Array<Method*>* methods = ik->methods();
   int num_methods = methods->length();
@@ -2178,26 +2179,135 @@
   return dest;
 }
 
-// different verisons of is_same_class_package
-bool InstanceKlass::is_same_class_package(const Klass* class2) const {
-  const Klass* const class1 = (const Klass* const)this;
-  oop classloader1 = InstanceKlass::cast(class1)->class_loader();
-  const Symbol* const classname1 = class1->name();
+const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
+  ResourceMark rm;
+  length = 0;
+  if (name == NULL) {
+    return NULL;
+  } else {
+    const jbyte* base_name = name->base();
+    const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
 
+    if (last_slash == NULL) {
+      // No package name
+      return NULL;
+    } else {
+      // Skip over '['s
+      if (*base_name == '[') {
+        do {
+          base_name++;
+        } while (*base_name == '[');
+        if (*base_name != 'L') {
+          // Fully qualified class names should not contain a 'L'.
+          // Set length to -1 to indicate that the package name
+          // could not be obtained due to an error condition.
+          // In this situtation, is_same_class_package returns false.
+          length = -1;
+          return NULL;
+        }
+      }
+
+      // Found the package name, look it up in the symbol table.
+      length = last_slash - base_name;
+      assert(length > 0, "Bad length for package name");
+      return base_name;
+    }
+  }
+}
+
+ModuleEntry* InstanceKlass::module() const {
+  if (!in_unnamed_package()) {
+    return _package_entry->module();
+  }
+  const Klass* host = host_klass();
+  if (host == NULL) {
+    return class_loader_data()->modules()->unnamed_module();
+  }
+  return host->class_loader_data()->modules()->unnamed_module();
+}
+
+void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
+  int length = 0;
+  const jbyte* base_name = package_from_name(name(), length);
+
+  if (base_name != NULL && loader_data != NULL) {
+    TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
+
+    // Find in class loader's package entry table.
+    _package_entry = loader_data->packages()->lookup_only(pkg_name);
+
+    // If the package name is not found in the loader's package
+    // entry table, it is an indication that the package has not
+    // been defined. Consider it defined within the unnamed module.
+    if (_package_entry == NULL) {
+      ResourceMark rm;
+
+      if (!ModuleEntryTable::javabase_defined()) {
+        // Before java.base is defined during bootstrapping, define all packages in
+        // the java.base module.  If a non-java.base package is erroneously placed
+        // in the java.base module it will be caught later when java.base
+        // is defined by ModuleEntryTable::verify_javabase_packages check.
+        assert(ModuleEntryTable::javabase_module() != NULL, "java.base module is NULL");
+        _package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
+      } else {
+        assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL");
+        _package_entry = loader_data->packages()->lookup(pkg_name,
+                                                         loader_data->modules()->unnamed_module());
+      }
+
+      // A package should have been successfully created
+      assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
+             name()->as_C_string(), loader_data->loader_name());
+    }
+
+    if (log_is_enabled(Debug, modules)) {
+      ResourceMark rm;
+      ModuleEntry* m = _package_entry->module();
+      log_trace(modules)("Setting package: class: %s, package: %s, loader: %s, module: %s",
+                         external_name(),
+                         pkg_name->as_C_string(),
+                         loader_data->loader_name(),
+                         (m->is_named() ? m->name()->as_C_string() : UNNAMED_MODULE));
+    }
+  } else {
+    ResourceMark rm;
+    log_trace(modules)("Setting package: class: %s, package: unnamed, loader: %s, module: %s",
+                       external_name(),
+                       (loader_data != NULL) ? loader_data->loader_name() : "NULL",
+                       UNNAMED_MODULE);
+  }
+}
+
+
+// different versions of is_same_class_package
+
+bool InstanceKlass::is_same_class_package(const Klass* class2) const {
+  oop classloader1 = this->class_loader();
+  PackageEntry* classpkg1 = this->package();
   if (class2->is_objArray_klass()) {
     class2 = ObjArrayKlass::cast(class2)->bottom_klass();
   }
+
   oop classloader2;
+  PackageEntry* classpkg2;
   if (class2->is_instance_klass()) {
-    classloader2 = InstanceKlass::cast(class2)->class_loader();
+    classloader2 = class2->class_loader();
+    classpkg2 = InstanceKlass::cast(class2)->package();
   } else {
     assert(class2->is_typeArray_klass(), "should be type array");
     classloader2 = NULL;
+    classpkg2 = NULL;
   }
-  const Symbol* classname2 = class2->name();
 
-  return InstanceKlass::is_same_class_package(classloader1, classname1,
-                                              classloader2, classname2);
+  // Same package is determined by comparing class loader
+  // and package entries. Both must be the same. This rule
+  // applies even to classes that are defined in the unnamed
+  // package, they still must have the same class loader.
+  if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) {
+    return true;
+  }
+
+  return false;
 }
 
 bool InstanceKlass::is_same_class_package(oop other_class_loader,
@@ -2225,43 +2335,24 @@
     // The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
     // for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
     // Otherwise, we just compare jbyte values between the strings.
-    const jbyte *name1 = class_name1->base();
-    const jbyte *name2 = class_name2->base();
+    int length1 = 0;
+    int length2 = 0;
+    const jbyte *name1 = package_from_name(class_name1, length1);
+    const jbyte *name2 = package_from_name(class_name2, length2);
 
-    const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
-    const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
+    if ((length1 < 0) || (length2 < 0)) {
+      // error occurred parsing package name.
+      return false;
+    }
 
-    if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
+    if ((name1 == NULL) || (name2 == NULL)) {
       // One of the two doesn't have a package.  Only return true
       // if the other one also doesn't have a package.
-      return last_slash1 == last_slash2;
-    } else {
-      // Skip over '['s
-      if (*name1 == '[') {
-        do {
-          name1++;
-        } while (*name1 == '[');
-        if (*name1 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-      if (*name2 == '[') {
-        do {
-          name2++;
-        } while (*name2 == '[');
-        if (*name2 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-
-      // Check that package part is identical
-      int length1 = last_slash1 - name1;
-      int length2 = last_slash2 - name2;
-
-      return UTF8::equal(name1, length1, name2, length2);
+      return name1 == name2;
     }
+
+    // Check that package part is identical
+    return UTF8::equal(name1, length1, name2, length2);
   }
 }
 
@@ -2300,7 +2391,7 @@
   if (!class2->is_instance_klass())  return false;
 
   // must be in same package before we try anything else
-  if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
+  if (!class1->is_same_class_package(class2))
     return false;
 
   // As long as there is an outer1.getEnclosingClass,
@@ -2908,6 +2999,7 @@
 
 void InstanceKlass::print_loading_log(LogLevel::type type,
                                       ClassLoaderData* loader_data,
+                                      const char* module_name,
                                       const ClassFileStream* cfs) const {
   ResourceMark rm;
   outputStream* log;
@@ -2928,7 +3020,11 @@
   // Source
   if (cfs != NULL) {
     if (cfs->source() != NULL) {
-      log->print(" source: %s", cfs->source());
+      if (module_name != NULL) {
+        log->print(" source: jrt:/%s", module_name);
+      } else {
+        log->print(" source: %s", cfs->source());
+      }
     } else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
       Thread* THREAD = Thread::current();
       Klass* caller =
diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp
index 47924e5..4fdcc44 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp
@@ -25,8 +25,11 @@
 #ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
 #define SHARE_VM_OOPS_INSTANCEKLASS_HPP
 
+#include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.hpp"
+#include "classfile/packageEntry.hpp"
 #include "gc/shared/specialized_oop_closures.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "logging/logLevel.hpp"
 #include "memory/referenceType.hpp"
 #include "oops/annotations.hpp"
@@ -140,6 +143,8 @@
  protected:
   // Annotations for this class
   Annotations*    _annotations;
+  // Package this class is defined in
+  PackageEntry*   _package_entry;
   // Array classes holding elements of this class.
   Klass*          _array_klasses;
   // Constant pool for this class.
@@ -199,16 +204,22 @@
 
   // Start after _misc_kind field.
   enum {
-    _misc_rewritten                = 1 << 2, // methods rewritten.
-    _misc_has_nonstatic_fields     = 1 << 3, // for sizing with UseCompressedOops
-    _misc_should_verify_class      = 1 << 4, // allow caching of preverification
-    _misc_is_anonymous             = 1 << 5, // has embedded _host_klass field
-    _misc_is_contended             = 1 << 6, // marked with contended annotation
-    _misc_has_default_methods      = 1 << 7, // class/superclass/implemented interfaces has default methods
-    _misc_declares_default_methods = 1 << 8, // directly declares default methods (any access)
-    _misc_has_been_redefined       = 1 << 9, // class has been redefined
-    _misc_is_scratch_class         = 1 << 10 // class is the redefined scratch class
+    _misc_rewritten                = 1 << 2,  // methods rewritten.
+    _misc_has_nonstatic_fields     = 1 << 3,  // for sizing with UseCompressedOops
+    _misc_should_verify_class      = 1 << 4,  // allow caching of preverification
+    _misc_is_anonymous             = 1 << 5,  // has embedded _host_klass field
+    _misc_is_contended             = 1 << 6,  // marked with contended annotation
+    _misc_has_default_methods      = 1 << 7,  // class/superclass/implemented interfaces has default methods
+    _misc_declares_default_methods = 1 << 8,  // directly declares default methods (any access)
+    _misc_has_been_redefined       = 1 << 9,  // class has been redefined
+    _misc_is_scratch_class         = 1 << 10, // class is the redefined scratch class
+    _misc_is_shared_boot_class     = 1 << 11, // defining class loader is boot class loader
+    _misc_is_shared_platform_class = 1 << 12, // defining class loader is platform class loader
+    _misc_is_shared_app_class      = 1 << 13  // defining class loader is app class loader
   };
+  u2 loader_type_bits() {
+    return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
+  }
   u2              _misc_flags;
   u2              _minor_version;        // minor version number of class file
   u2              _major_version;        // major version number of class file
@@ -290,6 +301,39 @@
   friend class SystemDictionary;
 
  public:
+  u2 loader_type() {
+    return _misc_flags & loader_type_bits();
+  }
+
+  bool is_shared_boot_class() const {
+    return (_misc_flags & _misc_is_shared_boot_class) != 0;
+  }
+  bool is_shared_platform_class() const {
+    return (_misc_flags & _misc_is_shared_platform_class) != 0;
+  }
+  bool is_shared_app_class() const {
+    return (_misc_flags & _misc_is_shared_app_class) != 0;
+  }
+
+  void set_class_loader_type(jshort loader_type) {
+    assert(( _misc_flags & loader_type_bits()) == 0,
+           "Should only be called once for each class.");
+    switch (loader_type) {
+    case ClassLoader::BOOT_LOADER:
+      _misc_flags |= _misc_is_shared_boot_class;
+       break;
+    case ClassLoader::PLATFORM_LOADER:
+      _misc_flags |= _misc_is_shared_platform_class;
+      break;
+    case ClassLoader::APP_LOADER:
+      _misc_flags |= _misc_is_shared_app_class;
+      break;
+    default:
+      ShouldNotReachHere();
+      break;
+    }
+  }
+
   bool has_nonstatic_fields() const        {
     return (_misc_flags & _misc_has_nonstatic_fields) != 0;
   }
@@ -395,6 +439,11 @@
   bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
 
   // package
+  PackageEntry* package() const     { return _package_entry; }
+  ModuleEntry* module() const;
+  bool in_unnamed_package() const   { return (_package_entry == NULL); }
+  void set_package(PackageEntry* p) { _package_entry = p; }
+  void set_package(ClassLoaderData* loader_data, TRAPS);
   bool is_same_class_package(const Klass* class2) const;
   bool is_same_class_package(oop classloader2, const Symbol* classname2) const;
   static bool is_same_class_package(oop class_loader1,
@@ -1030,6 +1079,7 @@
 
   // Naming
   const char* signature_name() const;
+  static const jbyte* package_from_name(const Symbol* name, int& length);
 
   // GC specific object visitors
   //
@@ -1247,7 +1297,8 @@
   void oop_verify_on(oop obj, outputStream* st);
 
   // Logging
-  void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, const ClassFileStream* cfs) const;
+  void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data,
+                         const char* module_name, const ClassFileStream* cfs) const;
 };
 
 // for adding methods
diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp
index 3cedd34..8e32678 100644
--- a/hotspot/src/share/vm/oops/klass.cpp
+++ b/hotspot/src/share/vm/oops/klass.cpp
@@ -512,7 +512,21 @@
   // gotten an OOM later but keep the mirror if it was created.
   if (java_mirror() == NULL) {
     Handle loader = loader_data->class_loader();
-    java_lang_Class::create_mirror(this, loader, protection_domain, CHECK);
+    ModuleEntry* module_entry = NULL;
+    Klass* k = this;
+    if (k->is_objArray_klass()) {
+      k = ObjArrayKlass::cast(k)->bottom_klass();
+    }
+    // Obtain klass' module.
+    if (k->is_instance_klass()) {
+      InstanceKlass* ik = (InstanceKlass*) k;
+      module_entry = ik->module();
+    } else {
+      module_entry = ModuleEntryTable::javabase_module();
+    }
+    // Obtain java.lang.reflect.Module, if available
+    Handle module_handle(THREAD, ((module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL));
+    java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, CHECK);
   }
 }
 
diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp
index 7620ea9..d309e9a 100644
--- a/hotspot/src/share/vm/oops/method.cpp
+++ b/hotspot/src/share/vm/oops/method.cpp
@@ -1329,7 +1329,7 @@
   // exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
   // which does not use the class default class loader so we check for its loader here
   const InstanceKlass* ik = InstanceKlass::cast(holder);
-  if ((ik->class_loader() != NULL) && !SystemDictionary::is_ext_class_loader(ik->class_loader())) {
+  if ((ik->class_loader() != NULL) && !SystemDictionary::is_platform_class_loader(ik->class_loader())) {
     return vmSymbols::NO_SID;   // regardless of name, no intrinsics here
   }
 
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp
index bd696d5..8750ac7 100644
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp
@@ -135,8 +135,18 @@
   // GC walks these as strong roots.
   loader_data->add_class(oak);
 
+  // The array is defined in the module of its bottom class
+  Klass* bottom_klass = oak->bottom_klass();
+  ModuleEntry* module;
+  if (bottom_klass->is_instance_klass()) {
+    module = InstanceKlass::cast(bottom_klass)->module();
+  } else {
+    module = ModuleEntryTable::javabase_module();
+  }
+  assert(module != NULL, "No module entry for array");
+
   // Call complete_create_array_klass after all instance variables has been initialized.
-  ArrayKlass::complete_create_array_klass(oak, super_klass, CHECK_0);
+  ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 
   return oak;
 }
diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
index f8ec9ee..3fa9770 100644
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
@@ -70,7 +70,7 @@
   null_loader_data->add_class(ak);
 
   // Call complete_create_array_klass after all instance variables have been initialized.
-  complete_create_array_klass(ak, ak->super(), CHECK_NULL);
+  complete_create_array_klass(ak, ak->super(), ModuleEntryTable::javabase_module(), CHECK_NULL);
 
   return ak;
 }
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 74d6f88..cbcc5ae 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -319,8 +319,6 @@
 
   bool inline_profileBoolean();
   bool inline_isCompileConstant();
-
-  bool inline_deoptimize();
 };
 
 //---------------------------make_vm_intrinsic----------------------------
@@ -821,9 +819,6 @@
   case vmIntrinsics::_hasNegatives:
     return inline_hasNegatives();
 
-  case vmIntrinsics::_deoptimize:
-    return inline_deoptimize();
-
   default:
     // If you get here, it may be that someone has added a new intrinsic
     // to the list in vmSymbols.hpp without implementing it here.
@@ -6754,12 +6749,3 @@
   set_result(n->is_Con() ? intcon(1) : intcon(0));
   return true;
 }
-
-bool LibraryCallKit::inline_deoptimize() {
-  assert(WhiteBoxAPI, "");
-  PreserveReexecuteState preexecs(this);
-  jvms()->set_should_reexecute(false);
-  uncommon_trap(Deoptimization::Reason_intrinsic,
-                Deoptimization::Action_none);
-  return true;
-}
diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp
index bd79327..f3e0fea 100644
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp
@@ -58,6 +58,9 @@
 # include "classfile/classFileStream.hpp"
 # include "classfile/classLoader.hpp"
 # include "classfile/javaClasses.hpp"
+# include "classfile/moduleEntry.hpp"
+# include "classfile/modules.hpp"
+# include "classfile/packageEntry.hpp"
 # include "classfile/symbolTable.hpp"
 # include "classfile/systemDictionary.hpp"
 # include "classfile/vmSymbols.hpp"
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index 40e3c92..5f08fcd 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -28,7 +28,9 @@
 #include "classfile/altHashing.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/javaClasses.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -3443,6 +3445,47 @@
   return JNI_OK;
 JNI_END
 
+
+JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
+  JNIWrapper("GetModule");
+  return Modules::get_module(clazz, THREAD);
+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,
@@ -3722,7 +3765,13 @@
 
     // New 1_6 features
 
-    jni_GetObjectRefType
+    jni_GetObjectRefType,
+
+    // Module features
+
+    jni_GetModule,
+    jni_AddModuleReads,
+    jni_CanReadModule
 };
 
 
diff --git a/hotspot/src/share/vm/prims/jni.h b/hotspot/src/share/vm/prims/jni.h
index 564499f..9699688 100644
--- a/hotspot/src/share/vm/prims/jni.h
+++ b/hotspot/src/share/vm/prims/jni.h
@@ -765,6 +765,17 @@
 
     jobjectRefType (JNICALL *GetObjectRefType)
         (JNIEnv* env, jobject obj);
+
+    /* Module Features */
+
+    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);
 };
 
 /*
@@ -1857,6 +1868,20 @@
         return functions->GetObjectRefType(this, obj);
     }
 
+    /* Module Features */
+
+    jobject GetModule(jclass clazz) {
+        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 8ba2212..d6b7035 100644
--- a/hotspot/src/share/vm/prims/jniCheck.cpp
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp
@@ -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
@@ -1989,7 +1989,48 @@
     return result;
 JNI_END
 
+JNI_ENTRY_CHECKED(jobject,
+  checked_jni_GetModule(JNIEnv *env,
+                        jclass clazz))
+    functionEnter(thr);
+    IN_VM(
+      jniCheck::validate_class(thr, clazz, false);
+    )
+    jobject result = UNCHECKED()->GetModule(env,clazz);
+    functionExit(thr);
+    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
@@ -2272,7 +2313,13 @@
 
     // New 1.6 Features
 
-    checked_jni_GetObjectRefType
+    checked_jni_GetObjectRefType,
+
+    // Module Features
+
+    checked_jni_GetModule,
+    checked_jni_AddModuleReads,
+    checked_jni_CanReadModule
 };
 
 
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
index 2067afd..093efe3 100644
--- a/hotspot/src/share/vm/prims/jvm.cpp
+++ b/hotspot/src/share/vm/prims/jvm.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,12 @@
 #include "precompiled.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaAssertions.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -1047,6 +1051,58 @@
             (jclass) JNIHandles::make_local(env, k->java_mirror());
 JVM_END
 
+// Module support //////////////////////////////////////////////////////////////////////////////
+
+JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
+                                 jobjectArray packages))
+  JVMWrapper("JVM_DefineModule");
+  Modules::define_module(module, version, location, packages, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
+  JVMWrapper("JVM_SetBootLoaderUnnamedModule");
+  Modules::set_bootloader_unnamed_module(module, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+  JVMWrapper("JVM_AddModuleExports");
+  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
+  Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAll");
+  Modules::add_module_exports(from_module, package, NULL, CHECK);
+JVM_END
+
+JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module))
+  JVMWrapper("JVM_AddReadsModule");
+  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);
+JVM_END
+
+JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
+  JVMWrapper("JVM_GetModuleByPackageName");
+  return Modules::get_module_by_package_name(loader, package, THREAD);
+JVM_END
 
 // Reflection support //////////////////////////////////////////////////////////////////////////////
 
diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h
index af12c25..31ff94c 100644
--- a/hotspot/src/share/vm/prims/jvm.h
+++ b/hotspot/src/share/vm/prims/jvm.h
@@ -417,6 +417,41 @@
                           const char *source);
 
 /*
+ * Module support funcions
+ */
+
+JNIEXPORT void JNICALL
+JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
+                 jobjectArray packages);
+
+JNIEXPORT void JNICALL
+JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+
+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);
+
+JNIEXPORT jobject JNICALL
+JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
+
+/*
  * Reflection support functions
  */
 
@@ -920,6 +955,7 @@
 #define JVM_ACC_SYNTHETIC     0x1000  /* compiler-generated class, method or field */
 #define JVM_ACC_ANNOTATION    0x2000  /* annotation type */
 #define JVM_ACC_ENUM          0x4000  /* field is declared as element of enum */
+#define JVM_ACC_MODULE        0x8000  /* module-info class file */
 
 #define JVM_ACC_PUBLIC_BIT        0
 #define JVM_ACC_PRIVATE_BIT       1
diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml
index 98a0a06..f6a18c7 100644
--- a/hotspot/src/share/vm/prims/jvmti.xml
+++ b/hotspot/src/share/vm/prims/jvmti.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
 <!--
- Copyright (c) 2002, 2013, 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
@@ -21,7 +21,7 @@
  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  or visit www.oracle.com if you need additional information or have any
  questions.
-  
+
 -->
 
 <!DOCTYPE specification [
@@ -356,9 +356,9 @@
  ]>
 
 <specification label="JVM(TM) Tool Interface"
-        majorversion="1"
-        minorversion="2"
-        microversion="3">
+        majorversion="9"
+        minorversion="0"
+        microversion="0">
   <title subtitle="Version">
     <tm>JVM</tm> Tool Interface
   </title>
@@ -863,6 +863,23 @@
     to be instrumented by the use of wrapper methods.
   </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.
+  <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 class, the Java virtual machine arranges for the module
+  of classes transformed by the <eventlink id="ClassFileLoadHook"/> event to
+  read the unnamed module of both class loaders.
+</intro>
+
   <intro id="mUTF" label="Modified UTF-8 String Encoding">
     <jvmti/> uses modified UTF-8 to encode character strings.
     This is the same encoding used by JNI.
@@ -1880,10 +1897,6 @@
 	  <outptr><struct>jvmtiThreadInfo</struct></outptr>
 	  <description>
 	    On return, filled with information describing the specified thread.
-	    <p/>
-	    For JDK 1.1 implementations that don't
-	    recognize context class loaders, 
-	    the <code>context_class_loader</code> field will be NULL.
 	  </description>
 	</param>
       </parameters>
@@ -6460,6 +6473,43 @@
     </function>
   </category>
 
+  <category id="module" label="Module">
+
+    <intro>
+    </intro>
+
+    <function id="GetAllModules" num="3" since="9">
+      <synopsis>Get All Modules</synopsis>
+      <description>
+	Return an array of all modules loaded in the virtual machine.
+	The number of modules in the array is returned via
+	<code>module_count_ptr</code>, and the array itself via
+	<code>modules_ptr</code>.
+	<p/>
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+	<param id="module_count_ptr">
+	  <outptr><jint/></outptr>
+	  <description>
+	    On return, points to the number of returned modules.
+	  </description>
+	</param>
+	<param id="modules_ptr">
+	  <allocbuf outcount="module_count_ptr"><jobject/></allocbuf>
+	    <description>
+	      On return, points to an array of references, one
+              for each module.
+	    </description>
+	</param>
+      </parameters>
+      <errors>
+      </errors>
+    </function>
+  </category>
+
   <category id="class" label="Class">
 
     <intro>
@@ -6508,9 +6558,6 @@
 	either by defining it directly or by delegation to another class loader.
 	See <vmspec chapter="5.3"/>.
 	<p/>
-	For JDK version 1.1 implementations that don't
-	recognize the distinction between initiating and defining class loaders,
-	this function should return all classes loaded in the virtual machine.
 	The number of classes in the array is returned via
 	<code>class_count_ptr</code>, and the array itself via
 	<code>classes_ptr</code>.
@@ -9941,6 +9988,12 @@
           See <eventlink id="ResourceExhausted"/>.
 	</description>
       </capabilityfield>
+      <capabilityfield id="can_generate_early_vmstart" since="9">
+        <description>
+          Can generate the <code>VMStart</code> event early.
+          See <eventlink id="VMStart"/>.
+        </description>
+      </capabilityfield>
     </capabilitiestypedef>
 
     <function id="GetPotentialCapabilities" jkernel="yes" phase="onload" num="140">
@@ -12351,7 +12404,7 @@
     </parameters>
   </event>
 
-  <event label="Class File Load Hook" phase="any"
+  <event label="Class File Load Hook" phase="start"
 	 id="ClassFileLoadHook" const="JVMTI_EVENT_CLASS_FILE_LOAD_HOOK" num="54">
     <description>
       This event is sent when the VM obtains class file data,
@@ -12367,9 +12420,9 @@
       <internallink id="bci">bytecode instrumentation</internallink>
       for usage information.
       <p/>
-    This event may be sent before the VM is initialized (the primordial 
-    <functionlink id="GetPhase">phase</functionlink>). During this time
-    no VM resources should be created.  Some classes might not be compatible
+    This event may be sent before the VM is initialized (the start 
+    <functionlink id="GetPhase">phase</functionlink>).
+    Some classes might not be compatible
     with the function (eg. ROMized classes) and this event will not be
     generated for these classes.
     <p/>
@@ -12378,9 +12431,7 @@
     using the memory allocation function 
     <functionlink id="Allocate"></functionlink> because the
     VM is responsible for freeing the new class file data buffer
-    using <functionlink id="Deallocate"></functionlink>.  
-    Note that <functionlink id="Allocate"></functionlink>
-    is permitted during the primordial phase.
+    using <functionlink id="Deallocate"></functionlink>.
     <p/>
     If the agent wishes to modify the class file, it must set 
     <code>new_class_data</code> to point
@@ -12427,8 +12478,6 @@
         </outptr>
           <description>
             The JNI environment of the event (current) thread.
-	    Will be <code>NULL</code> if sent during the primordial 
-            <functionlink id="GetPhase">phase</functionlink>.
           </description>
       </param>
       <param id="class_being_redefined">
@@ -12496,9 +12545,28 @@
       The VM initialization event signals the start of the VM.
       At this time JNI is live but the VM is not yet fully initialized.
       Once this event is generated, the agent is free to call any JNI function.
-      This event signals the beginning of the start phase, 
+      This event signals the beginning of the start phase,
       <jvmti/> functions permitted in the start phase may be called.
       <p/>
+      The timing of this event may depend on whether the agent has added the
+      <internallink id="jvmtiCapabilities.can_generate_early_vmstart">
+      <code>can_generate_early_vmstart</code></internallink> capability or not.
+      If the capability has been added then the VM posts the event as early
+      as possible. The VM is capable of executing bytecode but it may not have
+      initialized to the point where it can load classes in modules other than
+      <code>java.base</code>. Agents that do load-time instrumentation in this
+      phase must take great care when instrumenting code that potentially
+      executes in this phase. Care should also be taken with JNI
+      <code>FindClass</code> as it may not be possible to load classes that are
+      not in the <code>java.base</code> module.
+      If the capability has not been added then the VM delays posting this
+      event until it is capable of loading classes in modules other than
+      <code>java.base</code> or the VM has completed its initialization.
+      Agents that create more than one JVM TI environment, where the
+      capability is added to some but not all environments, may observe the
+      start phase beginning earlier in the JVM TI environments that possess
+      the capabilty.
+      <p/>
       In the case of VM start-up failure, this event will not be sent.
     </description>
     <origin>jvmdi</origin>
@@ -12576,7 +12644,7 @@
     </parameters>
   </event>
 
-  <event label="Compiled Method Load"
+  <event label="Compiled Method Load" phase="start"
 	 id="CompiledMethodLoad" const="JVMTI_EVENT_COMPILED_METHOD_LOAD" num="68">
     <description>
       Sent when a method is compiled and loaded into memory by the VM.
@@ -12667,7 +12735,7 @@
     </parameters>
   </event>
 
-  <event label="Compiled Method Unload"
+  <event label="Compiled Method Unload" phase="start"
 	 id="CompiledMethodUnload" const="JVMTI_EVENT_COMPILED_METHOD_UNLOAD" num="69">
     <description>
       Sent when a compiled method is unloaded from memory.
@@ -14340,6 +14408,17 @@
   <change date="19 June 2013" version="1.2.3">
       Added support for statically linked agents.
   </change>
+  <change date="20 January 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
+  </change>
+  <change date="17 February 2016" version="9.0.0">
+      Support for modules:
+       - Add new capability can_generate_early_vmstart
+       - Allow CompiledMethodLoad events at start phase
+  </change>
 </changehistory>
 
 </specification>
diff --git a/hotspot/src/share/vm/prims/jvmti.xsl b/hotspot/src/share/vm/prims/jvmti.xsl
index 1f975d2..00a1551 100644
--- a/hotspot/src/share/vm/prims/jvmti.xsl
+++ b/hotspot/src/share/vm/prims/jvmti.xsl
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright (c) 2002, 2006, 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
@@ -1801,7 +1801,7 @@
             <xsl:text>) (jvmtiEnv* env</xsl:text>
             <xsl:apply-templates select="$thisFunction/parameters" mode="signature">
               <xsl:with-param name="comma">
-                <xsl:text>, &#xA;                       </xsl:text>
+                <xsl:text>,&#xA;                       </xsl:text>
               </xsl:with-param>
             </xsl:apply-templates>
             <xsl:text>);</xsl:text>
diff --git a/hotspot/src/share/vm/prims/jvmtiEnter.xsl b/hotspot/src/share/vm/prims/jvmtiEnter.xsl
index cee47ec..15fd952 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl
+++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright (c) 2002, 2015, 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
@@ -517,7 +517,7 @@
   }</xsl:text>
       </xsl:if>
       <xsl:if test="contains(@phase,'start')">
-        <xsl:text>  if(JvmtiEnv::get_phase()!=JVMTI_PHASE_START &amp;&amp; JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
+        <xsl:text>  if(JvmtiEnv::get_phase(env)!=JVMTI_PHASE_START &amp;&amp; JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
 </xsl:text>
     <xsl:if test="$trace='Trace'">
       <xsl:text>    if (trace_flags) {
diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp
index c2b5289..ca2d50b 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp
@@ -187,6 +187,20 @@
 } /* end GetThreadLocalStorage */
 
   //
+  // Module functions
+  //
+
+// module_count_ptr - pre-checked for NULL
+// modules_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetAllModules(jint* module_count_ptr, jobject** modules_ptr) {
+    JvmtiModuleClosure jmc;
+
+    return jmc.get_all_modules(this, module_count_ptr, modules_ptr);
+} /* end GetAllModules */
+
+
+  //
   // Class functions
   //
 
@@ -563,7 +577,7 @@
 // phase_ptr - pre-checked for NULL
 jvmtiError
 JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) {
-  *phase_ptr = get_phase();
+  *phase_ptr = phase();
   return JVMTI_ERROR_NONE;
 } /* end GetPhase */
 
@@ -3489,7 +3503,7 @@
 
   for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
     if (strcmp(property, p->key()) == 0) {
-      if (p->set_value(value_ptr)) {
+      if (p->set_writeable_value(value_ptr)) {
         err =  JVMTI_ERROR_NONE;
       }
     }
diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
index 5b2bff5..6c92b9c 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
@@ -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
@@ -114,6 +114,17 @@
   }
 }
 
+jvmtiPhase
+JvmtiEnvBase::phase() {
+  // For the JVMTI environments possessed the can_generate_early_vmstart:
+  //   replace JVMTI_PHASE_PRIMORDIAL with JVMTI_PHASE_START
+  if (_phase == JVMTI_PHASE_PRIMORDIAL &&
+      JvmtiExport::early_vmstart_recorded() &&
+      early_vmstart_env()) {
+    return JVMTI_PHASE_START;
+  }
+  return _phase; // Normal case
+}
 
 bool
 JvmtiEnvBase::is_valid() {
@@ -1475,3 +1486,35 @@
     }
   }
 }
+
+GrowableArray<jobject>* JvmtiModuleClosure::_tbl = NULL;
+
+jvmtiError
+JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
+  ResourceMark rm;
+  MutexLocker ml(Module_lock);
+
+  _tbl = new GrowableArray<jobject>(77);
+  if (_tbl == NULL) {
+    return JVMTI_ERROR_OUT_OF_MEMORY;
+  }
+
+  // Iterate over all the modules loaded to the system.
+  ClassLoaderDataGraph::modules_do(&do_module);
+
+  jint len = _tbl->length();
+  guarantee(len > 0, "at least one module must be present");
+
+  jobject* array = (jobject*)env->jvmtiMalloc((jlong)(len * sizeof(jobject)));
+  if (array == NULL) {
+    return JVMTI_ERROR_OUT_OF_MEMORY;
+  }
+  for (jint idx = 0; idx < len; idx++) {
+    array[idx] = _tbl->at(idx);
+  }
+  _tbl = NULL;
+  *modules_ptr = array;
+  *module_count_ptr = len;
+  return JVMTI_ERROR_NONE;
+}
+
diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp
index d8f4ffc..1c199bd 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -75,6 +75,7 @@
   };
 
   static jvmtiPhase  get_phase()                    { return _phase; }
+  static jvmtiPhase  get_phase(jvmtiEnv* env)       { return ((JvmtiEnvBase*)JvmtiEnv_from_jvmti_env(env))->phase(); }
   static void  set_phase(jvmtiPhase phase)          { _phase = phase; }
   static bool is_vm_live()                          { return _phase == JVMTI_PHASE_LIVE; }
 
@@ -140,6 +141,7 @@
 
  public:
 
+  jvmtiPhase  phase();
   bool is_valid();
 
   bool use_version_1_0_semantics();  // agent asked for version 1.0
@@ -160,6 +162,10 @@
 
   jvmtiCapabilities *get_prohibited_capabilities()  { return &_prohibited_capabilities; }
 
+  bool early_vmstart_env() {
+    return get_capabilities()->can_generate_early_vmstart != 0;
+  }
+
   static char** get_all_native_method_prefixes(int* count_ptr);
 
   // This test will answer true when all environments have been disposed and some have
@@ -689,4 +695,21 @@
   jvmtiError error() { return _error;}
 };
 
+
+// Jvmti module closure to collect all modules loaded to the system.
+class JvmtiModuleClosure : public StackObj {
+private:
+  static GrowableArray<jobject> *_tbl; // Protected with Module_lock
+
+  static void do_module(ModuleEntry* entry) {
+    assert_locked_or_safepoint(Module_lock);
+    jobject module = entry->module();
+    guarantee(module != NULL, "module object is NULL");
+    _tbl->push(module);
+  }
+
+public:
+  jvmtiError get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr);
+};
+
 #endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP
diff --git a/hotspot/src/share/vm/prims/jvmtiEventController.cpp b/hotspot/src/share/vm/prims/jvmtiEventController.cpp
index 893e91d..81ca1d7 100644
--- a/hotspot/src/share/vm/prims/jvmtiEventController.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEventController.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -98,6 +98,7 @@
 static const jlong  EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT |
                                VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
                                THREAD_START_BIT | THREAD_END_BIT |
+                               COMPILED_METHOD_LOAD_BIT | COMPILED_METHOD_UNLOAD_BIT |
                                DYNAMIC_CODE_GENERATED_BIT;
 static const jlong  GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS;
 static const jlong  SHOULD_POST_ON_EXCEPTIONS_BITS = EXCEPTION_BITS | METHOD_EXIT_BIT | FRAME_POP_BIT;
@@ -409,7 +410,7 @@
     env->env_event_enable()->_event_callback_enabled.get_bits() &
     env->env_event_enable()->_event_user_enabled.get_bits();
 
-  switch (JvmtiEnv::get_phase()) {
+  switch (env->phase()) {
   case JVMTI_PHASE_PRIMORDIAL:
   case JVMTI_PHASE_ONLOAD:
     // only these events allowed in primordial or onload phase
@@ -576,8 +577,6 @@
   // filtered events and there weren't last time
   if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
       (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
-    assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START),
-      "thread filtered events should not be enabled when VM not in start or live phase");
     {
       MutexLocker mu(Threads_lock);   //hold the Threads_lock for the iteration
       for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp
index 7ad0541..9b7b038 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp
@@ -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
@@ -46,6 +46,7 @@
 #include "runtime/arguments.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/javaCalls.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/os.inline.hpp"
@@ -369,6 +370,14 @@
           return JNI_EVERSION;  // unsupported minor version number
       }
       break;
+    case 9:
+      switch (minor) {
+        case 0:  // version 9.0.<micro> is recognized
+          break;
+        default:
+          return JNI_EVERSION;  // unsupported minor version number
+      }
+      break;
     default:
       return JNI_EVERSION;  // unsupported major version number
   }
@@ -397,6 +406,28 @@
   }
 }
 
+void
+JvmtiExport::add_default_read_edges(Handle h_module, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return; // extra safety
+  }
+  assert(!h_module.is_null(), "module should always be set");
+
+  // Invoke the transformedByAgent method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::transformedByAgent_name(),
+                         vmSymbols::transformedByAgent_signature(),
+                         h_module,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    java_lang_Throwable::print(PENDING_EXCEPTION, tty);
+    CLEAR_PENDING_EXCEPTION;
+    return;
+  }
+}
 
 void
 JvmtiExport::decode_version_values(jint version, int * major, int * minor,
@@ -410,6 +441,11 @@
   JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
 }
 
+void JvmtiExport::enter_early_start_phase() {
+  JvmtiManageCapabilities::recompute_always_capabilities();
+  set_early_vmstart_recorded(true);
+}
+
 void JvmtiExport::enter_start_phase() {
   JvmtiManageCapabilities::recompute_always_capabilities();
   JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
@@ -428,6 +464,28 @@
 // and call the agent's premain() for java.lang.instrument.
 //
 
+void JvmtiExport::post_early_vm_start() {
+  EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg Early VM start event triggered" ));
+
+  // can now enable some events
+  JvmtiEventController::vm_start();
+
+  JvmtiEnvIterator it;
+  for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+    // Only early vmstart envs post early VMStart event
+    if (env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
+      EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt Early VM start event sent" ));
+      JavaThread *thread  = JavaThread::current();
+      JvmtiThreadEventMark jem(thread);
+      JvmtiJavaThreadEventTransition jet(thread);
+      jvmtiEventVMStart callback = env->callbacks()->VMStart;
+      if (callback != NULL) {
+        (*callback)(env->jvmti_external(), jem.jni_env());
+      }
+    }
+  }
+}
+
 void JvmtiExport::post_vm_start() {
   EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));
 
@@ -436,7 +494,8 @@
 
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
-    if (env->is_enabled(JVMTI_EVENT_VM_START)) {
+    // Early vmstart envs do not post normal VMStart event
+    if (!env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
       EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));
 
       JavaThread *thread  = JavaThread::current();
@@ -544,6 +603,21 @@
     if (_state != NULL) {
       _h_class_being_redefined = _state->get_class_being_redefined();
       _load_kind = _state->get_class_load_kind();
+      Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)();
+      if (_load_kind != jvmti_class_load_kind_load && klass != NULL) {
+        ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
+        assert(module_entry != NULL, "module_entry should always be set");
+        if (module_entry->is_named() &&
+            module_entry->module() != NULL &&
+            !module_entry->has_default_read_edges()) {
+          if (!module_entry->set_has_default_read_edges()) {
+            // We won a potential race.
+            // Add read edges to the unnamed modules of the bootstrap and app class loaders
+            Handle class_module(_thread, JNIHandles::resolve(module_entry->module())); // Obtain j.l.r.Module
+            JvmtiExport::add_default_read_edges(class_module, _thread);
+          }
+        }
+      }
       // Clear class_being_redefined flag here. The action
       // from agent handler could generate a new class file load
       // hook event and if it is not cleared the new event generated
@@ -591,6 +665,9 @@
   }
 
   void post_to_env(JvmtiEnv* env, bool caching_needed) {
+    if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+      return;
+    }
     unsigned char *new_data = NULL;
     jint new_len = 0;
 //    EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
@@ -602,11 +679,9 @@
                                     _h_protection_domain,
                                     _h_class_being_redefined);
     JvmtiJavaThreadEventTransition jet(_thread);
-    JNIEnv* jni_env =  (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)?
-                                                        NULL : jem.jni_env();
     jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
     if (callback != NULL) {
-      (*callback)(env->jvmti_external(), jni_env,
+      (*callback)(env->jvmti_external(), jem.jni_env(),
                   jem.class_being_redefined(),
                   jem.jloader(), jem.class_name(),
                   jem.protection_domain(),
@@ -668,6 +743,10 @@
                                             unsigned char **data_ptr,
                                             unsigned char **end_ptr,
                                             JvmtiCachedClassFileData **cache_ptr) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
+
   JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
                                       h_protection_domain,
                                       data_ptr, end_ptr,
@@ -756,6 +835,9 @@
 
 void JvmtiExport::post_compiled_method_unload(
        jmethodID method, const void *code_begin) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
                  ("JVMTI [%s] method compile unload event triggered",
@@ -765,7 +847,9 @@
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
     if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
-
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
                 ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
                  JvmtiTrace::safe_get_thread_name(thread), p2i(method)));
@@ -838,6 +922,8 @@
 bool              JvmtiExport::_can_pop_frame                             = false;
 bool              JvmtiExport::_can_force_early_return                    = false;
 
+bool              JvmtiExport::_early_vmstart_recorded                    = false;
+
 bool              JvmtiExport::_should_post_single_step                   = false;
 bool              JvmtiExport::_should_post_field_access                  = false;
 bool              JvmtiExport::_should_post_field_modification            = false;
@@ -912,6 +998,9 @@
 }
 
 void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
 
@@ -924,11 +1013,13 @@
   JvmtiEnvThreadStateIterator it(state);
   for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
     if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {
+      JvmtiEnv *env = ets->get_env();
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",
                                          JvmtiTrace::safe_get_thread_name(thread),
                                          kh()==NULL? "NULL" : kh()->external_name() ));
-
-      JvmtiEnv *env = ets->get_env();
       JvmtiClassEventMark jem(thread, kh());
       JvmtiJavaThreadEventTransition jet(thread);
       jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;
@@ -941,6 +1032,9 @@
 
 
 void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
 
@@ -953,11 +1047,13 @@
   JvmtiEnvThreadStateIterator it(state);
   for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
     if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {
+      JvmtiEnv *env = ets->get_env();
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",
                                             JvmtiTrace::safe_get_thread_name(thread),
                                             kh()==NULL? "NULL" : kh()->external_name() ));
-
-      JvmtiEnv *env = ets->get_env();
       JvmtiClassEventMark jem(thread, kh());
       JvmtiJavaThreadEventTransition jet(thread);
       jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;
@@ -969,6 +1065,9 @@
 }
 
 void JvmtiExport::post_class_unload(Klass* klass) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   Thread *thread = Thread::current();
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
@@ -983,6 +1082,9 @@
 
     JvmtiEnvIterator it;
     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
         EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",
                   kh()==NULL? "NULL" : kh()->external_name() ));
@@ -1018,6 +1120,9 @@
 
 
 void JvmtiExport::post_thread_start(JavaThread *thread) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
 
   EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",
@@ -1031,6 +1136,9 @@
       !thread->is_hidden_from_external_view()) {
     JvmtiEnvIterator it;
     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {
         EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",
                      JvmtiTrace::safe_get_thread_name(thread) ));
@@ -1048,6 +1156,9 @@
 
 
 void JvmtiExport::post_thread_end(JavaThread *thread) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",
                       JvmtiTrace::safe_get_thread_name(thread)));
 
@@ -1063,10 +1174,13 @@
     JvmtiEnvThreadStateIterator it(state);
     for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
       if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {
+        JvmtiEnv *env = ets->get_env();
+        if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+          continue;
+        }
         EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",
                      JvmtiTrace::safe_get_thread_name(thread) ));
 
-        JvmtiEnv *env = ets->get_env();
         JvmtiThreadEventMark jem(thread);
         JvmtiJavaThreadEventTransition jet(thread);
         jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;
@@ -1705,7 +1819,7 @@
 
         JvmtiMethodEventMark jem(thread, mh);
         JvmtiJavaThreadEventTransition jet(thread);
-        JNIEnv* jni_env =  JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL? NULL : jem.jni_env();
+        JNIEnv* jni_env = (env->phase() == JVMTI_PHASE_PRIMORDIAL) ? NULL : jem.jni_env();
         jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;
         if (callback != NULL) {
           (*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),
@@ -1758,6 +1872,9 @@
 }
 
 void JvmtiExport::post_compiled_method_load(nmethod *nm) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
 
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
@@ -1767,7 +1884,9 @@
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
     if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
-
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
                 ("JVMTI [%s] class compile method load event sent %s.%s  ",
                 JvmtiTrace::safe_get_thread_name(thread),
@@ -1797,6 +1916,9 @@
                                             const void *code_begin, const jint map_length,
                                             const jvmtiAddrLocationMap* map)
 {
+  if (env->phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
                  ("JVMTI [%s] method compile load event triggered (by GenerateEvents)",
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp
index 8b06d62..4e9def5 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -91,6 +91,8 @@
   JVMTI_SUPPORT_FLAG(can_pop_frame)
   JVMTI_SUPPORT_FLAG(can_force_early_return)
 
+  JVMTI_SUPPORT_FLAG(early_vmstart_recorded)
+
   friend class JvmtiEventControllerPrivate;  // should only modify these flags
   JVMTI_SUPPORT_FLAG(should_post_single_step)
   JVMTI_SUPPORT_FLAG(should_post_field_access)
@@ -213,6 +215,8 @@
     _all_dependencies_are_recorded = (on != 0);
   }
 
+  // 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;
 
   // let JVMTI know that the JVM_OnLoad code is running
   static void enter_onload_phase() NOT_JVMTI_RETURN;
@@ -221,6 +225,7 @@
   static void enter_primordial_phase() NOT_JVMTI_RETURN;
 
   // let JVMTI know that the VM isn't up yet but JNI is live
+  static void enter_early_start_phase() NOT_JVMTI_RETURN;
   static void enter_start_phase() NOT_JVMTI_RETURN;
 
   // let JVMTI know that the VM is fully up and running now
@@ -270,6 +275,7 @@
   static bool hide_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN_(false);
 
   // Methods that notify the debugger that something interesting has happened in the VM.
+  static void post_early_vm_start        () NOT_JVMTI_RETURN;
   static void post_vm_start              () NOT_JVMTI_RETURN;
   static void post_vm_initialized        () NOT_JVMTI_RETURN;
   static void post_vm_death              () NOT_JVMTI_RETURN;
diff --git a/hotspot/src/share/vm/prims/jvmtiH.xsl b/hotspot/src/share/vm/prims/jvmtiH.xsl
index 0b19276..0f454a9 100644
--- a/hotspot/src/share/vm/prims/jvmtiH.xsl
+++ b/hotspot/src/share/vm/prims/jvmtiH.xsl
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -113,6 +113,7 @@
     JVMTI_VERSION_1_0 = 0x30010000,
     JVMTI_VERSION_1_1 = 0x30010100,
     JVMTI_VERSION_1_2 = 0x30010200,
+    JVMTI_VERSION_9   = 0x30090000,
 
     JVMTI_VERSION = 0x30000000 + (</xsl:text>
   <xsl:value-of select="//specification/@majorversion"/>
@@ -137,21 +138,21 @@
   <xsl:text> */
 };
 
-JNIEXPORT jint JNICALL 
+JNIEXPORT jint JNICALL
 Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
 
 JNIEXPORT jint JNICALL
 Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
 
-JNIEXPORT void JNICALL 
+JNIEXPORT void JNICALL
 Agent_OnUnload(JavaVM *vm);
 
     /* Forward declaration of the environment */
-        
+
 struct _jvmtiEnv;
 
 struct jvmtiInterface_1_;
-  
+
 #ifdef __cplusplus
 typedef _jvmtiEnv jvmtiEnv;
 #else
@@ -169,7 +170,6 @@
 #endif /* __cplusplus */
 
 #endif /* !_JAVA_JVMTI_H_ */
-
 </xsl:text>
 </xsl:template>
 
@@ -238,7 +238,7 @@
     (jvmtiEnv *jvmti_env</xsl:text>
   <xsl:apply-templates select="parameters" mode="signature">
     <xsl:with-param name="comma">
-      <xsl:text>, 
+      <xsl:text>,
      </xsl:text>
     </xsl:with-param>
    </xsl:apply-templates>
@@ -250,7 +250,7 @@
    <xsl:text>
 
     /* Function Interface */
-    
+
 typedef struct jvmtiInterface_1_ {
 
 </xsl:text>
@@ -290,7 +290,7 @@
       <xsl:text>) (jvmtiEnv* env</xsl:text>
       <xsl:apply-templates select="$thisFunction/parameters" mode="signature">
         <xsl:with-param name="comma">
-          <xsl:text>, 
+          <xsl:text>,
     </xsl:text>
         </xsl:with-param>
       </xsl:apply-templates>
@@ -365,7 +365,7 @@
 
     /* </xsl:text>
     <xsl:value-of select="@label"/>
-    <xsl:text> */ 
+    <xsl:text> */
 </xsl:text>
     <xsl:choose>
       <xsl:when test="@kind='enum'">
diff --git a/hotspot/src/share/vm/prims/jvmtiLib.xsl b/hotspot/src/share/vm/prims/jvmtiLib.xsl
index b1b4683..3c6a89e 100644
--- a/hotspot/src/share/vm/prims/jvmtiLib.xsl
+++ b/hotspot/src/share/vm/prims/jvmtiLib.xsl
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 
- 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
@@ -44,20 +44,20 @@
   </xsl:template>
 
   <xsl:template name="copyrightComment">
-    <xsl:text>/* </xsl:text>
+    <xsl:text>/*</xsl:text>
     <!-- Copy the Copyright comment from jvmti.xml -->
     <xsl:value-of select="/comment()[position()=1]"/>
-    <xsl:text> */ &#xA;&#xA;</xsl:text>
+    <xsl:text> */&#xA;&#xA;</xsl:text>
   </xsl:template>
 
   <xsl:template name="includeHeader">
     <xsl:call-template name="copyrightComment"/>
-    <xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ &#xA;</xsl:text>    
+    <xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */&#xA;</xsl:text>    
   </xsl:template>
 
   <xsl:template name="sourceHeader">
     <xsl:call-template name="copyrightComment"/>
-    <xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT &#xA;</xsl:text>    
+    <xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT&#xA;</xsl:text>    
   </xsl:template>
 
 
diff --git a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp
index b614b5a..a9ce01c 100644
--- a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -133,9 +133,7 @@
   jc.can_get_owned_monitor_info = 1;
   jc.can_get_owned_monitor_stack_depth_info = 1;
   jc.can_get_current_contended_monitor = 1;
-  // jc.can_get_monitor_info = 1;
-  jc.can_tag_objects = 1;                 // TODO: this should have been removed
-  jc.can_generate_object_free_events = 1; // TODO: this should have been removed
+  jc.can_generate_early_vmstart = 1;
   return jc;
 }
 
@@ -454,6 +452,8 @@
     tty->print_cr("can_generate_resource_exhaustion_heap_events");
   if (cap->can_generate_resource_exhaustion_threads_events)
     tty->print_cr("can_generate_resource_exhaustion_threads_events");
+  if (cap->can_generate_early_vmstart)
+    tty->print_cr("can_generate_early_vmstart");
 }
 
 #endif
diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp
index 38b68a4..de66179 100644
--- a/hotspot/src/share/vm/prims/methodHandles.cpp
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp
@@ -1177,9 +1177,9 @@
     if (reference_klass != NULL && reference_klass->is_instance_klass()) {
       // Emulate LinkResolver::check_klass_accessability.
       Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
-      if (!Reflection::verify_class_access(caller,
-                                           reference_klass,
-                                           true)) {
+      if (Reflection::verify_class_access(caller,
+                                          reference_klass,
+                                          true) != Reflection::ACCESS_OK) {
         THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
       }
     }
diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp
index c89e4f1..1ebcaee 100644
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp
@@ -41,7 +41,9 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "utilities/macros.hpp"
-
+#if INCLUDE_TRACE
+#include "trace/traceMacros.hpp"
+#endif
 
 static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
   char* bytes = (char*)name->bytes() + begin;
@@ -131,6 +133,9 @@
   { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime",            NULL, FN_PTR(JVM_GetJVMCIRuntime)             },
   { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives",       NULL, FN_PTR(JVM_RegisterJVMCINatives)        },
 #endif
+#if INCLUDE_TRACE
+  { CC"Java_jdk_jfr_internal_JVM_registerNatives",                 NULL, TRACE_REGISTER_NATIVES                  },
+#endif
 };
 
 static address lookup_special_native(char* jni_name) {
diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp
index 776df02..c6d4c41 100644
--- a/hotspot/src/share/vm/prims/whitebox.cpp
+++ b/hotspot/src/share/vm/prims/whitebox.cpp
@@ -27,6 +27,7 @@
 #include <new>
 
 #include "classfile/classLoaderData.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/stringTable.hpp"
 #include "code/codeCache.hpp"
 #include "compiler/methodMatcher.hpp"
@@ -1250,6 +1251,43 @@
   MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
 WB_END
 
+WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
+                                jobjectArray packages))
+  Modules::define_module(module, version, location, packages, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
+  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports(module, package, NULL, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
+  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
+
+WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
+  return Modules::get_module_by_package_name(loader, package, THREAD);
+WB_END
+
 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
   if (inc < 0) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -1278,7 +1316,6 @@
 WB_END
 
 
-
 WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
   Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
                                            Monitor::_safepoint_check_always :
@@ -1287,10 +1324,6 @@
                    attemptedNoSafepointValue == JNI_TRUE);
 WB_END
 
-WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
-  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
-WB_END
-
 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
   oop obj_oop = JNIHandles::resolve(obj);
   return (jboolean) obj_oop->mark()->has_monitor();
@@ -1417,6 +1450,10 @@
   return MetaspaceShared::is_in_shared_space((void*)obj_oop);
 WB_END
 
+WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
+  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
+WB_END
+
 WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
   return StringTable::shared_string_ignored();
 WB_END
@@ -1528,10 +1565,9 @@
   {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
   {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
   {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
-  {CC"isSharedClass", CC"(Ljava/lang/Class;)Z",       (void*)&WB_IsSharedClass },
 #if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
-  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z",(void*)&WB_G1IsHumongous     },
+  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
   {CC"g1BelongsToHumongousRegion0", CC"(J)Z",         (void*)&WB_G1BelongsToHumongousRegion},
   {CC"g1BelongsToFreeRegion0", CC"(J)Z",              (void*)&WB_G1BelongsToFreeRegion},
   {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
@@ -1649,6 +1685,24 @@
   {CC"getCodeBlob",        CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob        },
   {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
   {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
+  {CC"DefineModule",       CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
+                                                      (void*)&WB_DefineModule },
+  {CC"AddModuleExports",   CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
+                                                      (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;",
+                                                      (void*)&WB_GetModuleByPackageName },
+  {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
+                                                      (void*)&WB_AddModuleExportsToAllUnnamed },
+  {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
+                                                      (void*)&WB_AddModuleExportsToAll },
   {CC"assertMatchingSafepointCalls", CC"(ZZ)V",       (void*)&WB_AssertMatchingSafepointCalls },
   {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated  },
   {CC"forceSafepoint",     CC"()V",                   (void*)&WB_ForceSafepoint     },
@@ -1675,6 +1729,7 @@
       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
                                                       (void*)&WB_GetMethodStringOption},
   {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
+  {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
   {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
   {CC"clearInlineCaches",  CC"()V",                   (void*)&WB_ClearInlineCaches },
 };
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 8af50bd..e6f1f20 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -94,6 +94,9 @@
 const char*  Arguments::_sun_java_launcher      = DEFAULT_JAVA_LAUNCHER;
 int    Arguments::_sun_java_launcher_pid        = -1;
 bool   Arguments::_sun_java_launcher_is_altjvm  = false;
+int    Arguments::_patch_dirs_count          = 0;
+char** Arguments::_patch_dirs                = NULL;
+int    Arguments::_bootclassloader_append_index = -1;
 
 // These parameters are reset in method parse_vm_init_args()
 bool   Arguments::_AlwaysCompileLoopMethods     = AlwaysCompileLoopMethods;
@@ -117,7 +120,9 @@
 SystemProperty *Arguments::_java_library_path = NULL;
 SystemProperty *Arguments::_java_home = NULL;
 SystemProperty *Arguments::_java_class_path = NULL;
-SystemProperty *Arguments::_sun_boot_class_path = NULL;
+SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
+
+PathString *Arguments::_system_boot_class_path = NULL;
 
 char* Arguments::_ext_dirs = NULL;
 
@@ -195,6 +200,12 @@
 
 // Initialize system properties key and value.
 void Arguments::init_system_properties() {
+
+  // Set up _system_boot_class_path which is not a property but
+  // relies heavily on argument processing and the jdk.boot.class.path.append
+  // property. It is used to store the underlying system boot class path.
+  _system_boot_class_path = new PathString(NULL);
+
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
                                                                  "Java Virtual Machine Specification",  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(),  false));
@@ -208,16 +219,19 @@
   _sun_boot_library_path = new SystemProperty("sun.boot.library.path", NULL,  true);
   _java_library_path = new SystemProperty("java.library.path", NULL,  true);
   _java_home =  new SystemProperty("java.home", NULL,  true);
-  _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL,  true);
-
   _java_class_path = new SystemProperty("java.class.path", "",  true);
+  // jdk.boot.class.path.append is a non-writeable, internal property.
+  // It can only be set by either:
+  //    - -Xbootclasspath/a:
+  //    - AddToBootstrapClassLoaderSearch during JVMTI OnLoad phase
+  _jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", "", false, true);
 
   // Add to System Property list.
   PropertyList_add(&_system_properties, _sun_boot_library_path);
   PropertyList_add(&_system_properties, _java_library_path);
   PropertyList_add(&_system_properties, _java_home);
   PropertyList_add(&_system_properties, _java_class_path);
-  PropertyList_add(&_system_properties, _sun_boot_class_path);
+  PropertyList_add(&_system_properties, _jdk_boot_class_path_append);
 
   // Set OS specific system properties values
   os::init_system_properties_values();
@@ -542,19 +556,19 @@
 }
 #endif
 
-// Constructs the system class path (aka boot class path) from the following
-// components, in order:
+// Constructs the system boot class path from the following components, in order:
 //
-//     prefix           // from -Xbootclasspath/p:...
-//     base             // from os::get_system_properties() or -Xbootclasspath=
+//     prefix           // from -Xpatch:...
+//     base             // from os::get_system_properties()
 //     suffix           // from -Xbootclasspath/a:...
 //
 // This could be AllStatic, but it isn't needed after argument processing is
-// complete.
-class SysClassPath: public StackObj {
+// complete. After argument processing, the combined components are copied
+// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
+class ArgumentBootClassPath: public StackObj {
 public:
-  SysClassPath(const char* base);
-  ~SysClassPath();
+  ArgumentBootClassPath(const char* base);
+  ~ArgumentBootClassPath();
 
   inline void set_base(const char* base);
   inline void add_prefix(const char* prefix);
@@ -562,9 +576,9 @@
   inline void add_suffix(const char* suffix);
   inline void reset_path(const char* base);
 
-  inline const char* get_base()     const { return _items[_scp_base]; }
-  inline const char* get_prefix()   const { return _items[_scp_prefix]; }
-  inline const char* get_suffix()   const { return _items[_scp_suffix]; }
+  inline const char* get_base()     const { return _items[_bcp_base]; }
+  inline const char* get_prefix()   const { return _items[_bcp_prefix]; }
+  inline const char* get_suffix()   const { return _items[_bcp_suffix]; }
 
   // Combine all the components into a single c-heap-allocated string; caller
   // must free the string if/when no longer needed.
@@ -580,55 +594,55 @@
   // Array indices for the items that make up the sysclasspath.  All except the
   // base are allocated in the C heap and freed by this class.
   enum {
-    _scp_prefix,        // from -Xbootclasspath/p:...
-    _scp_base,          // the default sysclasspath
-    _scp_suffix,        // from -Xbootclasspath/a:...
-    _scp_nitems         // the number of items, must be last.
+    _bcp_prefix,        // was -Xpatch:...
+    _bcp_base,          // the default system boot class path
+    _bcp_suffix,        // from -Xbootclasspath/a:...
+    _bcp_nitems         // the number of items, must be last.
   };
 
-  const char* _items[_scp_nitems];
+  const char* _items[_bcp_nitems];
 };
 
-SysClassPath::SysClassPath(const char* base) {
+ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
   memset(_items, 0, sizeof(_items));
-  _items[_scp_base] = base;
+  _items[_bcp_base] = base;
 }
 
-SysClassPath::~SysClassPath() {
+ArgumentBootClassPath::~ArgumentBootClassPath() {
   // Free everything except the base.
-  for (int i = 0; i < _scp_nitems; ++i) {
-    if (i != _scp_base) reset_item_at(i);
+  for (int i = 0; i < _bcp_nitems; ++i) {
+    if (i != _bcp_base) reset_item_at(i);
   }
 }
 
-inline void SysClassPath::set_base(const char* base) {
-  _items[_scp_base] = base;
+inline void ArgumentBootClassPath::set_base(const char* base) {
+  _items[_bcp_base] = base;
 }
 
-inline void SysClassPath::add_prefix(const char* prefix) {
-  _items[_scp_prefix] = add_to_path(_items[_scp_prefix], prefix, true);
+inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
+  _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
 }
 
-inline void SysClassPath::add_suffix_to_prefix(const char* suffix) {
-  _items[_scp_prefix] = add_to_path(_items[_scp_prefix], suffix, false);
+inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
+  _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
 }
 
-inline void SysClassPath::add_suffix(const char* suffix) {
-  _items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false);
+inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
+  _items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
 }
 
-inline void SysClassPath::reset_item_at(int index) {
-  assert(index < _scp_nitems && index != _scp_base, "just checking");
+inline void ArgumentBootClassPath::reset_item_at(int index) {
+  assert(index < _bcp_nitems && index != _bcp_base, "just checking");
   if (_items[index] != NULL) {
     FREE_C_HEAP_ARRAY(char, _items[index]);
     _items[index] = NULL;
   }
 }
 
-inline void SysClassPath::reset_path(const char* base) {
+inline void ArgumentBootClassPath::reset_path(const char* base) {
   // Clear the prefix and suffix.
-  reset_item_at(_scp_prefix);
-  reset_item_at(_scp_suffix);
+  reset_item_at(_bcp_prefix);
+  reset_item_at(_bcp_suffix);
   set_base(base);
 }
 
@@ -637,17 +651,21 @@
 
 // Combine the bootclasspath elements, some of which may be null, into a single
 // c-heap-allocated string.
-char* SysClassPath::combined_path() {
-  assert(_items[_scp_base] != NULL, "empty default sysclasspath");
+char* ArgumentBootClassPath::combined_path() {
+  assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
 
-  size_t lengths[_scp_nitems];
+  size_t lengths[_bcp_nitems];
   size_t total_len = 0;
 
   const char separator = *os::path_separator();
 
   // Get the lengths.
   int i;
-  for (i = 0; i < _scp_nitems; ++i) {
+  for (i = 0; i < _bcp_nitems; ++i) {
+    if (i == _bcp_suffix) {
+      // Record index of boot loader's append path.
+      Arguments::set_bootclassloader_append_index((int)total_len);
+    }
     if (_items[i] != NULL) {
       lengths[i] = strlen(_items[i]);
       // Include space for the separator char (or a NULL for the last item).
@@ -659,7 +677,7 @@
   // Copy the _items to a single string.
   char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal);
   char* cp_tmp = cp;
-  for (i = 0; i < _scp_nitems; ++i) {
+  for (i = 0; i < _bcp_nitems; ++i) {
     if (_items[i] != NULL) {
       memcpy(cp_tmp, _items[i], lengths[i]);
       cp_tmp += lengths[i];
@@ -672,7 +690,7 @@
 
 // Note:  path must be c-heap-allocated (or NULL); it is freed if non-null.
 char*
-SysClassPath::add_to_path(const char* path, const char* str, bool prepend) {
+ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
   char *cp;
 
   assert(str != NULL, "just checking");
@@ -706,7 +724,7 @@
 
 // Scan the directory and append any jar or zip files found to path.
 // Note:  path must be c-heap-allocated (or NULL); it is freed if non-null.
-char* SysClassPath::add_jars_to_path(char* path, const char* directory) {
+char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
   DIR* dir = os::opendir(directory);
   if (dir == NULL) return path;
 
@@ -1375,6 +1393,54 @@
   return true;
 }
 
+// sets or adds a module name to the jdk.launcher.addmods property
+bool Arguments::append_to_addmods_property(const char* module_name) {
+  const char* key = "jdk.launcher.addmods";
+  const char* old_value = Arguments::get_property(key);
+  size_t buf_len = strlen(key) + strlen(module_name) + 2;
+  if (old_value != NULL) {
+    buf_len += strlen(old_value) + 1;
+  }
+  char* new_value = AllocateHeap(buf_len, mtInternal);
+  if (new_value == NULL) {
+    return false;
+  }
+  if (old_value == NULL) {
+    jio_snprintf(new_value, buf_len, "%s=%s", key, module_name);
+  } else {
+    jio_snprintf(new_value, buf_len, "%s=%s,%s", key, old_value, module_name);
+  }
+  bool added = add_property(new_value);
+  FreeHeap(new_value);
+  return added;
+}
+
+#if INCLUDE_CDS
+void Arguments::check_unsupported_dumping_properties() {
+  assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
+  const char* unsupported_properties[5] = { "jdk.module.main",
+                                           "jdk.module.path",
+                                           "jdk.upgrade.module.path",
+                                           "jdk.launcher.addmods",
+                                           "jdk.launcher.limitmods" };
+  const char* unsupported_options[5] = { "-m",
+                                        "-modulepath",
+                                        "-upgrademodulepath",
+                                        "-addmods",
+                                        "-limitmods" };
+  SystemProperty* sp = system_properties();
+  while (sp != NULL) {
+    for (int i = 0; i < 5; i++) {
+      if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
+          vm_exit_during_initialization(
+            "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
+      }
+    }
+    sp = sp->next();
+  }
+}
+#endif
+
 //===========================================================================================================
 // Setting int/mixed/comp mode flags
 
@@ -2553,8 +2619,8 @@
                                    const JavaVMInitArgs *java_options_args,
                                    const JavaVMInitArgs *cmd_line_args) {
   // For components of the system classpath.
-  SysClassPath scp(Arguments::get_sysclasspath());
-  bool scp_assembly_required = false;
+  ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
+  bool bcp_assembly_required = false;
 
   // Save default settings for some mode flags
   Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
@@ -2572,13 +2638,13 @@
   // Parse args structure generated from JAVA_TOOL_OPTIONS environment
   // variable (if present).
   jint result = parse_each_vm_init_arg(
-      java_tool_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
+      java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
   if (result != JNI_OK) {
     return result;
   }
 
   // Parse args structure generated from the command line flags.
-  result = parse_each_vm_init_arg(cmd_line_args, &scp, &scp_assembly_required,
+  result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
                                   Flag::COMMAND_LINE);
   if (result != JNI_OK) {
     return result;
@@ -2587,13 +2653,13 @@
   // Parse args structure generated from the _JAVA_OPTIONS environment
   // variable (if present) (mimics classic VM)
   result = parse_each_vm_init_arg(
-      java_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
+      java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
   if (result != JNI_OK) {
     return result;
   }
 
   // Do final processing now that all arguments have been parsed
-  result = finalize_vm_init_args(&scp, scp_assembly_required);
+  result = finalize_vm_init_args(&bcp, bcp_assembly_required);
   if (result != JNI_OK) {
     return result;
   }
@@ -2647,8 +2713,8 @@
 }
 
 jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
-                                       SysClassPath* scp_p,
-                                       bool* scp_assembly_required_p,
+                                       ArgumentBootClassPath* bcp_p,
+                                       bool* bcp_assembly_required_p,
                                        Flag::Flags origin) {
   // For match_option to return remaining or value part of option string
   const char* tail;
@@ -2700,16 +2766,18 @@
       JavaAssertions::setSystemClassDefault(enable);
     // -bootclasspath:
     } else if (match_option(option, "-Xbootclasspath:", &tail)) {
-      scp_p->reset_path(tail);
-      *scp_assembly_required_p = true;
+        jio_fprintf(defaultStream::output_stream(),
+          "-Xbootclasspath is no longer a supported option.\n");
+        return JNI_EINVAL;
     // -bootclasspath/a:
     } else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
-      scp_p->add_suffix(tail);
-      *scp_assembly_required_p = true;
+      bcp_p->add_suffix(tail);
+      *bcp_assembly_required_p = true;
     // -bootclasspath/p:
     } else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
-      scp_p->add_prefix(tail);
-      *scp_assembly_required_p = true;
+        jio_fprintf(defaultStream::output_stream(),
+          "-Xbootclasspath/p is no longer a supported option.\n");
+        return JNI_EINVAL;
     // -Xrun
     } else if (match_option(option, "-Xrun", &tail)) {
       if (tail != NULL) {
@@ -2761,9 +2829,14 @@
         "Instrumentation agents are not supported in this VM\n");
       return JNI_ERR;
 #else
-      if(tail != NULL) {
+      if (tail != NULL) {
         char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
         add_init_agent("instrument", options, false);
+        // java agents need module java.instrument. Also -addmods ALL-SYSTEM because
+        // the java agent is in the unmamed module of the application class loader
+        if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
+          return JNI_ENOMEM;
+        }
       }
 #endif // !INCLUDE_JVMTI
     // -Xnoclassgc
@@ -3029,12 +3102,50 @@
         if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
           return JNI_EINVAL;
         }
+        // management agent in module java.management
+        if (!Arguments::append_to_addmods_property("java.management")) {
+          return JNI_ENOMEM;
+        }
 #else
         jio_fprintf(defaultStream::output_stream(),
           "-Dcom.sun.management is not supported in this VM.\n");
         return JNI_ERR;
 #endif
       }
+      if (match_option(option, "-Djdk.launcher.patch.0=", &tail)) {
+        // -Xpatch
+        int dir_count;
+        char** patch_dirs = os::split_path(tail, &dir_count);
+        if (patch_dirs == NULL) {
+          jio_fprintf(defaultStream::output_stream(),
+            "Bad value for -Xpatch.\n");
+          return JNI_ERR;
+        }
+        set_patch_dirs(patch_dirs);
+        set_patch_dirs_count(dir_count);
+
+        // Create a path for each patch dir consisting of dir/java.base.
+        char file_sep = os::file_separator()[0];
+        for (int x = 0; x < dir_count; x++) {
+          // Really shouldn't be NULL, but check can't hurt
+          if (patch_dirs[x] != NULL) {
+            size_t len = strlen(patch_dirs[x]);
+            if (len != 0) { // Ignore empty strings.
+              len += 11; // file_sep + "java.base" + null terminator.
+              char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+              jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
+
+              // See if Xpatch module path exists.
+              struct stat st;
+              if ((os::stat(dir, &st) == 0)) {
+                bcp_p->add_prefix(dir);
+                *bcp_assembly_required_p = true;
+              }
+              FREE_C_HEAP_ARRAY(char, dir);
+            }
+          }
+        }
+      }
     // -Xint
     } else if (match_option(option, "-Xint")) {
           set_mode_flags(_int);
@@ -3294,6 +3405,18 @@
   return JNI_OK;
 }
 
+// Set property jdk.boot.class.path.append to the contents of the bootclasspath
+// that follows either the jimage file or exploded module directories.  The
+// property will contain -Xbootclasspath/a and/or jvmti appended additions.
+void Arguments::set_jdkbootclasspath_append() {
+  char *sysclasspath = get_sysclasspath();
+  assert(sysclasspath != NULL, "NULL sysclasspath");
+  int bcp_a_idx = bootclassloader_append_index();
+  if (bcp_a_idx != -1 && bcp_a_idx < (int)strlen(sysclasspath)) {
+    _jdk_boot_class_path_append->set_value(sysclasspath + bcp_a_idx);
+  }
+}
+
 // Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
 //
 // This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar
@@ -3329,7 +3452,7 @@
       // Keep replacing ";;" -> ";" until we have no more ";;" (windows)
     }
 
-    _java_class_path->set_value(copy);
+    _java_class_path->set_writeable_value(copy);
     FreeHeap(copy); // a copy was made by set_value, so don't need this anymore
   }
 }
@@ -3380,7 +3503,7 @@
   return nonEmptyDirs;
 }
 
-jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
+jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
   // check if the default lib/endorsed directory exists; if so, error
   char path[JVM_MAXPATHLEN];
   const char* fileSep = os::file_separator();
@@ -3416,11 +3539,16 @@
     return JNI_ERR;
   }
 
-  if (scp_assembly_required) {
+  if (bcp_assembly_required) {
     // Assemble the bootclasspath elements into the final path.
-    char *combined_path = scp_p->combined_path();
+    char *combined_path = bcp_p->combined_path();
     Arguments::set_sysclasspath(combined_path);
     FREE_C_HEAP_ARRAY(char, combined_path);
+  } else {
+    // At this point in sysclasspath processing anything
+    // added would be considered in the boot loader's append path.
+    // Record this index, including +1 for the file separator character.
+    Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
   }
 
   // This must be done after all arguments have been processed.
@@ -3766,6 +3894,11 @@
 
 void Arguments::set_shared_spaces_flags() {
   if (DumpSharedSpaces) {
+    if (Arguments::patch_dirs() != NULL) {
+      vm_exit_during_initialization(
+        "Cannot use the following option when dumping the shared archive", "-Xpatch");
+    }
+
     if (RequireSharedSpaces) {
       warning("Cannot dump shared archive while using shared archive");
     }
@@ -4455,7 +4588,7 @@
       if (append) {
         prop->append_value(v);
       } else {
-        prop->set_value(v);
+        prop->set_writeable_value(v);
       }
       return;
     }
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index 8fb9549..67a9661 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -43,37 +43,30 @@
 }
 
 // Forward declarations
+class ArgumentBootClassPath;
 
-class SysClassPath;
-
-// Element describing System and User (-Dkey=value flags) defined property.
-
-class SystemProperty: public CHeapObj<mtInternal> {
- private:
-  char*           _key;
+// PathString is used as the underlying value container for a
+// SystemProperty and for the string that represents the system
+// boot class path, Arguments::_system_boot_class_path.
+class PathString : public CHeapObj<mtInternal> {
+ protected:
   char*           _value;
-  SystemProperty* _next;
-  bool            _writeable;
-  bool writeable()   { return _writeable; }
-
  public:
-  // Accessors
-  const char* key() const                   { return _key; }
   char* value() const                       { return _value; }
-  SystemProperty* next() const              { return _next; }
-  void set_next(SystemProperty* next)       { _next = next; }
+
   bool set_value(const char *value) {
-    if (writeable()) {
-      if (_value != NULL) {
-        FreeHeap(_value);
-      }
-      _value = AllocateHeap(strlen(value)+1, mtInternal);
-      if (_value != NULL) {
-        strcpy(_value, value);
-      }
-      return true;
+    if (_value != NULL) {
+      FreeHeap(_value);
     }
-    return false;
+    _value = AllocateHeap(strlen(value)+1, mtInternal);
+    assert(_value != NULL, "Unable to allocate space for new path value");
+    if (_value != NULL) {
+      strcpy(_value, value);
+    } else {
+      // not able to allocate
+      return false;
+    }
+    return true;
   }
 
   void append_value(const char *value) {
@@ -85,6 +78,7 @@
         len += strlen(_value);
       }
       sp = AllocateHeap(len+2, mtInternal);
+      assert(sp != NULL, "Unable to allocate space for new append path value");
       if (sp != NULL) {
         if (_value != NULL) {
           strcpy(sp, _value);
@@ -100,20 +94,61 @@
   }
 
   // Constructor
-  SystemProperty(const char* key, const char* value, bool writeable) {
-    if (key == NULL) {
-      _key = NULL;
-    } else {
-      _key = AllocateHeap(strlen(key)+1, mtInternal);
-      strcpy(_key, key);
-    }
+  PathString(const char* value) {
     if (value == NULL) {
       _value = NULL;
     } else {
       _value = AllocateHeap(strlen(value)+1, mtInternal);
       strcpy(_value, value);
     }
+  }
+};
+
+// Element describing System and User (-Dkey=value flags) defined property.
+//
+// An internal SystemProperty is one that has been removed in
+// jdk.internal.VM.saveAndRemoveProperties, like jdk.boot.class.path.append.
+//
+class SystemProperty : public PathString {
+ private:
+  char*           _key;
+  SystemProperty* _next;
+  bool            _internal;
+  bool            _writeable;
+  bool writeable()   { return _writeable; }
+
+ public:
+  // Accessors
+  char* value() const                 { return PathString::value(); }
+  const char* key() const             { return _key; }
+  bool internal() const               { return _internal; }
+  SystemProperty* next() const        { return _next; }
+  void set_next(SystemProperty* next) { _next = next; }
+
+  // A system property should only have its value set
+  // via an external interface if it is a writeable property.
+  // The internal, non-writeable property jdk.boot.class.path.append
+  // is the only exception to this rule.  It can be set externally
+  // via -Xbootclasspath/a or JVMTI OnLoad phase call to AddToBootstrapClassLoaderSearch.
+  // In those cases for jdk.boot.class.path.append, the base class
+  // set_value and append_value methods are called directly.
+  bool set_writeable_value(const char *value) {
+    if (writeable()) {
+      return set_value(value);
+    }
+    return false;
+  }
+
+  // Constructor
+  SystemProperty(const char* key, const char* value, bool writeable, bool internal = false) : PathString(value) {
+    if (key == NULL) {
+      _key = NULL;
+    } else {
+      _key = AllocateHeap(strlen(key)+1, mtInternal);
+      strcpy(_key, key);
+    }
     _next = NULL;
+    _internal = internal;
     _writeable = writeable;
   }
 };
@@ -273,7 +308,13 @@
   static SystemProperty *_java_library_path;
   static SystemProperty *_java_home;
   static SystemProperty *_java_class_path;
-  static SystemProperty *_sun_boot_class_path;
+  static SystemProperty *_jdk_boot_class_path_append;
+
+  // The constructed value of the system class path after
+  // argument processing and JVMTI OnLoad additions via
+  // calls to AddToBootstrapClassLoaderSearch.  This is the
+  // final form before ClassLoader::setup_bootstrap_search().
+  static PathString *_system_boot_class_path;
 
   // temporary: to emit warning if the default ext dirs are not empty.
   // remove this variable when the warning is no longer needed.
@@ -298,7 +339,7 @@
   // Value of the conservative maximum heap alignment needed
   static size_t  _conservative_max_heap_alignment;
 
-  static uintx _min_heap_size;
+  static uintx  _min_heap_size;
 
   // -Xrun arguments
   static AgentLibraryList _libraryList;
@@ -323,6 +364,17 @@
   static void set_java_compiler(bool arg) { _java_compiler = arg; }
   static bool java_compiler()   { return _java_compiler; }
 
+  // Capture the index location of -Xbootclasspath\a within sysclasspath.
+  // Used when setting up the bootstrap search path in order to
+  // mark the boot loader's append path observability boundary.
+  static int _bootclassloader_append_index;
+
+  // -Xpatch flag
+  static char** _patch_dirs;
+  static int _patch_dirs_count;
+  static void set_patch_dirs(char** dirs) { _patch_dirs = dirs; }
+  static void set_patch_dirs_count(int count) { _patch_dirs_count = count; }
+
   // -Xdebug flag
   static bool _xdebug_mode;
   static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
@@ -373,6 +425,9 @@
   // System properties
   static bool add_property(const char* prop);
 
+  // Miscellaneous system property setter
+  static bool append_to_addmods_property(const char* module_name);
+
   // Aggressive optimization flags.
   static jint set_aggressive_opts_flags();
 
@@ -406,8 +461,8 @@
   static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
                                  const JavaVMInitArgs *java_options_args,
                                  const JavaVMInitArgs *cmd_line_args);
-  static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, Flag::Flags origin);
-  static jint finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required);
+  static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, ArgumentBootClassPath* bcp_p, bool* bcp_assembly_required_p, Flag::Flags origin);
+  static jint finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required);
   static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
 
   static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
@@ -569,6 +624,18 @@
   static size_t min_heap_size()             { return _min_heap_size; }
   static void  set_min_heap_size(size_t v)  { _min_heap_size = v;  }
 
+  // -Xbootclasspath/a
+  static int  bootclassloader_append_index() {
+    return _bootclassloader_append_index;
+  }
+  static void set_bootclassloader_append_index(int value) {
+    _bootclassloader_append_index = value;
+  }
+
+  // -Xpatch
+  static char** patch_dirs()             { return _patch_dirs; }
+  static int patch_dirs_count()          { return _patch_dirs_count; }
+
   // -Xrun
   static AgentLibrary* libraries()          { return _libraryList.first(); }
   static bool init_libraries_at_startup()   { return !_libraryList.is_empty(); }
@@ -625,24 +692,35 @@
   static void set_java_home(const char *value) { _java_home->set_value(value); }
   static void set_library_path(const char *value) { _java_library_path->set_value(value); }
   static void set_ext_dirs(char *value)     { _ext_dirs = os::strdup_check_oom(value); }
-  static void set_sysclasspath(const char *value) { _sun_boot_class_path->set_value(value); }
-  static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); }
+
+  // Set up of the underlying system boot class path
+  static void set_jdkbootclasspath_append();
+  static void set_sysclasspath(const char *value) {
+    _system_boot_class_path->set_value(value);
+    set_jdkbootclasspath_append();
+  }
+  static void append_sysclasspath(const char *value) {
+    _system_boot_class_path->append_value(value);
+    set_jdkbootclasspath_append();
+  }
 
   static char* get_java_home() { return _java_home->value(); }
   static char* get_dll_dir() { return _sun_boot_library_path->value(); }
-  static char* get_sysclasspath() { return _sun_boot_class_path->value(); }
+  static char* get_sysclasspath() { return _system_boot_class_path->value(); }
   static char* get_ext_dirs()        { return _ext_dirs;  }
   static char* get_appclasspath() { return _java_class_path->value(); }
   static void  fix_appclasspath();
 
 
   // Operation modi
-  static Mode mode()                { return _mode; }
+  static Mode mode()                        { return _mode; }
   static bool is_interpreter_only() { return mode() == _int; }
 
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
+
+  static void check_unsupported_dumping_properties() NOT_CDS_RETURN;
 };
 
 bool Arguments::gc_selected() {
diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp
index 1a72cec..b2a3216 100644
--- a/hotspot/src/share/vm/runtime/frame.cpp
+++ b/hotspot/src/share/vm/runtime/frame.cpp
@@ -642,6 +642,13 @@
         m->name_and_sig_as_C_string(buf, buflen);
         st->print("j  %s", buf);
         st->print("+%d", this->interpreter_frame_bci());
+        ModuleEntry* module = m->method_holder()->module();
+        if (module->is_named()) {
+          module->name()->as_C_string(buf, buflen);
+          st->print(" %s", buf);
+          module->version()->as_C_string(buf, buflen);
+          st->print("@%s", buf);
+        }
       } else {
         st->print("j  " PTR_FORMAT, p2i(pc()));
       }
@@ -662,6 +669,13 @@
         st->print("J %d%s %s ",
                   nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
                   ((nm->compiler() != NULL) ? nm->compiler()->name() : ""));
+        ModuleEntry* module = m->method_holder()->module();
+        if (module->is_named()) {
+          module->name()->as_C_string(buf, buflen);
+          st->print(" %s", buf);
+          module->version()->as_C_string(buf, buflen);
+          st->print("@%s", buf);
+        }
         st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
                   buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
 #if INCLUDE_JVMCI
diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp
index 8e4636b..3d44d32 100644
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp
@@ -467,6 +467,14 @@
   return allocate_handle(obj);  // retry
 }
 
+void JNIHandleBlock::release_handle(jobject h) {
+  if (h != NULL) {
+    assert(chain_contains(h), "does not contain the JNI handle");
+    // Mark the handle as deleted, allocate will reuse it
+    *((oop*)h) = JNIHandles::deleted_handle();
+  }
+}
+
 
 void JNIHandleBlock::rebuild_free_list() {
   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
diff --git a/hotspot/src/share/vm/runtime/jniHandles.hpp b/hotspot/src/share/vm/runtime/jniHandles.hpp
index 069a1f3..7a39655 100644
--- a/hotspot/src/share/vm/runtime/jniHandles.hpp
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp
@@ -138,6 +138,9 @@
   // Handle allocation
   jobject allocate_handle(oop obj);
 
+  // Release Handle
+  void release_handle(jobject);
+
   // Block allocation and block free list management
   static JNIHandleBlock* allocate_block(Thread* thread = NULL);
   static void release_block(JNIHandleBlock* block, Thread* thread = NULL);
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp
index fa1aea2..7066ae2 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp
@@ -39,7 +39,7 @@
 
 Mutex*   Patching_lock                = NULL;
 Monitor* SystemDictionary_lock        = NULL;
-Mutex*   PackageTable_lock            = NULL;
+Mutex*   Module_lock                  = NULL;
 Mutex*   CompiledIC_lock              = NULL;
 Mutex*   InlineCacheBuffer_lock       = NULL;
 Mutex*   VMStatistic_lock             = NULL;
@@ -206,7 +206,7 @@
   def(JmethodIdCreation_lock       , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for creating jmethodIDs.
 
   def(SystemDictionary_lock        , Monitor, leaf,        true,  Monitor::_safepoint_check_always);     // lookups done by VM thread
-  def(PackageTable_lock            , Mutex  , leaf,        false, Monitor::_safepoint_check_always);
+  def(Module_lock                  , Mutex  , leaf+2,      true,  Monitor::_safepoint_check_always);
   def(InlineCacheBuffer_lock       , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);
   def(VMStatistic_lock             , Mutex  , leaf,        false, Monitor::_safepoint_check_always);
   def(ExpandHeap_lock              , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);     // Used during compilation by VM thread
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp
index eccd3ca..f603297 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp
@@ -32,7 +32,7 @@
 
 extern Mutex*   Patching_lock;                   // a lock used to guard code patching of compiled code
 extern Monitor* SystemDictionary_lock;           // a lock on the system dictionary
-extern Mutex*   PackageTable_lock;               // a lock on the class loader package table
+extern Mutex*   Module_lock;                     // a lock on module and package related data structures
 extern Mutex*   CompiledIC_lock;                 // a lock used to guard compiled IC patching and access
 extern Mutex*   InlineCacheBuffer_lock;          // a lock used to guard the InlineCacheBuffer
 extern Mutex*   VMStatistic_lock;                // a lock used to guard statistics count increment
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index c482d21..016b6e3 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -1193,67 +1193,14 @@
     return formatted_path;
 }
 
-// returns a PATH of all entries in the given directory that do not start with a '.'
-static char* expand_entries_to_path(char* directory, char fileSep, char pathSep) {
-  DIR* dir = os::opendir(directory);
-  if (dir == NULL) return NULL;
-
-  char* path = NULL;
-  size_t path_len = 0;  // path length including \0 terminator
-
-  size_t directory_len = strlen(directory);
-  struct dirent *entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
-  while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
-    const char* name = entry->d_name;
-    if (name[0] == '.') continue;
-
-    size_t name_len = strlen(name);
-    size_t needed = directory_len + name_len + 2;
-    size_t new_len = path_len + needed;
-    if (path == NULL) {
-      path = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
-    } else {
-      path = REALLOC_C_HEAP_ARRAY(char, path, new_len, mtInternal);
-    }
-    if (path == NULL)
-      break;
-
-    // append <pathSep>directory<fileSep>name
-    char* p = path;
-    if (path_len > 0) {
-      p += (path_len -1);
-      *p = pathSep;
-      p++;
-    }
-
-    strcpy(p, directory);
-    p += directory_len;
-
-    *p = fileSep;
-    p++;
-
-    strcpy(p, name);
-    p += name_len;
-
-    path_len = new_len;
-  }
-
-  FREE_C_HEAP_ARRAY(char, dbuf);
-  os::closedir(dir);
-
-  return path;
-}
-
 bool os::set_boot_path(char fileSep, char pathSep) {
   const char* home = Arguments::get_java_home();
   int home_len = (int)strlen(home);
 
-  char* sysclasspath = NULL;
   struct stat st;
 
-  // modular image if bootmodules.jimage exists
-  char* jimage = format_boot_path("%/lib/modules/" BOOT_IMAGE_NAME, home, home_len, fileSep, pathSep);
+  // modular image if "modules" jimage exists
+  char* jimage = format_boot_path("%/lib/" MODULES_IMAGE_NAME, home, home_len, fileSep, pathSep);
   if (jimage == NULL) return false;
   bool has_jimage = (os::stat(jimage, &st) == 0);
   if (has_jimage) {
@@ -1264,23 +1211,16 @@
   FREE_C_HEAP_ARRAY(char, jimage);
 
   // check if developer build with exploded modules
-  char* modules_dir = format_boot_path("%/modules", home, home_len, fileSep, pathSep);
-  if (os::stat(modules_dir, &st) == 0) {
-    if ((st.st_mode & S_IFDIR) == S_IFDIR) {
-      sysclasspath = expand_entries_to_path(modules_dir, fileSep, pathSep);
-    }
+  char* base_classes = format_boot_path("%/modules/java.base", home, home_len, fileSep, pathSep);
+  if (base_classes == NULL) return false;
+  if (os::stat(base_classes, &st) == 0) {
+    Arguments::set_sysclasspath(base_classes);
+    FREE_C_HEAP_ARRAY(char, base_classes);
+    return true;
   }
-  FREE_C_HEAP_ARRAY(char, modules_dir);
+  FREE_C_HEAP_ARRAY(char, base_classes);
 
-  // fallback to classes
-  if (sysclasspath == NULL)
-    sysclasspath = format_boot_path("%/classes", home, home_len, fileSep, pathSep);
-
-  if (sysclasspath == NULL) return false;
-  Arguments::set_sysclasspath(sysclasspath);
-  FREE_C_HEAP_ARRAY(char, sysclasspath);
-
-  return true;
+  return false;
 }
 
 /*
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 128c73c..7b71ca5 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -778,6 +778,8 @@
   // Amount beyond the callee frame size that we bang the stack.
   static int extra_bang_size_in_bytes();
 
+  static char** split_path(const char* path, int* n);
+
   // Extensions
 #include "runtime/os_ext.hpp"
 
@@ -993,7 +995,6 @@
                                 char fileSep,
                                 char pathSep);
   static bool set_boot_path(char fileSep, char pathSep);
-  static char** split_path(const char* path, int* n);
 
 };
 
diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp
index 7eda3c5..b60c63a 100644
--- a/hotspot/src/share/vm/runtime/reflection.cpp
+++ b/hotspot/src/share/vm/runtime/reflection.cpp
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verifier.hpp"
@@ -452,25 +454,193 @@
   return false;
 }
 
-bool Reflection::verify_class_access(const Klass* current_class,
-                                     const Klass* new_class,
-                                     bool classloader_only) {
+/*
+    Type Accessibility check for public types: Callee Type T is accessible to Caller Type S if:
+
+                        Callee T in             Callee T in package PT,
+                        unnamed module          runtime module MT
+ ------------------------------------------------------------------------------------------------
+
+ Caller S in package     If MS is loose: YES      If same classloader/package (PS == PT): YES
+ PS, runtime module MS   If MS can read T's       If same runtime module: (MS == MT): YES
+                         unnamed module: YES
+                                                  Else if (MS can read MT (Establish readability) &&
+                                                    MT exports PT to MS or to all modules): YES
+
+ ------------------------------------------------------------------------------------------------
+ Caller S in unnamed         YES                  Readability exists because unnamed module
+ module UM                                            "reads" all modules
+                                                  if (MT exports PT to UM or to all modules): YES
+
+ ------------------------------------------------------------------------------------------------
+
+ Note: a loose module is a module that can read all current and future unnamed modules.
+*/
+Reflection::VerifyClassAccessResults Reflection::verify_class_access(
+  const Klass* current_class, const Klass* new_class, bool classloader_only) {
+
   // Verify that current_class can access new_class.  If the classloader_only
   // flag is set, we automatically allow any accesses in which current_class
   // doesn't have a classloader.
   if ((current_class == NULL) ||
       (current_class == new_class) ||
-      (new_class->is_public()) ||
       is_same_class_package(current_class, new_class)) {
-    return true;
+    return ACCESS_OK;
   }
   // Allow all accesses from sun/reflect/MagicAccessorImpl subclasses to
   // succeed trivially.
   if (current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
-    return true;
+    return ACCESS_OK;
   }
 
-  return can_relax_access_check_for(current_class, new_class, classloader_only);
+  // module boundaries
+  if (new_class->is_public()) {
+    // Ignore modules for DumpSharedSpaces because we do not have any package
+    // or module information for modules other than java.base.
+    if (DumpSharedSpaces) {
+      return ACCESS_OK;
+    }
+
+    // Find the module entry for current_class, the accessor
+    ModuleEntry* module_from = InstanceKlass::cast(current_class)->module();
+    // Find the module entry for new_class, the accessee
+    if (new_class->is_objArray_klass()) {
+      new_class = ObjArrayKlass::cast(new_class)->bottom_klass();
+    }
+    if (!new_class->is_instance_klass()) {
+      // Everyone can read a typearray.
+      assert (new_class->is_typeArray_klass(), "Unexpected klass type");
+      return ACCESS_OK;
+    }
+    ModuleEntry* module_to = InstanceKlass::cast(new_class)->module();
+
+    // both in same (possibly unnamed) module
+    if (module_from == module_to) {
+      return ACCESS_OK;
+    }
+
+    // Acceptable access to a type in an unamed module.  Note that since
+    // unnamed modules can read all unnamed modules, this also handles the
+    // case where module_from is also unnamed but in a different class loader.
+    if (!module_to->is_named() &&
+        (module_from->can_read_all_unnamed() || module_from->can_read(module_to))) {
+      return ACCESS_OK;
+    }
+
+    // Establish readability, check if module_from is allowed to read module_to.
+    if (!module_from->can_read(module_to)) {
+      return MODULE_NOT_READABLE;
+    }
+
+    PackageEntry* package_to = InstanceKlass::cast(new_class)->package();
+    assert(package_to != NULL, "can not obtain new_class' package");
+
+    // Once readability is established, if module_to exports T unqualifiedly,
+    // (to all modules), than whether module_from is in the unnamed module
+    // or not does not matter, access is allowed.
+    if (package_to->is_unqual_exported()) {
+      return ACCESS_OK;
+    }
+
+    // Access is allowed if both 1 & 2 hold:
+    //   1. Readability, module_from can read module_to (established above).
+    //   2. Either module_to exports T to module_from qualifiedly.
+    //      or
+    //      module_to exports T to all unnamed modules and module_from is unnamed.
+    //      or
+    //      module_to exports T unqualifiedly to all modules (checked above).
+    if (!package_to->is_qexported_to(module_from)) {
+      return TYPE_NOT_EXPORTED;
+    }
+    return ACCESS_OK;
+  }
+
+  if (can_relax_access_check_for(current_class, new_class, classloader_only)) {
+    return ACCESS_OK;
+  }
+  return OTHER_PROBLEM;
+}
+
+// Return an error message specific to the specified Klass*'s and result.
+// This function must be called from within a block containing a ResourceMark.
+char* Reflection::verify_class_access_msg(const Klass* current_class,
+                                          const Klass* new_class,
+                                          VerifyClassAccessResults result) {
+  assert(result != ACCESS_OK, "must be failure result");
+  char * msg = NULL;
+  if (result != OTHER_PROBLEM && new_class != NULL && current_class != NULL) {
+    // Find the module entry for current_class, the accessor
+    ModuleEntry* module_from = InstanceKlass::cast(current_class)->module();
+    const char * module_from_name = module_from->is_named() ? module_from->name()->as_C_string() : UNNAMED_MODULE;
+    const char * current_class_name = current_class->external_name();
+
+    // Find the module entry for new_class, the accessee
+    ModuleEntry* module_to = NULL;
+    if (new_class->is_objArray_klass()) {
+      new_class = ObjArrayKlass::cast(new_class)->bottom_klass();
+    }
+    if (new_class->is_instance_klass()) {
+      module_to = InstanceKlass::cast(new_class)->module();
+    } else {
+      module_to = ModuleEntryTable::javabase_module();
+    }
+    const char * module_to_name = module_to->is_named() ? module_to->name()->as_C_string() : UNNAMED_MODULE;
+    const char * new_class_name = new_class->external_name();
+
+    if (result == MODULE_NOT_READABLE) {
+      assert(module_from->is_named(), "Unnamed modules can read all modules");
+      if (module_to->is_named()) {
+        size_t len = 100 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*strlen(module_to_name);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not read module %s",
+          current_class_name, module_from_name, new_class_name,
+          module_to_name, module_from_name, module_to_name);
+      } else {
+        jobject jlrm = module_to->module();
+        assert(jlrm != NULL, "Null jlrm in module_to ModuleEntry");
+        intptr_t identity_hash = JNIHandles::resolve(jlrm)->identity_hash();
+        size_t len = 160 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*sizeof(uintx);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in unnamed module @" SIZE_FORMAT_HEX ") because module %s does not read unnamed module @" SIZE_FORMAT_HEX,
+          current_class_name, module_from_name, new_class_name, uintx(identity_hash),
+          module_from_name, uintx(identity_hash));
+      }
+
+    } else if (result == TYPE_NOT_EXPORTED) {
+      assert(InstanceKlass::cast(new_class)->package() != NULL,
+             "Unnamed packages are always exported");
+      const char * package_name =
+        InstanceKlass::cast(new_class)->package()->name()->as_klass_external_name();
+      assert(module_to->is_named(), "Unnamed modules export all packages");
+      if (module_from->is_named()) {
+        size_t len = 118 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*strlen(module_to_name) + strlen(package_name);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not export %s to module %s",
+          current_class_name, module_from_name, new_class_name,
+          module_to_name, module_to_name, package_name, module_from_name);
+      } else {
+        jobject jlrm = module_from->module();
+        assert(jlrm != NULL, "Null jlrm in module_from ModuleEntry");
+        intptr_t identity_hash = JNIHandles::resolve(jlrm)->identity_hash();
+        size_t len = 170 + strlen(current_class_name) + strlen(new_class_name) +
+          2*strlen(module_to_name) + strlen(package_name) + 2*sizeof(uintx);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in unnamed module @" SIZE_FORMAT_HEX ") cannot access class %s (in module %s) because module %s does not export %s to unnamed module @" SIZE_FORMAT_HEX,
+          current_class_name, uintx(identity_hash), new_class_name, module_to_name,
+          module_to_name, package_name, uintx(identity_hash));
+      }
+    } else {
+        ShouldNotReachHere();
+    }
+  }  // result != OTHER_PROBLEM...
+  return msg;
 }
 
 bool Reflection::verify_field_access(const Klass* current_class,
diff --git a/hotspot/src/share/vm/runtime/reflection.hpp b/hotspot/src/share/vm/runtime/reflection.hpp
index 920cf4c..736e21f 100644
--- a/hotspot/src/share/vm/runtime/reflection.hpp
+++ b/hotspot/src/share/vm/runtime/reflection.hpp
@@ -53,6 +53,14 @@
     MAX_DIM           = 255
   };
 
+  // Results returned by verify_class_access()
+  enum VerifyClassAccessResults {
+    ACCESS_OK = 0,
+    MODULE_NOT_READABLE = 1,
+    TYPE_NOT_EXPORTED = 2,
+    OTHER_PROBLEM = 3
+  };
+
   // Boxing. Returns boxed value of appropriate type. Throws IllegalArgumentException.
   static oop box(jvalue* v, BasicType type, TRAPS);
   // Unboxing. Returns type code and sets value.
@@ -73,9 +81,14 @@
   static arrayOop reflect_new_multi_array(oop element_mirror, typeArrayOop dimensions, TRAPS);
 
   // Verification
-  static bool     verify_class_access(const Klass* current_class,
-                                      const Klass* new_class,
-                                      bool classloader_only);
+  static VerifyClassAccessResults verify_class_access(const Klass* current_class,
+                                                      const Klass* new_class,
+                                                      bool classloader_only);
+  // Return an error message specific to the specified Klass*'s and result.
+  // This function must be called from within a block containing a ResourceMark.
+  static char*    verify_class_access_msg(const Klass* current_class,
+                                          const Klass* new_class,
+                                          const VerifyClassAccessResults result);
 
   static bool     verify_field_access(const Klass* current_class,
                                       const Klass* resolved_class,
diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp
index 4adec0c..fe69768 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp
@@ -39,6 +39,8 @@
 #include "interpreter/interpreterRuntime.hpp"
 #include "logging/log.hpp"
 #include "memory/universe.inline.hpp"
+#include "oops/klass.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/forte.hpp"
 #include "prims/jvmtiExport.hpp"
@@ -1915,28 +1917,58 @@
 }
 JRT_END
 
+// The caller of generate_class_cast_message() (or one of its callers)
+// must use a ResourceMark in order to correctly free the result.
 char* SharedRuntime::generate_class_cast_message(
-    JavaThread* thread, const char* objName) {
+    JavaThread* thread, Klass* caster_klass) {
 
   // Get target class name from the checkcast instruction
   vframeStream vfst(thread, true);
   assert(!vfst.at_end(), "Java frame must exist");
   Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci()));
-  Klass* targetKlass = vfst.method()->constants()->klass_at(
+  Klass* target_klass = vfst.method()->constants()->klass_at(
     cc.index(), thread);
-  return generate_class_cast_message(objName, targetKlass->external_name());
+  return generate_class_cast_message(caster_klass, target_klass);
 }
 
 char* SharedRuntime::generate_class_cast_message(
-    const char* objName, const char* targetKlassName, const char* desc) {
-  size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
+    Klass* caster_klass, Klass* target_klass) {
+
+  const char* caster_klass_name = caster_klass->external_name();
+  Klass* c_klass = caster_klass->is_objArray_klass() ?
+    ObjArrayKlass::cast(caster_klass)->bottom_klass() : caster_klass;
+  ModuleEntry* caster_module;
+  const char* caster_module_name;
+  if (c_klass->is_instance_klass()) {
+    caster_module = InstanceKlass::cast(c_klass)->module();
+    caster_module_name = caster_module->is_named() ?
+      caster_module->name()->as_C_string() : UNNAMED_MODULE;
+  } else {
+    caster_module_name = "java.base";
+  }
+  const char* target_klass_name = target_klass->external_name();
+  Klass* t_klass = target_klass->is_objArray_klass() ?
+    ObjArrayKlass::cast(target_klass)->bottom_klass() : target_klass;
+  ModuleEntry* target_module;
+  const char* target_module_name;
+  if (t_klass->is_instance_klass()) {
+    target_module = InstanceKlass::cast(t_klass)->module();
+    target_module_name = target_module->is_named() ?
+      target_module->name()->as_C_string(): UNNAMED_MODULE;
+  } else {
+    target_module_name = "java.base";
+  }
+
+  size_t msglen = strlen(caster_klass_name) + strlen(caster_module_name) +
+     strlen(target_klass_name) + strlen(target_module_name) + 50;
 
   char* message = NEW_RESOURCE_ARRAY(char, msglen);
   if (NULL == message) {
     // Shouldn't happen, but don't cause even more problems if it does
-    message = const_cast<char*>(objName);
+    message = const_cast<char*>(caster_klass_name);
   } else {
-    jio_snprintf(message, msglen, "%s%s%s", objName, desc, targetKlassName);
+    jio_snprintf(message, msglen, "%s (in module: %s) cannot be cast to %s (in module: %s)",
+      caster_klass_name, caster_module_name, target_klass_name, target_module_name);
   }
   return message;
 }
diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp
index f00b911..10c94e6 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp
@@ -293,22 +293,21 @@
   // Fill in the "X cannot be cast to a Y" message for ClassCastException
   //
   // @param thr the current thread
-  // @param name the name of the class of the object attempted to be cast
+  // @param caster_klass the class of the object we are casting
   // @return the dynamically allocated exception message (must be freed
   // by the caller using a resource mark)
   //
   // BCP must refer to the current 'checkcast' opcode for the frame
   // on top of the stack.
-  // The caller (or one of it's callers) must use a ResourceMark
+  // The caller (or one of its callers) must use a ResourceMark
   // in order to correctly free the result.
   //
-  static char* generate_class_cast_message(JavaThread* thr, const char* name);
+  static char* generate_class_cast_message(JavaThread* thr, Klass* caster_klass);
 
   // Fill in the "X cannot be cast to a Y" message for ClassCastException
   //
-  // @param name the name of the class of the object attempted to be cast
-  // @param klass the name of the target klass attempt
-  // @param gripe the specific kind of problem being reported
+  // @param caster_klass the class of the object we are casting
+  // @param target_klass the target klass attempt
   // @return the dynamically allocated exception message (must be freed
   // by the caller using a resource mark)
   //
@@ -317,8 +316,7 @@
   // The caller (or one of it's callers) must use a ResourceMark
   // in order to correctly free the result.
   //
-  static char* generate_class_cast_message(const char* name, const char* klass,
-                                           const char* gripe = " cannot be cast to ");
+  static char* generate_class_cast_message(Klass* caster_klass, Klass* target_klass);
 
   // Resolves a call site- may patch in the destination of the call into the
   // compiled code.
diff --git a/hotspot/src/share/vm/runtime/statSampler.cpp b/hotspot/src/share/vm/runtime/statSampler.cpp
index 3e693d9..cc88f88 100644
--- a/hotspot/src/share/vm/runtime/statSampler.cpp
+++ b/hotspot/src/share/vm/runtime/statSampler.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -238,7 +238,6 @@
 
 // unstable interface, unsupported counters
 static const char* property_counters_uu[] = {
-  "sun.boot.class.path",
   "sun.boot.library.path",
   NULL
 };
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index 9d6531d..a7b9f41 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
@@ -118,6 +119,9 @@
 #include "runtime/rtmLocking.hpp"
 #endif
 
+// Initialization after module runtime initialization
+void universe_post_module_init();  // must happen after call_initPhase2
+
 #ifdef DTRACE_ENABLED
 
 // Only bother with this argument setup if dtrace is available
@@ -997,15 +1001,6 @@
   return thread_oop();
 }
 
-static void call_initializeSystemClass(TRAPS) {
-  Klass* k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
-  instanceKlassHandle klass (THREAD, k);
-
-  JavaValue result(T_VOID);
-  JavaCalls::call_static(&result, klass, vmSymbols::initializeSystemClass_name(),
-                         vmSymbols::void_method_signature(), CHECK);
-}
-
 char java_runtime_name[128] = "";
 char java_runtime_version[128] = "";
 
@@ -3364,6 +3359,62 @@
   // If CompilerThreads ever become non-JavaThreads, add them here
 }
 
+// The system initialization in the library has three phases.
+//
+// Phase 1: java.lang.System class initialization
+//     java.lang.System is a primordial class loaded and initialized
+//     by the VM early during startup.  java.lang.System.<clinit>
+//     only does registerNatives and keeps the rest of the class
+//     initialization work later until thread initialization completes.
+//
+//     System.initPhase1 initializes the system properties, the static
+//     fields in, out, and err. Set up java signal handlers, OS-specific
+//     system settings, and thread group of the main thread.
+static void call_initPhase1(TRAPS) {
+  Klass* k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase1_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+}
+
+// Phase 2. Module system initialization
+//     This will initialize the module system.  Only java.base classes
+//     can be loaded until phase 2 completes.
+//
+//     Call System.initPhase2 after the compiler initialization and jsr292
+//     classes get initialized because module initialization runs a lot of java
+//     code, that for performance reasons, should be compiled.  Also, this will
+//     enable the startup code to use lambda and other language features in this
+//     phase and onward.
+//
+//     After phase 2, The VM will begin search classes from -Xbootclasspath/a.
+static void call_initPhase2(TRAPS) {
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase2_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+  universe_post_module_init();
+}
+
+// Phase 3. final setup - set security manager, system class loader and TCCL
+//
+//     This will instantiate and set the security manager, set the system class
+//     loader as well as the thread context class loader.  The security manager
+//     and system class loader may be a custom class loaded from -Xbootclasspath/a,
+//     other modules or the application's classpath.
+static void call_initPhase3(TRAPS) {
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase3_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+}
+
 void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
   TraceStartupTime timer("Initialize java.lang classes");
 
@@ -3391,10 +3442,15 @@
   java_lang_Thread::set_thread_status(thread_object,
                                       java_lang_Thread::RUNNABLE);
 
+  // The VM creates objects of this class.
+  initialize_class(vmSymbols::java_lang_reflect_Module(), CHECK);
+
   // The VM preresolves methods to these classes. Make sure that they get initialized
   initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK);
   initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK);
-  call_initializeSystemClass(CHECK);
+
+  // Phase 1 of the system initialization in the library, java.lang.System class initialization
+  call_initPhase1(CHECK);
 
   // get the Java runtime name after java.lang.System is initialized
   JDK_Version::set_runtime_name(get_java_runtime_name(THREAD));
@@ -3612,10 +3668,10 @@
 
   // Always call even when there are not JVMTI environments yet, since environments
   // may be attached late and JVMTI must track phases of VM execution
-  JvmtiExport::enter_start_phase();
+  JvmtiExport::enter_early_start_phase();
 
   // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
-  JvmtiExport::post_vm_start();
+  JvmtiExport::post_early_vm_start();
 
   initialize_java_lang_classes(main_thread, CHECK_JNI_ERR);
 
@@ -3643,12 +3699,9 @@
   Management::record_vm_init_completed();
 #endif // INCLUDE_MANAGEMENT
 
-  // Compute system loader. Note that this has to occur after set_init_completed, since
-  // valid exceptions may be thrown in the process.
   // Note that we do not use CHECK_0 here since we are inside an EXCEPTION_MARK and
   // set_init_completed has just been called, causing exceptions not to be shortcut
   // anymore. We call vm_exit_during_initialization directly instead.
-  SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
 
 #if INCLUDE_ALL_GCS
   // Support for ConcurrentMarkSweep. This should be cleaned up
@@ -3663,10 +3716,6 @@
   }
 #endif // INCLUDE_ALL_GCS
 
-  // Always call even when there are not JVMTI environments yet, since environments
-  // may be attached late and JVMTI must track phases of VM execution
-  JvmtiExport::enter_live_phase();
-
   // Signal Dispatcher needs to be started before VMInit event is posted
   os::signal_init();
 
@@ -3685,13 +3734,6 @@
     create_vm_init_libraries();
   }
 
-  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
-  JvmtiExport::post_vm_initialized();
-
-  if (TRACE_START() != JNI_OK) {
-    vm_exit_during_initialization("Failed to start tracing backend.");
-  }
-
   if (CleanChunkPoolAsync) {
     Chunk::start_chunk_pool_cleaner_task();
   }
@@ -3716,6 +3758,34 @@
   // (see SystemDictionary::find_method_handle_intrinsic).
   initialize_jsr292_core_classes(CHECK_JNI_ERR);
 
+  // This will initialize the module system.  Only java.base classes can be
+  // loaded until phase 2 completes
+  call_initPhase2(CHECK_JNI_ERR);
+
+  // Always call even when there are not JVMTI environments yet, since environments
+  // may be attached late and JVMTI must track phases of VM execution
+  JvmtiExport::enter_start_phase();
+
+  // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
+  JvmtiExport::post_vm_start();
+
+  // Final system initialization including security manager and system class loader
+  call_initPhase3(CHECK_JNI_ERR);
+
+  // cache the system class loader
+  SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
+
+  // Always call even when there are not JVMTI environments yet, since environments
+  // may be attached late and JVMTI must track phases of VM execution
+  JvmtiExport::enter_live_phase();
+
+  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
+  JvmtiExport::post_vm_initialized();
+
+  if (TRACE_START() != JNI_OK) {
+    vm_exit_during_initialization("Failed to start tracing backend.");
+  }
+
 #if INCLUDE_MANAGEMENT
   Management::initialize(THREAD);
 
diff --git a/hotspot/src/share/vm/services/jmm.h b/hotspot/src/share/vm/services/jmm.h
index 0362e79..b6497cd 100644
--- a/hotspot/src/share/vm/services/jmm.h
+++ b/hotspot/src/share/vm/services/jmm.h
@@ -59,7 +59,6 @@
   unsigned int isThreadContentionMonitoringSupported : 1;
   unsigned int isCurrentThreadCpuTimeSupported : 1;
   unsigned int isOtherThreadCpuTimeSupported : 1;
-  unsigned int isBootClassPathSupported : 1;
   unsigned int isObjectMonitorUsageSupported : 1;
   unsigned int isSynchronizerUsageSupported : 1;
   unsigned int isThreadAllocatedMemorySupported : 1;
diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp
index 892ce92..6de924a 100644
--- a/hotspot/src/share/vm/services/management.cpp
+++ b/hotspot/src/share/vm/services/management.cpp
@@ -121,7 +121,6 @@
     _optional_support.isOtherThreadCpuTimeSupported = 0;
   }
 
-  _optional_support.isBootClassPathSupported = 1;
   _optional_support.isObjectMonitorUsageSupported = 1;
 #if INCLUDE_SERVICES
   // This depends on the heap inspector
diff --git a/hotspot/src/share/vm/trace/traceBackend.cpp b/hotspot/src/share/vm/trace/traceBackend.cpp
new file mode 100644
index 0000000..a930774
--- /dev/null
+++ b/hotspot/src/share/vm/trace/traceBackend.cpp
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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 "precompiled.hpp"
+#include "prims/jni.h"
+
+extern "C" void JNICALL trace_register_natives(JNIEnv*, jclass) {}
diff --git a/hotspot/src/share/vm/trace/traceDataTypes.hpp b/hotspot/src/share/vm/trace/traceDataTypes.hpp
index b51343d..5df07eb 100644
--- a/hotspot/src/share/vm/trace/traceDataTypes.hpp
+++ b/hotspot/src/share/vm/trace/traceDataTypes.hpp
@@ -57,6 +57,10 @@
 
 typedef enum ReservedEvent ReservedEvent;
 
+typedef u8 traceid;
+
+class ModuleEntry;
+class PackageEntry;
 class Symbol;
 
 #endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP
diff --git a/hotspot/src/share/vm/trace/traceMacros.hpp b/hotspot/src/share/vm/trace/traceMacros.hpp
index c67024a..23a1557 100644
--- a/hotspot/src/share/vm/trace/traceMacros.hpp
+++ b/hotspot/src/share/vm/trace/traceMacros.hpp
@@ -32,10 +32,14 @@
 #define TRACE_KLASS_CREATION(k, p, t)
 
 #define TRACE_INIT_KLASS_ID(k)
+#define TRACE_INIT_MODULE_ID(m)
+#define TRACE_INIT_PACKAGE_ID(p)
 #define TRACE_INIT_THREAD_ID(td)
 #define TRACE_DATA TraceThreadData
 
 #define THREAD_TRACE_ID(thread) ((traceid)thread->osthread()->thread_id())
+extern "C" void JNICALL trace_register_natives(JNIEnv*, jclass);
+#define TRACE_REGISTER_NATIVES ((void*)((address_word)(&trace_register_natives)))
 #define TRACE_START() JNI_OK
 #define TRACE_INITIALIZE() JNI_OK
 
diff --git a/hotspot/src/share/vm/trace/tracetypes.xml b/hotspot/src/share/vm/trace/tracetypes.xml
index 52d6e9a..c4c3ddb 100644
--- a/hotspot/src/share/vm/trace/tracetypes.xml
+++ b/hotspot/src/share/vm/trace/tracetypes.xml
@@ -78,6 +78,7 @@
                   type="U8" builtin_type="CLASS">
       <value type="CLASS" field="loaderClass" label="ClassLoader"/>
       <value type="SYMBOL" field="name" label="Name"/>
+      <value type="PACKAGE" field="package" label="Package"/>
       <value type="SHORT" field="modifiers" label="Access modifiers"/>
     </content_type>
 
@@ -174,6 +175,21 @@
                   type="U8" jvm_type="INFLATECAUSE">
       <value type="UTF8" field="cause" label="cause" />
     </content_type>
+
+    <content_type id="Module" hr_name="Module"
+              type="U8" jvm_type="MODULE">
+      <value type="SYMBOL" field="name" label="Name"/>
+      <value type="SYMBOL" field="version" label="Version"/>
+      <value type="SYMBOL" field="location" label="Location"/>
+      <value type="CLASS" field="classLoader" label="ClassLoader"/>
+    </content_type>
+
+    <content_type id="Package" hr_name="Package"
+              type="U8" jvm_type="PACKAGE">
+      <value type="SYMBOL" field="name" label="Name"/>
+      <value type="MODULE" field="module" label="Module"/>
+      <value type="BOOLEAN" field="exported" label="Exported"/>
+    </content_type>
   </content_types>
 
 
@@ -286,6 +302,12 @@
     <primary_type symbol="CLASS" datatype="U8" contenttype="CLASS"
                   type="const Klass*" sizeop="sizeof(u8)"/>
 
+    <primary_type symbol="MODULE" datatype="U8" contenttype="MODULE"
+                  type="const ModuleEntry*" sizeop="sizeof(u8)"/>
+
+    <primary_type symbol="PACKAGE" datatype="U8" contenttype="PACKAGE"
+              type="const PackageEntry*" sizeop="sizeof(u8)"/>
+
     <!-- A Method *. The method is marked as "used" and will eventually be
          written into the recording constant pool. -->
     <primary_type symbol="METHOD" datatype="U8" contenttype="METHOD"
diff --git a/hotspot/src/share/vm/utilities/dtrace_disabled.hpp b/hotspot/src/share/vm/utilities/dtrace_disabled.hpp
index 4009359..44f49f6 100644
--- a/hotspot/src/share/vm/utilities/dtrace_disabled.hpp
+++ b/hotspot/src/share/vm/utilities/dtrace_disabled.hpp
@@ -1084,6 +1084,12 @@
 #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(arg0)
 #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN_ENABLED()  0
 
+/* Modules */
+#define HOTSPOT_JNI_GETMODULE_ENTRY(arg0, arg1)
+#define HOTSPOT_JNI_GETMODULE_ENTRY_ENABLED()  0
+#define HOTSPOT_JNI_GETMODULE_RETURN(arg0)
+#define HOTSPOT_JNI_GETMODULE_RETURN_ENABLED()
+
 #else /* !defined(DTRACE_ENABLED) */
 #error This file should only be included when dtrace is not enabled
 #endif /* !defined(DTRACE_ENABLED) */
diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp
index 3bafaec..de62ba3 100644
--- a/hotspot/src/share/vm/utilities/ostream.cpp
+++ b/hotspot/src/share/vm/utilities/ostream.cpp
@@ -706,8 +706,10 @@
       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
         // Print in two stages to avoid problems with long
         // keys/values.
+        assert(p->key() != NULL, "p->key() is NULL");
         text->print_raw(p->key());
         text->put('=');
+        assert(p->value() != NULL, "p->value() is NULL");
         text->print_raw_cr(p->value());
       }
       xs->tail("properties");
diff --git a/hotspot/src/share/vm/utilities/utf8.cpp b/hotspot/src/share/vm/utilities/utf8.cpp
index d7a6043..93ad3e2 100644
--- a/hotspot/src/share/vm/utilities/utf8.cpp
+++ b/hotspot/src/share/vm/utilities/utf8.cpp
@@ -333,6 +333,68 @@
                  + ((str[4] & 0x0f) << 6)  + (str[5] & 0x3f);
 }
 
+bool UTF8::is_legal_utf8(const unsigned char* buffer, int length,
+                         bool version_leq_47) {
+  int i = 0;
+  int count = length >> 2;
+  for (int k=0; k<count; k++) {
+    unsigned char b0 = buffer[i];
+    unsigned char b1 = buffer[i+1];
+    unsigned char b2 = buffer[i+2];
+    unsigned char b3 = buffer[i+3];
+    // For an unsigned char v,
+    // (v | v - 1) is < 128 (highest bit 0) for 0 < v < 128;
+    // (v | v - 1) is >= 128 (highest bit 1) for v == 0 or v >= 128.
+    unsigned char res = b0 | b0 - 1 |
+                        b1 | b1 - 1 |
+                        b2 | b2 - 1 |
+                        b3 | b3 - 1;
+    if (res >= 128) break;
+    i += 4;
+  }
+  for(; i < length; i++) {
+    unsigned short c;
+    // no embedded zeros
+    if (buffer[i] == 0) return false;
+    if(buffer[i] < 128) {
+      continue;
+    }
+    if ((i + 5) < length) { // see if it's legal supplementary character
+      if (UTF8::is_supplementary_character(&buffer[i])) {
+        c = UTF8::get_supplementary_character(&buffer[i]);
+        i += 5;
+        continue;
+      }
+    }
+    switch (buffer[i] >> 4) {
+      default: break;
+      case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
+        return false;
+      case 0xC: case 0xD:  // 110xxxxx  10xxxxxx
+        c = (buffer[i] & 0x1F) << 6;
+        i++;
+        if ((i < length) && ((buffer[i] & 0xC0) == 0x80)) {
+          c += buffer[i] & 0x3F;
+          if (version_leq_47 || c == 0 || c >= 0x80) {
+            break;
+          }
+        }
+        return false;
+      case 0xE:  // 1110xxxx 10xxxxxx 10xxxxxx
+        c = (buffer[i] & 0xF) << 12;
+        i += 2;
+        if ((i < length) && ((buffer[i-1] & 0xC0) == 0x80) && ((buffer[i] & 0xC0) == 0x80)) {
+          c += ((buffer[i-1] & 0x3F) << 6) + (buffer[i] & 0x3F);
+          if (version_leq_47 || c >= 0x800) {
+            break;
+          }
+        }
+        return false;
+    }  // end of switch
+  } // end of for
+  return true;
+}
+
 //-------------------------------------------------------------------------------------
 
 bool UNICODE::is_latin1(jchar c) {
diff --git a/hotspot/src/share/vm/utilities/utf8.hpp b/hotspot/src/share/vm/utilities/utf8.hpp
index 161eb41..1a30cb4 100644
--- a/hotspot/src/share/vm/utilities/utf8.hpp
+++ b/hotspot/src/share/vm/utilities/utf8.hpp
@@ -73,6 +73,9 @@
   static bool   equal(const jbyte* base1, int length1, const jbyte* base2,int length2);
   static bool   is_supplementary_character(const unsigned char* str);
   static jint   get_supplementary_character(const unsigned char* str);
+
+  static bool   is_legal_utf8(const unsigned char* buffer, int length,
+                              bool version_leq_47);
 };
 
 
diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT
index 8dd7c84..55979b0 100644
--- a/hotspot/test/TEST.ROOT
+++ b/hotspot/test/TEST.ROOT
@@ -32,8 +32,8 @@
 groups=TEST.groups [closed/TEST.groups]
 requires.properties=sun.arch.data.model
 
-# Tests using jtreg 4.1 b12 features
-requiredVersion=4.1 b12
+# Tests using jtreg 4.2 b01 features
+requiredVersion=4.2 b01
 
 # 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/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java
index f4109d6..24a8222 100644
--- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java
+++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java
@@ -22,6 +22,8 @@
  */
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -35,11 +37,11 @@
  * @modules java.base/sun.misc
  *          java.management
  *          java.base/jdk.internal
+ * @ignore 8132924
  * @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
  * @run main TestMonomorphicObjectCall
  */
 public class TestMonomorphicObjectCall {
-    final static String testClasses = System.getProperty("test.classes") + File.separator;
 
     private static void callFinalize(Object object) throws Throwable {
         // Call modified version of java.lang.Object::finalize() that is
@@ -50,6 +52,9 @@
 
     public static void main(String[] args) throws Throwable {
         if (args.length == 0) {
+            byte[] bytecode = Files.readAllBytes(Paths.get(System.getProperty("test.classes") + File.separator +
+                "java" + File.separator + "lang" + File.separator + "Object.class"));
+            ClassFileInstaller.writeClassToDisk("java.lang.Object", bytecode, "mods/java.base");
             // Execute new instance with modified java.lang.Object
             executeTestJvm();
         } else {
@@ -62,7 +67,7 @@
         // Execute test with modified version of java.lang.Object
         // in -Xbootclasspath.
         String[] vmOpts = new String[] {
-                "-Xbootclasspath/p:" + testClasses,
+                "-Xpatch:mods",
                 "-Xcomp",
                 "-XX:+IgnoreUnrecognizedVMOptions",
                 "-XX:-VerifyDependencies",
diff --git a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
index e650aa5..78ee713 100644
--- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
+++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java
@@ -24,13 +24,25 @@
 /**
  * @test
  * @bug 8057967
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library patches
+ * @build java.base/java.lang.invoke.MethodHandleHelper
  * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -Xlog:classunload
  *                         -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
- *                         -verbose:gc java.lang.invoke.CallSiteDepContextTest
+ *                         -verbose:gc compiler.jsr292.CallSiteDepContextTest
  */
-package java.lang.invoke;
 
-import java.lang.ref.*;
+package compiler.jsr292;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
 import java.lang.reflect.Field;
 
 import jdk.internal.org.objectweb.asm.*;
@@ -40,10 +52,10 @@
 
 public class CallSiteDepContextTest {
     static final Unsafe               UNSAFE = Unsafe.getUnsafe();
-    static final MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+    static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
     static final String           CLASS_NAME = "java/lang/invoke/Test";
     static final String          METHOD_NAME = "m";
-    static final MethodType             TYPE = MethodType.methodType(int.class);
+    static final MethodType TYPE = MethodType.methodType(int.class);
 
     static MutableCallSite mcs;
     static MethodHandle bsmMH;
@@ -77,7 +89,8 @@
             mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, METHOD_NAME, TYPE.toMethodDescriptorString(), null, null);
             mv.visitCode();
             Handle bsm = new Handle(H_INVOKESTATIC,
-                    "java/lang/invoke/CallSiteDepContextTest", "bootstrap",
+                    CallSiteDepContextTest.class.getName().replace(".", "/"),
+                    "bootstrap",
                     bsmMH.type().toMethodDescriptorString());
             mv.visitInvokeDynamicInsn("methodName", TYPE.toMethodDescriptorString(), bsm);
             mv.visitInsn(IRETURN);
@@ -99,9 +112,9 @@
         }
     }
 
-    public static void testHiddenDepField() throws Exception {
+    public static void testHiddenDepField() {
         try {
-            Field f = MethodHandleNatives.CallSiteContext.class.getDeclaredField("vmdependencies");
+            Field f = MethodHandleHelper.MHN_CALL_SITE_CONTEXT_CLASS.getDeclaredField("vmdependencies");
             throw new AssertionError("Context.dependencies field should be hidden");
         } catch(NoSuchFieldException e) { /* expected */ }
     }
@@ -111,8 +124,8 @@
         Class<?> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
 
         MethodHandle[] mhs = new MethodHandle[] {
-            LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),
-            LOOKUP.findStatic(cls2, METHOD_NAME, TYPE)
+                LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),
+                LOOKUP.findStatic(cls2, METHOD_NAME, TYPE)
         };
 
         mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
@@ -198,3 +211,4 @@
         System.out.println("TEST PASSED");
     }
 }
+
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/Agent.java b/hotspot/test/compiler/jsr292/NonInlinedCall/Agent.java
index 70665d5..e9f2f46 100644
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/Agent.java
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/Agent.java
@@ -20,28 +20,39 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+package compiler.jsr292.NonInlinedCall;
+
 import java.io.File;
 import java.io.PrintStream;
 import java.util.Arrays;
 
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.OutputAnalyzer;
+
 public class Agent {
     public static void main(String[] args) throws Exception {
         String jarName = args[0];
         String className = args[1];
         String manifestName = "manifest.mf";
 
-        System.out.println("Creating "+manifestName);
+        System.out.println("Creating " + manifestName);
         try (PrintStream out = new PrintStream(new File(manifestName))) {
             out.println("Premain-Class: " + className);
             out.println("Can-Redefine-Classes: true");
         }
-        System.out.println("Building "+jarName);
-        String[] jarArgs = new String[] {"-cfm", jarName, manifestName };
 
-        System.out.println("Running jar " + Arrays.toString(jarArgs));
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-        if (!jarTool.run(jarArgs)) {
-            throw new Error("jar failed: args=" + Arrays.toString(args));
-        }
+        System.out.println("Building " + jarName);
+        JDKToolLauncher jar = JDKToolLauncher
+                .create("jar")
+                .addToolArg("-cfm")
+                .addToolArg(jarName)
+                .addToolArg(manifestName);
+
+        System.out.println("Running jar " + Arrays.toString(jar.getCommand()));
+
+        ProcessBuilder pb = new ProcessBuilder(jar.getCommand());
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
     }
 }
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/GCTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/GCTest.java
index 49ce054..fc70585 100644
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/GCTest.java
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/GCTest.java
@@ -24,29 +24,38 @@
 /*
  * @test
  * @bug 8072008
- * @library /testlibrary /test/lib
- * @compile GCTest.java NonInlinedReinvoker.java
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              java.lang.invoke.GCTest
- *                              java.lang.invoke.GCTest$T
- *                              java.lang.invoke.NonInlinedReinvoker
- *                              jdk.test.lib.Asserts
- * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *                   -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
- *                      java.lang.invoke.GCTest
+ * @library /testlibrary /test/lib ../patches
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build java.base/java.lang.invoke.MethodHandleHelper
+ * @build sun.hotspot.WhiteBox
+ * @run main/bootclasspath -XX:+IgnoreUnrecognizedVMOptions
+ *                         -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                         -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
+ *                         -XX:+FoldStableValues
+ *                         compiler.jsr292.NonInlinedCall.GCTest
  */
-package java.lang.invoke;
 
-import sun.hotspot.WhiteBox;
+package compiler.jsr292.NonInlinedCall;
+
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodHandleHelper.NonInlinedReinvoker;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandle;
+
+import java.lang.invoke.MethodType;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+
 import jdk.internal.vm.annotation.DontInline;
 import jdk.internal.vm.annotation.Stable;
-import java.lang.ref.*;
+
+import sun.hotspot.WhiteBox;
+
 import static jdk.test.lib.Asserts.*;
 
 public class GCTest {
-    static final MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+    static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
 
     static class T {
         static int f1() { return 0; }
@@ -54,15 +63,15 @@
     }
 
     static @Stable MethodHandle mh;
-    static PhantomReference<LambdaForm> lform;
+    static PhantomReference<Object> lform;
 
-    static final ReferenceQueue<LambdaForm> rq = new ReferenceQueue<>();
+    static final ReferenceQueue<Object> rq = new ReferenceQueue<>();
     static final WhiteBox WB = WhiteBox.getWhiteBox();
 
     @DontInline
     static int invokeBasic() {
         try {
-            return (int) mh.invokeBasic();
+            return MethodHandleHelper.invokeBasicI(mh);
         } catch (Throwable e) {
             throw new Error(e);
         }
@@ -80,7 +89,7 @@
                 LOOKUP.findStatic(T.class, "f1", MethodType.methodType(int.class)));
 
         // Monitor LambdaForm GC
-        lform = new PhantomReference<>(mh.form, rq);
+        lform = new PhantomReference<>(MethodHandleHelper.getLambdaForm(mh), rq);
 
         test(0);
         WB.clearInlineCaches();
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
index 90724b3..225db60 100644
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
@@ -24,30 +24,33 @@
 /*
  * @test
  * @bug 8072008
- * @library /testlibrary /test/lib
- * @compile InvokeTest.java NonInlinedReinvoker.java
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              java.lang.invoke.InvokeTest
- *                              java.lang.invoke.InvokeTest$T
- *                              java.lang.invoke.InvokeTest$P1
- *                              java.lang.invoke.InvokeTest$P2
- *                              java.lang.invoke.InvokeTest$I
- *                              java.lang.invoke.NonInlinedReinvoker
- *                              jdk.test.lib.Asserts
- * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *                   -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
- *                      java.lang.invoke.InvokeTest
+ * @library /testlibrary /test/lib / ../patches
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build java.base/java.lang.invoke.MethodHandleHelper
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.jsr292.NonInlinedCall.InvokeTest
+ * @run main/bootclasspath -XX:+IgnoreUnrecognizedVMOptions
+ *                         -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                         -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
+ *                         compiler.jsr292.NonInlinedCall.InvokeTest
  */
-package java.lang.invoke;
+
+package compiler.jsr292.NonInlinedCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodHandleHelper.NonInlinedReinvoker;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import jdk.internal.vm.annotation.DontInline;
 
 import sun.hotspot.WhiteBox;
-import jdk.internal.vm.annotation.DontInline;
+
 import static jdk.test.lib.Asserts.*;
 
 public class InvokeTest {
-    static MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+    static MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
 
     static final MethodHandle virtualMH;  // invokevirtual   T.f1
     static final MethodHandle staticMH;   // invokestatic    T.f2
@@ -136,7 +139,7 @@
     @DontInline
     static void invokeBasic() {
         try {
-            Class<?> cls = (Class<?>)basicMH.invokeBasic();
+            Class<?> cls = (Class<?>)MethodHandleHelper.invokeBasicL(basicMH);
             assertEquals(cls, T.class);
         } catch (Throwable e) {
             throw new Error(e);
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/NonInlinedReinvoker.java b/hotspot/test/compiler/jsr292/NonInlinedCall/NonInlinedReinvoker.java
deleted file mode 100644
index c4c36d3..0000000
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/NonInlinedReinvoker.java
+++ /dev/null
@@ -1,48 +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 java.lang.invoke;
-
-class NonInlinedReinvoker extends DelegatingMethodHandle {
-    private final MethodHandle target;
-
-    private NonInlinedReinvoker(MethodHandle target, LambdaForm lf) {
-        super(target.type(), lf);
-        this.target = target;
-    }
-    @Override
-    protected MethodHandle getTarget() {
-        return target;
-    }
-
-    @Override
-    MethodHandle asTypeUncached(MethodType newType) {
-        return asTypeCache = target.asType(newType);
-    }
-
-    static MethodHandle make(MethodHandle target) {
-        LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(
-                target, -1, DelegatingMethodHandle.class, "reinvoker.dontInline",
-                /*forceInline=*/false, DelegatingMethodHandle.NF_getTarget, null);
-        return new NonInlinedReinvoker(target, lform);
-    }
-}
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/RedefineTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/RedefineTest.java
index 51481e8..6607ec1 100644
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/RedefineTest.java
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/RedefineTest.java
@@ -24,35 +24,46 @@
 /*
  * @test
  * @bug 8072008
- * @library /testlibrary /test/lib
- * @compile -XDignore.symbol.file RedefineTest.java Agent.java
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.misc
+ *          java.base/jdk.internal.vm.annotation
+ * @library /testlibrary /test/lib / ../patches
+ * @build sun.hotspot.WhiteBox
+ * @build java.base/java.lang.invoke.MethodHandleHelper
+ * @build compiler.jsr292.NonInlinedCall.RedefineTest
+ * @run main compiler.jsr292.NonInlinedCall.Agent agent.jar compiler.jsr292.NonInlinedCall.RedefineTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              java.lang.invoke.RedefineTest
- *                              Agent
- * @run main Agent agent.jar java.lang.invoke.RedefineTest
- * @run main/othervm -Xbootclasspath/a:. -javaagent:agent.jar
- *                   -XX:+IgnoreUnrecognizedVMOptions
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *                   -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
- *                      java.lang.invoke.RedefineTest
+ *                              compiler.jsr292.NonInlinedCall.RedefineTest
+ * @run main/bootclasspath -javaagent:agent.jar
+ *                         -XX:+IgnoreUnrecognizedVMOptions
+ *                         -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                         -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
+ *                         compiler.jsr292.NonInlinedCall.RedefineTest
  */
-package java.lang.invoke;
+
+package compiler.jsr292.NonInlinedCall;
 
 import sun.hotspot.WhiteBox;
-import sun.misc.Unsafe;
-import jdk.internal.org.objectweb.asm.*;
-import jdk.internal.vm.annotation.DontInline;
+
 import java.lang.instrument.ClassDefinition;
 import java.lang.instrument.Instrumentation;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodType;
+
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.org.objectweb.asm.*;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
 public class RedefineTest {
-    static final MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+    static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
     static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
-    static final String NAME = "java/lang/invoke/RedefineTest$T";
+    static final String NAME = "compiler/jsr292/NonInlinedCall/RedefineTest$T";
 
     static Class<?> getClass(int r) {
         byte[] classFile = getClassFile(r);
diff --git a/hotspot/test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java b/hotspot/test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java
new file mode 100644
index 0000000..a473262
--- /dev/null
+++ b/hotspot/test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java
@@ -0,0 +1,92 @@
+/*
+ * 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 java.lang.invoke;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.vm.annotation.ForceInline;
+/**
+ * Helper class to inject into java.lang.invoke that provides access to
+ * package-private methods in this package.
+ */
+
+public class MethodHandleHelper {
+
+    private MethodHandleHelper() { }
+
+    public static final Lookup IMPL_LOOKUP = Lookup.IMPL_LOOKUP;
+    public static final Class<?> MHN_CALL_SITE_CONTEXT_CLASS
+            = MethodHandleNatives.CallSiteContext.class;
+
+    public static void customize(MethodHandle mh) {
+        mh.customize();
+    }
+
+    @ForceInline
+    public static Object invokeBasicL(MethodHandle mh) throws Throwable {
+        return mh.invokeBasic();
+    }
+
+    @ForceInline
+    public static int invokeBasicI(MethodHandle mh) throws Throwable {
+        return (int) mh.invokeBasic();
+    }
+
+    public static MethodHandle varargsArray(int nargs) {
+        return MethodHandleImpl.varargsArray(nargs);
+    }
+
+    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+        return MethodHandleImpl.varargsArray(arrayType, nargs);
+    }
+
+    public static LambdaForm getLambdaForm(MethodHandle mh) {
+        return mh.form;
+    }
+
+    public static class NonInlinedReinvoker extends DelegatingMethodHandle {
+        private final MethodHandle target;
+
+        private NonInlinedReinvoker(MethodHandle target, LambdaForm lf) {
+            super(target.type(), lf);
+            this.target = target;
+        }
+        @Override
+        public MethodHandle getTarget() {
+            return target;
+        }
+
+        @Override
+        public MethodHandle asTypeUncached(MethodType newType) {
+            return asTypeCache = target.asType(newType);
+        }
+
+        public static MethodHandle make(MethodHandle target) {
+            LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(
+                    target, -1, DelegatingMethodHandle.class, "reinvoker.dontInline",
+                /*forceInline=*/false, DelegatingMethodHandle.NF_getTarget, null);
+            return new NonInlinedReinvoker(target, lform);
+        }
+    }
+}
diff --git a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java
index e74fc43..993cbba 100644
--- a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java
+++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java
@@ -27,25 +27,26 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ./common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ * @library common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_SEC_MAN
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      ALL_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_JVMCI_ACCESS_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -XX:-EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_JVMCI
diff --git a/hotspot/test/compiler/jvmci/code/DataPatchTest.java b/hotspot/test/compiler/jvmci/code/DataPatchTest.java
index af438a3..60e4691 100644
--- a/hotspot/test/compiler/jvmci/code/DataPatchTest.java
+++ b/hotspot/test/compiler/jvmci/code/DataPatchTest.java
@@ -24,7 +24,14 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
- * @compile CodeInstallationTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @library /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.code.site
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.vm.ci/jdk.vm.ci.amd64
+ *          jdk.vm.ci/jdk.vm.ci.sparc
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.DataPatchTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/code/SimpleCodeInstallationTest.java b/hotspot/test/compiler/jvmci/code/SimpleCodeInstallationTest.java
index 60def01..6c1377c 100644
--- a/hotspot/test/compiler/jvmci/code/SimpleCodeInstallationTest.java
+++ b/hotspot/test/compiler/jvmci/code/SimpleCodeInstallationTest.java
@@ -24,7 +24,14 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
- * @compile CodeInstallationTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @library /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.code.site
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.vm.ci/jdk.vm.ci.amd64
+ *          jdk.vm.ci/jdk.vm.ci.sparc
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.SimpleCodeInstallationTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/code/SimpleDebugInfoTest.java b/hotspot/test/compiler/jvmci/code/SimpleDebugInfoTest.java
index 041a184..b27802c 100644
--- a/hotspot/test/compiler/jvmci/code/SimpleDebugInfoTest.java
+++ b/hotspot/test/compiler/jvmci/code/SimpleDebugInfoTest.java
@@ -24,7 +24,14 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @library /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.code.site
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.vm.ci/jdk.vm.ci.amd64
+ *          jdk.vm.ci/jdk.vm.ci.sparc
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.SimpleDebugInfoTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java b/hotspot/test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java
index 2f1061a..c06c507 100644
--- a/hotspot/test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java
+++ b/hotspot/test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java
@@ -24,7 +24,14 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @library /
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.code.site
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.vm.ci/jdk.vm.ci.amd64
+ *          jdk.vm.ci/jdk.vm.ci.sparc
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.VirtualObjectDebugInfoTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java
index 67a1aef..6c33016 100644
--- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java
+++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java
@@ -24,6 +24,7 @@
 package compiler.jvmci.common;
 
 import java.io.IOException;
+import java.lang.reflect.Module;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Constructor;
@@ -88,20 +89,24 @@
     }
     public static Map<Integer, Integer> getBciToLineNumber(Executable method) {
         Map<Integer, Integer> lineNumbers = new TreeMap<>();
+        Class<?> aClass = method.getDeclaringClass();
+        ClassReader cr;
         try {
-            ClassReader cr = new ClassReader(method.getDeclaringClass()
-                    .getName());
-            ClassNode cn = new ClassNode();
-            cr.accept(cn, ClassReader.EXPAND_FRAMES);
-
-            Map<Label, Integer> labels = new HashMap<>();
-            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-            ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method);
-            cr.accept(cv, ClassReader.EXPAND_FRAMES);
-            labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v));
+            Module aModule = aClass.getModule();
+            String name = aClass.getName();
+            cr = new ClassReader(aModule.getResourceAsStream(
+                    name.replace('.', '/') + ".class"));
         } catch (IOException e) {
-            throw new Error("TEST BUG " + e, e);
+                        throw new Error("TEST BUG: can read " + aClass.getName() + " : " + e, e);
         }
+        ClassNode cn = new ClassNode();
+        cr.accept(cn, ClassReader.EXPAND_FRAMES);
+
+        Map<Label, Integer> labels = new HashMap<>();
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+        ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method);
+        cr.accept(cv, ClassReader.EXPAND_FRAMES);
+        labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v));
         boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers())
                 || Modifier.isNative(method.getModifiers());
         if (lineNumbers.isEmpty() && !isEmptyMethod) {
diff --git a/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
similarity index 100%
rename from hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java
rename to hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
diff --git a/hotspot/test/compiler/jvmci/events/MetaAccessWrapper.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/MetaAccessWrapper.java
similarity index 100%
rename from hotspot/test/compiler/jvmci/events/MetaAccessWrapper.java
rename to hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/MetaAccessWrapper.java
diff --git a/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java
similarity index 100%
rename from hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java
rename to hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java
index 63c009c..3902acf 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java
@@ -26,15 +26,21 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.AllocateCompileIdTest
  * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      -XX:-BackgroundCompilation
- *      compiler.jvmci.compilerToVM.AllocateCompileIdTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:-BackgroundCompilation
+ *                   compiler.jvmci.compilerToVM.AllocateCompileIdTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java
index 64dca91..b24d25c 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java
@@ -27,14 +27,20 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.CanInlineMethodTest
  * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.CanInlineMethodTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.CanInlineMethodTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java b/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java
index be1d594..81b7bd4 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CollectCountersTest.java
@@ -26,20 +26,20 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib/
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.CollectCountersTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI -Xbootclasspath/a:.
- *     -XX:JVMCICounterSize=0
- *     -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=0
- *     compiler.jvmci.compilerToVM.CollectCountersTest
+ *                   -XX:+EnableJVMCI
+ *                   -XX:JVMCICounterSize=0
+ *                   -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=0
+ *                   compiler.jvmci.compilerToVM.CollectCountersTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI -Xbootclasspath/a:.
- *     -XX:JVMCICounterSize=11
- *     -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=11
- *     compiler.jvmci.compilerToVM.CollectCountersTest
+ *                   -XX:+EnableJVMCI
+ *                   -XX:JVMCICounterSize=11
+ *                   -Dcompiler.jvmci.compilerToVM.CollectCountersTest.expected=11
+ *                   compiler.jvmci.compilerToVM.CollectCountersTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java
index d6c22fc..fe25187 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DebugOutputTest.java
@@ -26,12 +26,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run driver compiler.jvmci.compilerToVM.DebugOutputTest
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.DebugOutputTest
+ * @run main/othervm compiler.jvmci.compilerToVM.DebugOutputTest
  */
 
+ // as soon as CODETOOLS-7901589 fixed, '@run main/othervm' should be replaced w/ '@run driver'
+
 package compiler.jvmci.compilerToVM;
 
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
@@ -50,15 +53,13 @@
             System.out.println(testCase);
             OutputAnalyzer oa;
             try {
-                ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-                        /* use test options = */ true,
+                oa = ProcessTools.executeTestJvmAllArgs(
                         "-XX:+UnlockExperimentalVMOptions",
                         "-XX:+EnableJVMCI",
                         "-Xbootclasspath/a:.",
                         DebugOutputTest.Worker.class.getName(),
                         testCase.name());
-               oa = ProcessTools.executeProcess(pb);
-               } catch (Exception e) {
+               } catch (Throwable e) {
                 e.printStackTrace();
                 throw new Error("Problems running child process", e);
             }
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java
index 60a734d..bd39a56e 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java
@@ -27,16 +27,21 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
  * @ignore 8139700
- * @compile ../common/CompilerToVMHelper.java
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.DisassembleCodeBlobTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.DisassembleCodeBlobTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.DisassembleCodeBlobTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java
index a87cab4..747a9cf 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java
@@ -27,14 +27,20 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.DoNotInlineOrCompileTest
  * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.DoNotInlineOrCompileTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.DoNotInlineOrCompileTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java
index 839b509..fb89c4e 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java
@@ -23,16 +23,21 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
+ * @library ../common/patches
  * @ignore 8139383
- * @compile ../common/CompilerToVMHelper.java
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
  * @build sun.hotspot.WhiteBox
- *        compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.ExecuteInstalledCodeTest
  */
 
 public class ExecuteInstalledCodeTest {
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
index 2b39757..0cca017 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
@@ -26,12 +26,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java
index 586160f..472bc37 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java
@@ -27,11 +27,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetBytecodeTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.GetBytecodeTest
+ *                   compiler.jvmci.compilerToVM.GetBytecodeTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java
index 6c731a4..1b0eacd 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java
@@ -26,11 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.GetClassInitializerTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetClassInitializerTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetClassInitializerTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
index 4c34796..3e14a68 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
@@ -27,16 +27,19 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java ../common/PublicMetaspaceWrapperObject.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
+ * @build compiler.jvmci.compilerToVM.GetConstantPoolTest
  * @build sun.hotspot.WhiteBox
- *        compiler.jvmci.compilerToVM.GetConstantPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- *                              jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
- *                   -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetConstantPoolTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetConstantPoolTest
  */
 package compiler.jvmci.compilerToVM;
 
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java
index e8630c1..63f4433 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java
@@ -27,11 +27,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetExceptionTableTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.GetExceptionTableTest
+ *                   compiler.jvmci.compilerToVM.GetExceptionTableTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java
index fd88f772..1b03ef2 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java
@@ -26,12 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib/
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.GetImplementorTest
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetImplementorTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetImplementorTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java
index 8ca2f53..99fcd9f 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java
@@ -27,11 +27,16 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetLineNumberTableTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.GetLineNumberTableTest
+ *                   compiler.jvmci.compilerToVM.GetLineNumberTableTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java
index d967e60..958b2e4 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java
@@ -27,15 +27,19 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
  * @clean compiler.jvmci.compilerToVM.*
  * @compile -g DummyInterface.java
  * @compile -g DummyAbstractClass.java
  * @compile -g DummyClass.java
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetLocalVariableTableTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.GetLocalVariableTableTest
+ *                   compiler.jvmci.compilerToVM.GetLocalVariableTableTest
  * @clean compiler.jvmci.compilerToVM.*
  */
 
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java
index b803f55..c180d41 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java
@@ -26,12 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib/
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetMaxCallTargetOffsetTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java
index 830ff7b..44fbb4c 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java
@@ -26,11 +26,16 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *      -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetNextStackFrameTest
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetNextStackFrameTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetNextStackFrameTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java
index 3f578e9..87afff2 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java
@@ -27,11 +27,16 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetNextStackFrameTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.GetResolvedJavaMethodAtSlotTest
+ *                   compiler.jvmci.compilerToVM.GetResolvedJavaMethodAtSlotTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
index 5a98e88..4735af3 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
@@ -26,17 +26,18 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
- *          ../common/PublicMetaspaceWrapperObject.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ *        jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @build compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
  * @run main ClassFileInstaller
  *      sun.hotspot.WhiteBox
  *      sun.hotspot.WhiteBox$WhiteBoxPermission
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- *      jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *      -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *      compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java
index 50b1a60a..0ddc246 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java
@@ -26,22 +26,26 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
- *          ../common/PublicMetaspaceWrapperObject.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ *        jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @build compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller
  *      sun.hotspot.WhiteBox
  *      sun.hotspot.WhiteBox$WhiteBoxPermission
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- *      jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *      -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *      -XX:+UseCompressedOops
- *      compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *      -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *      -XX:-UseCompressedOops
- *      compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UseCompressedOops
+ *                   compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:-UseCompressedOops
+ *                   compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java
index 5554bc3..a6feb93 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java
@@ -27,10 +27,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.GetStackTraceElementTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:. compiler.jvmci.compilerToVM.GetStackTraceElementTest
+ *                   compiler.jvmci.compilerToVM.GetStackTraceElementTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
index e550282..9e1f829 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
@@ -26,17 +26,16 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.GetSymbolTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- *                              compiler.jvmci.common.testcases.SingleImplementer
- *                              compiler.jvmci.common.testcases.SingleImplementerInterface
- *                              compiler.jvmci.compilerToVM.GetSymbolTest
- *                              compiler.jvmci.common.CTVMUtilities
- *                              jdk.test.lib.Utils
- *                              jdk.test.lib.Asserts
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     -Xbootclasspath/a:. compiler.jvmci.compilerToVM.GetSymbolTest
+ *                  compiler.jvmci.compilerToVM.GetSymbolTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java
index f97a447..49fd321 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java
@@ -26,12 +26,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java
index cf839d7..e45940e 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java
@@ -27,15 +27,21 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.HasCompiledCodeForOSRTest
  * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      -XX:-BackgroundCompilation
- *      compiler.jvmci.compilerToVM.HasCompiledCodeForOSRTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:-BackgroundCompilation
+ *                   compiler.jvmci.compilerToVM.HasCompiledCodeForOSRTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java
index ce6f1a8..066e784 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java
@@ -26,11 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                  compiler.jvmci.compilerToVM.HasFinalizableSubclassTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java
index 2a2268a..3de8ec5 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java
@@ -26,13 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.InitializeConfigurationTest
- * @run main ClassFileInstaller
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:.
- *     -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     compiler.jvmci.compilerToVM.InitializeConfigurationTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.InitializeConfigurationTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java
index a8eac1d..b7a0cfd 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java
@@ -27,16 +27,22 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.runtime
  * @ignore 8139700
- * @compile ../common/CompilerToVMHelper.java
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
  * @build sun.hotspot.WhiteBox
- *        compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.InvalidateInstalledCodeTest
  */
 
 package compiler.jvmci.compilerToVM;
@@ -86,6 +92,7 @@
         CompilationResult compResult = new CompilationResult(name);
         // to pass sanity check of default -1
         compResult.setTotalFrameSize(0);
+        compResult.close();
         InstalledCode installedCode = CACHE_PROVIDER.installCode(
                 compRequest, compResult,
                 new InstalledCode(name), /* speculationLog = */ null,
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java
index a800426..f6ebb83 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java
@@ -26,14 +26,17 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
- * @build sun.hotspot.WhiteBox IsMatureTest
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.IsMatureTest
+ * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *     -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     compiler.jvmci.compilerToVM.IsMatureTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.IsMatureTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java
index 09893c0..21be817 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java
@@ -28,15 +28,21 @@
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @summary Testing compiler.jvmci.CompilerToVM.lookupKlassInPool method
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupKlassInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
- *                   -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupKlassInPoolTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   compiler.jvmci.compilerToVM.LookupKlassInPoolTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java
index e1dbe9f..b17763b 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.LookupKlassRefIndexInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java
index a1e71bb..1c23c74 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupMethodInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.LookupMethodInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java
index 0eea14a..16add70 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.LookupNameAndTypeRefIndexInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java
index 09db06c..9dc2552 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupNameInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.LookupNameInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java
index 00f5583..adcf6cb 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.LookupSignatureInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.LookupSignatureInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java
index 2f6efe1..269c5a7 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java
@@ -26,12 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.LookupTypeTest
- * @run main ClassFileInstaller
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.LookupTypeTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.LookupTypeTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java
index 326f24e..e281749 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java
@@ -26,22 +26,34 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
  * @ignore 8139703
- * @compile ../common/CompilerToVMHelper.java
- * @build sun.hotspot.WhiteBox MaterializeVirtualObjectTest
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
+ * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *     -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     -XX:CompileCommand=exclude,*::check -XX:+DoEscapeAnalysis -Xbatch
- *     -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false
- *     compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *     -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     -XX:CompileCommand=exclude,*::check -XX:+DoEscapeAnalysis -Xbatch
- *     -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true
- *     compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:CompileCommand=exclude,*::check
+ *                   -XX:+DoEscapeAnalysis
+ *                   -Xbatch
+ *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false
+ *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:CompileCommand=exclude,*::check
+ *                   -XX:+DoEscapeAnalysis
+ *                   -Xbatch
+ *                   -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true
+ *                   compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java
index 3d00dae..b63fa7a 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java
@@ -27,11 +27,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
- * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.MethodIsIgnoredBySecurityStackWalkTest
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.MethodIsIgnoredBySecurityStackWalkTest
+ *                   compiler.jvmci.compilerToVM.MethodIsIgnoredBySecurityStackWalkTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java
index 5ff5913..4ec17c2 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java
@@ -26,22 +26,24 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib/
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller
  *     sun.hotspot.WhiteBox
  *     sun.hotspot.WhiteBox$WhiteBoxPermission
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:.
- *     -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *     -XX:-UseCompressedOops
- *     compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:-UseCompressedOops
+ *                   compiler.jvmci.compilerToVM.ReadUncompressedOopTest
  * @run main/othervm -Xbootclasspath/a:.
- *     -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *     -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- *     -XX:+UseCompressedOops
- *     compiler.jvmci.compilerToVM.ReadUncompressedOopTest
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UseCompressedOops
+ *                   compiler.jvmci.compilerToVM.ReadUncompressedOopTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java
index bc3e781..1e8cb12 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java
@@ -27,16 +27,23 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
+ * @build compiler.jvmci.compilerToVM.ReprofileTest
  * @run main ClassFileInstaller
  *      sun.hotspot.WhiteBox
  *      sun.hotspot.WhiteBox$WhiteBoxPermission
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      -Xmixed
- *      compiler.jvmci.compilerToVM.ReprofileTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -Xmixed
+ *                   compiler.jvmci.compilerToVM.ReprofileTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java
index 2c37309..285f0ff 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java
@@ -27,14 +27,19 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *                   compiler.jvmci.compilerToVM.ResolveConstantInPoolTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
index 9e99842..2d7145d 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.ResolveFieldInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java
index ba43e6b..ff08b7e 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java
@@ -26,12 +26,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.ResolveMethodTest
- * @run main ClassFileInstaller
- *      jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
- *     -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveMethodTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.ResolveMethodTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java
index 6f0af4c..1e0f269 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java
@@ -27,12 +27,17 @@
  * @bug 8138708
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *                   compiler.jvmci.compilerToVM.ResolvePossiblyCachedConstantInPoolTest
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java
index 1e5fe57..cad8ccd 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java
@@ -28,15 +28,20 @@
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @summary Testing compiler.jvmci.CompilerToVM.resolveTypeInPool method
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
- *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
- *                   -XX:+EnableJVMCI compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   compiler.jvmci.compilerToVM.ResolveTypeInPoolTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java
index 86f9cef..69ceeff 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java
@@ -26,22 +26,20 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary /test/lib/
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
- * @run main ClassFileInstaller
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm
- *     -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:.
- *     -XX:+UnlockDiagnosticVMOptions
- *     -XX:+DebugNonSafepoints
- *     -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=true
- *     compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
- * @run main/othervm
- *     -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:.
- *     -XX:+UnlockDiagnosticVMOptions
- *     -XX:-DebugNonSafepoints
- *     -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=false
- *     compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+DebugNonSafepoints
+ *                   -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=true
+ *                   compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:-DebugNonSafepoints
+ *                   -Dcompiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest.expected=false
+ *                   compiler.jvmci.compilerToVM.ShouldDebugNonSafepointsTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java
index a034166..615b585 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java
@@ -27,14 +27,20 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library /testlibrary /test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @build compiler.jvmci.compilerToVM.ShouldInlineMethodTest
  * @build sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- *                              jdk.vm.ci.hotspot.CompilerToVMHelper
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- *      compiler.jvmci.compilerToVM.ShouldInlineMethodTest
+ * @run main/othervm -Xbootclasspath/a:.
+ *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ *                   compiler.jvmci.compilerToVM.ShouldInlineMethodTest
  */
 
 package compiler.jvmci.compilerToVM;
diff --git a/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.java b/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.java
index 810404b..c8bfbff 100644
--- a/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.java
+++ b/hotspot/test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.java
@@ -26,7 +26,12 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary
- * @compile ./MetaAccessWrapper.java
+ * @library ../common/patches
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.MetaAccessWrapper
  * @build compiler.jvmci.common.JVMCIHelpers
  *     compiler.jvmci.events.JvmciCreateMetaAccessContextTest
  * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
@@ -37,7 +42,6 @@
  *     compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
  *     compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
  *     compiler.jvmci.events.JvmciCreateMetaAccessContextTest
- *     jdk.vm.ci.hotspot.MetaAccessWrapper
  *     jdk.test.lib.Asserts
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *     -Xbootclasspath/a:.
diff --git a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java
index 75c808e..5e6f972 100644
--- a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java
+++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java
@@ -26,7 +26,15 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
  * @library / /testlibrary
- * @compile ../common/CompilerToVMHelper.java
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          jdk.vm.ci/jdk.vm.ci.hotspot
+ *          jdk.vm.ci/jdk.vm.ci.code
+ *          jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @ignore 8144964
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  * @build compiler.jvmci.common.JVMCIHelpers
  *     compiler.jvmci.events.JvmciNotifyInstallEventTest
  * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
@@ -38,7 +46,6 @@
  *     compiler.jvmci.events.JvmciNotifyInstallEventTest
  *     compiler.jvmci.common.CTVMUtilities
  *     compiler.jvmci.common.testcases.SimpleClass
- *     jdk.vm.ci.hotspot.CompilerToVMHelper
  *     jdk.test.lib.Asserts
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *     -Djvmci.compiler=EmptyCompiler -Xbootclasspath/a:. -Xmixed
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java
index 5be56d0..761db0e 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java
@@ -24,10 +24,13 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile ConstantTest.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.ConstantTest
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ConstantTest
  */
-
+// * @compile ConstantTest.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
 package jdk.vm.ci.runtime.test;
 
 import jdk.vm.ci.meta.JavaConstant;
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 1139241..038efdc 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
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile RedefineClassTest.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.RedefineClassTest
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.RedefineClassTest
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java
index dbde990..fe31f59 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestConstantReflectionProvider.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestConstantReflectionProvider
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestConstantReflectionProvider
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java
index d4c3a58..46f4e80 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestJavaField.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestJavaField
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaField
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java
index 50e7b2e..460abd9 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java NameAndSignature.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestJavaMethod
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaMethod
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java
index 311c96a..72506cf 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestJavaType.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestJavaType
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestJavaType
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java
index 9c19740..10b2e70 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestMetaAccessProvider.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestMetaAccessProvider
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestMetaAccessProvider
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java
index fb960c0..71e9f18 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestResolvedJavaField.java FieldUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestResolvedJavaField
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaField
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java
index 13dd099..c60a7d4 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java
@@ -24,7 +24,10 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestResolvedJavaMethod.java MethodUniverse.java TypeUniverse.java TestMetaAccessProvider.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ * @build jdk.vm.ci.runtime.test.TestResolvedJavaMethod
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaMethod
  */
 
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java
index 8c86980..2011bc0 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java
@@ -24,7 +24,11 @@
 /**
  * @test
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
- * @compile TestResolvedJavaType.java TypeUniverse.java TestMetaAccessProvider.java NameAndSignature.java
+ * @library ../../../../../
+ * @modules jdk.vm.ci/jdk.vm.ci.meta
+ *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.vm.ci/jdk.vm.ci.common
+ * @build jdk.vm.ci.runtime.test.TestResolvedJavaType
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.TestResolvedJavaType
  */
 
diff --git a/hotspot/test/compiler/stable/StableConfiguration.java b/hotspot/test/compiler/stable/StableConfiguration.java
index be69081..db7e9a0 100644
--- a/hotspot/test/compiler/stable/StableConfiguration.java
+++ b/hotspot/test/compiler/stable/StableConfiguration.java
@@ -22,16 +22,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package java.lang.invoke;
+
+package compiler.stable;
+
+import sun.hotspot.WhiteBox;
 
 import java.lang.reflect.Method;
-import java.util.Properties;
-import sun.hotspot.WhiteBox;
 
 public class StableConfiguration {
     static final WhiteBox WB = WhiteBox.getWhiteBox();
-    static final boolean isStableEnabled;
-    static final boolean isServerWithStable;
+    public static final boolean isStableEnabled;
+    public static final boolean isServerWithStable;
 
     static {
         Boolean value = WB.getBooleanVMFlag("FoldStableValues");
@@ -60,8 +61,6 @@
     static void get1() {
     }
 
-
-
     // ::get() is among immediately compiled methods.
     static boolean get() {
         try {
@@ -80,5 +79,4 @@
             throw new Error(e);
         }
     }
-
 }
diff --git a/hotspot/test/compiler/stable/TestStableBoolean.java b/hotspot/test/compiler/stable/TestStableBoolean.java
index 168ddf4..ed8d18b 100644
--- a/hotspot/test/compiler/stable/TestStableBoolean.java
+++ b/hotspot/test/compiler/stable/TestStableBoolean.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableBoolean
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableBoolean StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableBoolean
- *           java/lang/invoke/TestStableBoolean$BooleanStable
- *           java/lang/invoke/TestStableBoolean$StaticBooleanStable
- *           java/lang/invoke/TestStableBoolean$VolatileBooleanStable
- *           java/lang/invoke/TestStableBoolean$BooleanArrayDim1
- *           java/lang/invoke/TestStableBoolean$BooleanArrayDim2
- *           java/lang/invoke/TestStableBoolean$BooleanArrayDim3
- *           java/lang/invoke/TestStableBoolean$BooleanArrayDim4
- *           java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableBoolean$NestedStableField
- *           java/lang/invoke/TestStableBoolean$NestedStableField$A
- *           java/lang/invoke/TestStableBoolean$NestedStableField1
- *           java/lang/invoke/TestStableBoolean$NestedStableField1$A
- *           java/lang/invoke/TestStableBoolean$NestedStableField2
- *           java/lang/invoke/TestStableBoolean$NestedStableField2$A
- *           java/lang/invoke/TestStableBoolean$NestedStableField3
- *           java/lang/invoke/TestStableBoolean$NestedStableField3$A
- *           java/lang/invoke/TestStableBoolean$DefaultValue
- *           java/lang/invoke/TestStableBoolean$DefaultStaticValue
- *           java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableBoolean
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableBoolean
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableBoolean
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableBoolean
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:-FoldStableValues
+ *                         compiler.stable.TestStableBoolean
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableBoolean
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableBoolean
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:+TieredCompilation -XX:TieredStopAtLevel=1
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableBoolean
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:+TieredCompilation -XX:TieredStopAtLevel=1
+ *                         -XX:-FoldStableValues
+ *                         compiler.stable.TestStableBoolean
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableBoolean {
@@ -122,12 +95,13 @@
     /* ==================================================== */
 
     static class DefaultValue {
-        public @Stable boolean v;
+        public @Stable
+        boolean v;
 
         public static final DefaultValue c = new DefaultValue();
         public static boolean get() { return c.v; }
         public static void test() throws Exception {
-                        boolean val1 = get();
+            boolean val1 = get();
             c.v = true; boolean val2 = get();
             assertEquals(val1, false);
             assertEquals(val2, true);
@@ -157,7 +131,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static boolean get() { return c.v; }
         public static void test() throws Exception {
-                        boolean val1 = get();
+            boolean val1 = get();
             c.v = true; boolean val2 = get();
             assertEquals(val1, false);
             assertEquals(val2, true);
@@ -207,14 +181,14 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1]; c.v[0] = true;  boolean val1 = get();
-                                      c.v[0] = false; boolean val2 = get();
+                c.v[0] = false; boolean val2 = get();
                 assertEquals(val1, true);
                 assertEquals(val2, (isServerWithStable ? true : false));
             }
 
             {
                 c.v = new boolean[20]; c.v[10] = true;  boolean val1 = get1();
-                                       c.v[10] = false; boolean val2 = get1();
+                c.v[10] = false; boolean val2 = get1();
                 assertEquals(val1, true);
                 assertEquals(val2, (isServerWithStable ? true : false));
             }
@@ -239,7 +213,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1][1]; c.v[0][0] = true;  boolean val1 = get();
-                                         c.v[0][0] = false; boolean val2 = get();
+                c.v[0][0] = false; boolean val2 = get();
                 assertEquals(val1, true);
                 assertEquals(val2, (isServerWithStable ? true : false));
 
@@ -277,7 +251,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1][1][1]; c.v[0][0][0] = true;  boolean val1 = get();
-                                            c.v[0][0][0] = false; boolean val2 = get();
+                c.v[0][0][0] = false; boolean val2 = get();
                 assertEquals(val1, true);
                 assertEquals(val2, (isServerWithStable ? true : false));
 
@@ -325,7 +299,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = true;  boolean val1 = get();
-                                               c.v[0][0][0][0] = false; boolean val2 = get();
+                c.v[0][0][0][0] = false; boolean val2 = get();
                 assertEquals(val1, true);
                 assertEquals(val2, (isServerWithStable ? true : false));
 
@@ -383,7 +357,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1]; ((boolean[])c.v)[0] = true;  boolean val1 = get();
-                                      ((boolean[])c.v)[0] = false; boolean val2 = get();
+                ((boolean[])c.v)[0] = false; boolean val2 = get();
 
                 assertEquals(val1, true);
                 assertEquals(val2, false);
@@ -410,7 +384,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1][1]; ((boolean[][])c.v)[0][0] = true;  boolean val1 = get();
-                                         ((boolean[][])c.v)[0][0] = false; boolean val2 = get();
+                ((boolean[][])c.v)[0][0] = false; boolean val2 = get();
 
                 assertEquals(val1, true);
                 assertEquals(val2, false);
@@ -418,7 +392,7 @@
 
             {
                 c.v = new boolean[1][1]; c.v[0] = new boolean[0]; boolean[] val1 = get1();
-                                         c.v[0] = new boolean[0]; boolean[] val2 = get1();
+                c.v[0] = new boolean[0]; boolean[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -446,7 +420,7 @@
         public static void test() throws Exception {
             {
                 c.v = new boolean[1][1][1]; ((boolean[][][])c.v)[0][0][0] = true;  boolean val1 = get();
-                                            ((boolean[][][])c.v)[0][0][0] = false; boolean val2 = get();
+                ((boolean[][][])c.v)[0][0][0] = false; boolean val2 = get();
 
                 assertEquals(val1, true);
                 assertEquals(val2, false);
@@ -454,14 +428,14 @@
 
             {
                 c.v = new boolean[1][1][1]; c.v[0][0] = new boolean[0]; boolean[] val1 = get1();
-                                            c.v[0][0] = new boolean[0]; boolean[] val2 = get1();
+                c.v[0][0] = new boolean[0]; boolean[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new boolean[1][1][1]; c.v[0] = new boolean[0][0]; boolean[][] val1 = get2();
-                                            c.v[0] = new boolean[0][0]; boolean[][] val2 = get2();
+                c.v[0] = new boolean[0][0]; boolean[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -491,7 +465,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = true;  A val1 = get();
-                               c.v.a = false; A val2 = get();
+                c.v.a = false; A val2 = get();
 
                 assertEquals(val1.a, false);
                 assertEquals(val2.a, false);
@@ -499,7 +473,7 @@
 
             {
                 c.v = new A(); c.v.a = true;  boolean val1 = get1();
-                               c.v.a = false; boolean val2 = get1();
+                c.v.a = false; boolean val2 = get1();
                 c.v = new A(); c.v.a = false; boolean val3 = get1();
 
                 assertEquals(val1, true);
@@ -525,8 +499,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A(); c.v.next.next  = c.v;
-                               c.v.a = true;  c.v.next.a = true;  A val1 = get();
-                               c.v.a = false; c.v.next.a = false; A val2 = get();
+                c.v.a = true;  c.v.next.a = true;  A val1 = get();
+                c.v.a = false; c.v.next.a = false; A val2 = get();
 
                 assertEquals(val1.a, false);
                 assertEquals(val2.a, false);
@@ -534,10 +508,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = true;  boolean val1 = get1();
-                               c.v.a = false; boolean val2 = get1();
+                c.v.a = true;  boolean val1 = get1();
+                c.v.a = false; boolean val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = false; boolean val3 = get1();
+                c.v.a = false; boolean val3 = get1();
 
                 assertEquals(val1, true);
                 assertEquals(val2, (isStableEnabled ? true : false));
@@ -563,8 +537,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = true;  boolean val1 = get(); boolean val2 = get1();
-                               c.v.a = false; boolean val3 = get(); boolean val4 = get1();
+                c.v.a = true;  boolean val1 = get(); boolean val2 = get1();
+                c.v.a = false; boolean val3 = get(); boolean val4 = get1();
 
                 assertEquals(val1, true);
                 assertEquals(val3, (isStableEnabled ? true : false));
@@ -594,8 +568,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = true;  boolean val1 = get(); boolean val2 = get1();
-                               elem.a = false; boolean val3 = get(); boolean val4 = get1();
+                elem.a = true;  boolean val1 = get(); boolean val2 = get1();
+                elem.a = false; boolean val3 = get(); boolean val4 = get1();
 
                 assertEquals(val1, true);
                 assertEquals(val3, (isServerWithStable ? true : false));
@@ -632,4 +606,5 @@
             }
         }
     }
+
 }
diff --git a/hotspot/test/compiler/stable/TestStableByte.java b/hotspot/test/compiler/stable/TestStableByte.java
index 694205e..14ce6e4 100644
--- a/hotspot/test/compiler/stable/TestStableByte.java
+++ b/hotspot/test/compiler/stable/TestStableByte.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableByte
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableByte StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableByte
- *           java/lang/invoke/TestStableByte$ByteStable
- *           java/lang/invoke/TestStableByte$StaticByteStable
- *           java/lang/invoke/TestStableByte$VolatileByteStable
- *           java/lang/invoke/TestStableByte$ByteArrayDim1
- *           java/lang/invoke/TestStableByte$ByteArrayDim2
- *           java/lang/invoke/TestStableByte$ByteArrayDim3
- *           java/lang/invoke/TestStableByte$ByteArrayDim4
- *           java/lang/invoke/TestStableByte$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableByte$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableByte$NestedStableField
- *           java/lang/invoke/TestStableByte$NestedStableField$A
- *           java/lang/invoke/TestStableByte$NestedStableField1
- *           java/lang/invoke/TestStableByte$NestedStableField1$A
- *           java/lang/invoke/TestStableByte$NestedStableField2
- *           java/lang/invoke/TestStableByte$NestedStableField2$A
- *           java/lang/invoke/TestStableByte$NestedStableField3
- *           java/lang/invoke/TestStableByte$NestedStableField3$A
- *           java/lang/invoke/TestStableByte$DefaultValue
- *           java/lang/invoke/TestStableByte$DefaultStaticValue
- *           java/lang/invoke/TestStableByte$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableByte
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableByte
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableByte
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableByte
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableByte
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableByte
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableByte
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableByte
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableByte
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableByte {
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static byte get() { return c.v; }
         public static void test() throws Exception {
-                     byte val1 = get();
+            byte val1 = get();
             c.v = 1; byte val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static byte get() { return c.v; }
         public static void test() throws Exception {
-                     byte val1 = get();
+            byte val1 = get();
             c.v = 1; byte val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1]; c.v[0] = 1; byte val1 = get();
-                                   c.v[0] = 2; byte val2 = get();
+                c.v[0] = 2; byte val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new byte[1]; c.v[0] = 3; byte val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
                 c.v = new byte[20]; c.v[10] = 1; byte val1 = get1();
-                                    c.v[10] = 2; byte val2 = get1();
+                c.v[10] = 2; byte val2 = get1();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new byte[20]; c.v[10] = 3; byte val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get();
-                                      c.v[0][0] = 2; byte val2 = get();
+                c.v[0][0] = 2; byte val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get();
-                                         c.v[0][0][0] = 2; byte val2 = get();
+                c.v[0][0][0] = 2; byte val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get();
-                                            c.v[0][0][0][0] = 2; byte val2 = get();
+                c.v[0][0][0][0] = 2; byte val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
 
                 c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 6));
+                        : 6));
             }
 
             {
@@ -399,7 +372,7 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1]; ((byte[])c.v)[0] = 1; byte val1 = get();
-                                   ((byte[])c.v)[0] = 2; byte val2 = get();
+                ((byte[])c.v)[0] = 2; byte val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -426,7 +399,7 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1][1]; ((byte[][])c.v)[0][0] = 1; byte val1 = get();
-                                      ((byte[][])c.v)[0][0] = 2; byte val2 = get();
+                ((byte[][])c.v)[0][0] = 2; byte val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -434,7 +407,7 @@
 
             {
                 c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1();
-                                     c.v[0] = new byte[0]; byte[] val2 = get1();
+                c.v[0] = new byte[0]; byte[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -462,7 +435,7 @@
         public static void test() throws Exception {
             {
                 c.v = new byte[1][1][1]; ((byte[][][])c.v)[0][0][0] = 1;  byte val1 = get();
-                                         ((byte[][][])c.v)[0][0][0] = 2; byte val2 = get();
+                ((byte[][][])c.v)[0][0][0] = 2; byte val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -470,14 +443,14 @@
 
             {
                 c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1();
-                                         c.v[0][0] = new byte[0]; byte[] val2 = get1();
+                c.v[0][0] = new byte[0]; byte[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2();
-                                         c.v[0] = new byte[0][0]; byte[][] val2 = get2();
+                c.v[0] = new byte[0][0]; byte[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -507,7 +480,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1; A val1 = get();
-                               c.v.a = 2; A val2 = get();
+                c.v.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -515,7 +488,7 @@
 
             {
                 c.v = new A(); c.v.a = 1; byte val1 = get1();
-                               c.v.a = 2; byte val2 = get1();
+                c.v.a = 2; byte val2 = get1();
                 c.v = new A(); c.v.a = 3; byte val3 = get1();
 
                 assertEquals(val1, 1);
@@ -541,8 +514,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1; c.v.next.a = 1; A val1 = get();
-                               c.v.a = 2; c.v.next.a = 2; A val2 = get();
+                c.v.a = 1; c.v.next.a = 1; A val1 = get();
+                c.v.a = 2; c.v.next.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -550,10 +523,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1; byte val1 = get1();
-                               c.v.a = 2; byte val2 = get1();
+                c.v.a = 1; byte val1 = get1();
+                c.v.a = 2; byte val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3; byte val3 = get1();
+                c.v.a = 3; byte val3 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, (isStableEnabled ? 1 : 2));
@@ -579,8 +552,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1; byte val1 = get(); byte val2 = get1();
-                               c.v.a = 2; byte val3 = get(); byte val4 = get1();
+                c.v.a = 1; byte val1 = get(); byte val2 = get1();
+                c.v.a = 2; byte val3 = get(); byte val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isStableEnabled ? 1 : 2));
@@ -610,8 +583,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1; byte val1 = get(); byte val2 = get1();
-                               elem.a = 2; byte val3 = get(); byte val4 = get1();
+                elem.a = 1; byte val1 = get(); byte val2 = get1();
+                elem.a = 2; byte val3 = get(); byte val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isServerWithStable ? 1 : 2));
diff --git a/hotspot/test/compiler/stable/TestStableChar.java b/hotspot/test/compiler/stable/TestStableChar.java
index d92dfb6..ba8e935 100644
--- a/hotspot/test/compiler/stable/TestStableChar.java
+++ b/hotspot/test/compiler/stable/TestStableChar.java
@@ -26,65 +26,38 @@
 /*
  * @test TestStableChar
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableChar StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableChar
- *           java/lang/invoke/TestStableChar$CharStable
- *           java/lang/invoke/TestStableChar$StaticCharStable
- *           java/lang/invoke/TestStableChar$VolatileCharStable
- *           java/lang/invoke/TestStableChar$CharArrayDim1
- *           java/lang/invoke/TestStableChar$CharArrayDim2
- *           java/lang/invoke/TestStableChar$CharArrayDim3
- *           java/lang/invoke/TestStableChar$CharArrayDim4
- *           java/lang/invoke/TestStableChar$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableChar$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableChar$NestedStableField
- *           java/lang/invoke/TestStableChar$NestedStableField$A
- *           java/lang/invoke/TestStableChar$NestedStableField1
- *           java/lang/invoke/TestStableChar$NestedStableField1$A
- *           java/lang/invoke/TestStableChar$NestedStableField2
- *           java/lang/invoke/TestStableChar$NestedStableField2$A
- *           java/lang/invoke/TestStableChar$NestedStableField3
- *           java/lang/invoke/TestStableChar$NestedStableField3$A
- *           java/lang/invoke/TestStableChar$DefaultValue
- *           java/lang/invoke/TestStableChar$DefaultStaticValue
- *           java/lang/invoke/TestStableChar$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableChar
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableChar
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableChar
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableChar
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableChar
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableChar
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableChar
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableChar
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableChar
  */
-package java.lang.invoke;
 
-import jdk.internal.vm.annotation.Stable;
+package compiler.stable;
 
 import java.lang.reflect.InvocationTargetException;
+import jdk.internal.vm.annotation.Stable;
 
 public class TestStableChar {
     static final boolean isStableEnabled    = StableConfiguration.isStableEnabled;
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static char get() { return c.v; }
         public static void test() throws Exception {
-                       char val1 = get();
+            char val1 = get();
             c.v = 'a'; char val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 'a');
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static char get() { return c.v; }
         public static void test() throws Exception {
-                       char val1 = get();
+            char val1 = get();
             c.v = 'a'; char val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 'a');
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1]; c.v[0] = 'a'; char val1 = get();
-                                   c.v[0] = 'b'; char val2 = get();
+                c.v[0] = 'b'; char val2 = get();
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isServerWithStable ? 'a' : 'b'));
 
                 c.v = new char[1]; c.v[0] = 'c'; char val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'c'));
+                        : 'c'));
             }
 
             {
                 c.v = new char[20]; c.v[10] = 'a'; char val1 = get1();
-                                    c.v[10] = 'b'; char val2 = get1();
+                c.v[10] = 'b'; char val2 = get1();
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isServerWithStable ? 'a' : 'b'));
 
                 c.v = new char[20]; c.v[10] = 'c'; char val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'c'));
+                        : 'c'));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get();
-                                      c.v[0][0] = 'b'; char val2 = get();
+                c.v[0][0] = 'b'; char val2 = get();
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isServerWithStable ? 'a' : 'b'));
 
                 c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'c'));
+                        : 'c'));
 
                 c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'd'));
+                        : 'd'));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get();
-                                         c.v[0][0][0] = 'b'; char val2 = get();
+                c.v[0][0][0] = 'b'; char val2 = get();
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isServerWithStable ? 'a' : 'b'));
 
                 c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'c'));
+                        : 'c'));
 
                 c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'd'));
+                        : 'd'));
 
                 c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'e'));
+                        : 'e'));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get();
-                                            c.v[0][0][0][0] = 'b'; char val2 = get();
+                c.v[0][0][0][0] = 'b'; char val2 = get();
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isServerWithStable ? 'a' : 'b'));
 
                 c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'c'));
+                        : 'c'));
 
                 c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'd'));
+                        : 'd'));
 
                 c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'e'));
+                        : 'e'));
 
                 c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 'a' : 'b')
-                                                    : 'f'));
+                        : 'f'));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1]; ((char[])c.v)[0] = 'a'; char val1 = get();
-                                   ((char[])c.v)[0] = 'b'; char val2 = get();
+                ((char[])c.v)[0] = 'b'; char val2 = get();
 
                 assertEquals(val1, 'a');
                 assertEquals(val2, 'b');
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1][1]; ((char[][])c.v)[0][0] = 'a'; char val1 = get();
-                                      ((char[][])c.v)[0][0] = 'b'; char val2 = get();
+                ((char[][])c.v)[0][0] = 'b'; char val2 = get();
 
                 assertEquals(val1, 'a');
                 assertEquals(val2, 'b');
@@ -432,7 +405,7 @@
 
             {
                 c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1();
-                                      c.v[0] = new char[0]; char[] val2 = get1();
+                c.v[0] = new char[0]; char[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new char[1][1][1]; ((char[][][])c.v)[0][0][0] = 'a';  char val1 = get();
-                                         ((char[][][])c.v)[0][0][0] = 'b'; char val2 = get();
+                ((char[][][])c.v)[0][0][0] = 'b'; char val2 = get();
 
                 assertEquals(val1, 'a');
                 assertEquals(val2, 'b');
@@ -468,14 +441,14 @@
 
             {
                 c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1();
-                                         c.v[0][0] = new char[0]; char[] val2 = get1();
+                c.v[0][0] = new char[0]; char[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2();
-                                         c.v[0] = new char[0][0]; char[][] val2 = get2();
+                c.v[0] = new char[0][0]; char[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 'a'; A val1 = get();
-                               c.v.a = 'b'; A val2 = get();
+                c.v.a = 'b'; A val2 = get();
 
                 assertEquals(val1.a, 'b');
                 assertEquals(val2.a, 'b');
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 'a'; char val1 = get1();
-                               c.v.a = 'b'; char val2 = get1();
+                c.v.a = 'b'; char val2 = get1();
                 c.v = new A(); c.v.a = 'c'; char val3 = get1();
 
                 assertEquals(val1, 'a');
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A(); c.v.next.next  = c.v;
-                               c.v.a = 'a'; c.v.next.a = 'a'; A val1 = get();
-                               c.v.a = 'b'; c.v.next.a = 'b'; A val2 = get();
+                c.v.a = 'a'; c.v.next.a = 'a'; A val1 = get();
+                c.v.a = 'b'; c.v.next.a = 'b'; A val2 = get();
 
                 assertEquals(val1.a, 'b');
                 assertEquals(val2.a, 'b');
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 'a'; char val1 = get1();
-                               c.v.a = 'b'; char val2 = get1();
+                c.v.a = 'a'; char val1 = get1();
+                c.v.a = 'b'; char val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 'c'; char val3 = get1();
+                c.v.a = 'c'; char val3 = get1();
 
                 assertEquals(val1, 'a');
                 assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 'a'; char val1 = get(); char val2 = get1();
-                               c.v.a = 'b'; char val3 = get(); char val4 = get1();
+                c.v.a = 'a'; char val1 = get(); char val2 = get1();
+                c.v.a = 'b'; char val3 = get(); char val4 = get1();
 
                 assertEquals(val1, 'a');
                 assertEquals(val3, (isStableEnabled ? 'a' : 'b'));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 'a'; char val1 = get(); char val2 = get1();
-                               elem.a = 'b'; char val3 = get(); char val4 = get1();
+                elem.a = 'a'; char val1 = get(); char val2 = get1();
+                elem.a = 'b'; char val3 = get(); char val4 = get1();
 
                 assertEquals(val1, 'a');
                 assertEquals(val3, (isServerWithStable ? 'a' : 'b'));
diff --git a/hotspot/test/compiler/stable/TestStableDouble.java b/hotspot/test/compiler/stable/TestStableDouble.java
index 5e55a0f..c5ef689 100644
--- a/hotspot/test/compiler/stable/TestStableDouble.java
+++ b/hotspot/test/compiler/stable/TestStableDouble.java
@@ -26,65 +26,38 @@
 /*
  * @test TestStableDouble
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableDouble StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableDouble
- *           java/lang/invoke/TestStableDouble$DoubleStable
- *           java/lang/invoke/TestStableDouble$StaticDoubleStable
- *           java/lang/invoke/TestStableDouble$VolatileDoubleStable
- *           java/lang/invoke/TestStableDouble$DoubleArrayDim1
- *           java/lang/invoke/TestStableDouble$DoubleArrayDim2
- *           java/lang/invoke/TestStableDouble$DoubleArrayDim3
- *           java/lang/invoke/TestStableDouble$DoubleArrayDim4
- *           java/lang/invoke/TestStableDouble$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableDouble$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableDouble$NestedStableField
- *           java/lang/invoke/TestStableDouble$NestedStableField$A
- *           java/lang/invoke/TestStableDouble$NestedStableField1
- *           java/lang/invoke/TestStableDouble$NestedStableField1$A
- *           java/lang/invoke/TestStableDouble$NestedStableField2
- *           java/lang/invoke/TestStableDouble$NestedStableField2$A
- *           java/lang/invoke/TestStableDouble$NestedStableField3
- *           java/lang/invoke/TestStableDouble$NestedStableField3$A
- *           java/lang/invoke/TestStableDouble$DefaultValue
- *           java/lang/invoke/TestStableDouble$DefaultStaticValue
- *           java/lang/invoke/TestStableDouble$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableDouble
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableDouble
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableDouble
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableDouble
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableDouble
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableDouble
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableDouble
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableDouble
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableDouble
  */
-package java.lang.invoke;
 
-import jdk.internal.vm.annotation.Stable;
+package compiler.stable;
 
 import java.lang.reflect.InvocationTargetException;
+import jdk.internal.vm.annotation.Stable;
 
 public class TestStableDouble {
     static final boolean isStableEnabled    = StableConfiguration.isStableEnabled;
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static double get() { return c.v; }
         public static void test() throws Exception {
-                       double val1 = get();
+            double val1 = get();
             c.v = 1.0; double val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1.0);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static double get() { return c.v; }
         public static void test() throws Exception {
-                       double val1 = get();
+            double val1 = get();
             c.v = 1.0; double val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1.0);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1]; c.v[0] = 1.0; double val1 = get();
-                                     c.v[0] = 2.0; double val2 = get();
+                c.v[0] = 2.0; double val2 = get();
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isServerWithStable ? 1.0 : 2.0));
 
                 c.v = new double[1]; c.v[0] = 3.0; double val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 3.0));
+                        : 3.0));
             }
 
             {
                 c.v = new double[20]; c.v[10] = 1.0; double val1 = get1();
-                                      c.v[10] = 2.0; double val2 = get1();
+                c.v[10] = 2.0; double val2 = get1();
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isServerWithStable ? 1.0 : 2.0));
 
                 c.v = new double[20]; c.v[10] = 3.0; double val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 3.0));
+                        : 3.0));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1][1]; c.v[0][0] = 1.0; double val1 = get();
-                                        c.v[0][0] = 2.0; double val2 = get();
+                c.v[0][0] = 2.0; double val2 = get();
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isServerWithStable ? 1.0 : 2.0));
 
                 c.v = new double[1][1]; c.v[0][0] = 3.0; double val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 3.0));
+                        : 3.0));
 
                 c.v[0] = new double[1]; c.v[0][0] = 4.0; double val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 4.0));
+                        : 4.0));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1][1][1]; c.v[0][0][0] = 1.0; double val1 = get();
-                                           c.v[0][0][0] = 2.0; double val2 = get();
+                c.v[0][0][0] = 2.0; double val2 = get();
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isServerWithStable ? 1.0 : 2.0));
 
                 c.v = new double[1][1][1]; c.v[0][0][0] = 3.0; double val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 3.0));
+                        : 3.0));
 
                 c.v[0] = new double[1][1]; c.v[0][0][0] = 4.0; double val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 4.0));
+                        : 4.0));
 
                 c.v[0][0] = new double[1]; c.v[0][0][0] = 5.0; double val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 5.0));
+                        : 5.0));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 1.0; double val1 = get();
-                                              c.v[0][0][0][0] = 2.0; double val2 = get();
+                c.v[0][0][0][0] = 2.0; double val2 = get();
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isServerWithStable ? 1.0 : 2.0));
 
                 c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 3.0; double val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 3.0));
+                        : 3.0));
 
                 c.v[0] = new double[1][1][1]; c.v[0][0][0][0] = 4.0; double val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 4.0));
+                        : 4.0));
 
                 c.v[0][0] = new double[1][1]; c.v[0][0][0][0] = 5.0; double val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 5.0));
+                        : 5.0));
 
                 c.v[0][0][0] = new double[1]; c.v[0][0][0][0] = 6.0; double val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0)
-                                                    : 6.0));
+                        : 6.0));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1]; ((double[])c.v)[0] = 1.0; double val1 = get();
-                                     ((double[])c.v)[0] = 2.0; double val2 = get();
+                ((double[])c.v)[0] = 2.0; double val2 = get();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val2, 2.0);
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1][1]; ((double[][])c.v)[0][0] = 1.0; double val1 = get();
-                                        ((double[][])c.v)[0][0] = 2.0; double val2 = get();
+                ((double[][])c.v)[0][0] = 2.0; double val2 = get();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val2, 2.0);
@@ -432,7 +405,7 @@
 
             {
                 c.v = new double[1][1]; c.v[0] = new double[0]; double[] val1 = get1();
-                                        c.v[0] = new double[0]; double[] val2 = get1();
+                c.v[0] = new double[0]; double[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new double[1][1][1]; ((double[][][])c.v)[0][0][0] = 1.0; double val1 = get();
-                                           ((double[][][])c.v)[0][0][0] = 2.0; double val2 = get();
+                ((double[][][])c.v)[0][0][0] = 2.0; double val2 = get();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val2, 2.0);
@@ -468,14 +441,14 @@
 
             {
                 c.v = new double[1][1][1]; c.v[0][0] = new double[0]; double[] val1 = get1();
-                                           c.v[0][0] = new double[0]; double[] val2 = get1();
+                c.v[0][0] = new double[0]; double[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new double[1][1][1]; c.v[0] = new double[0][0]; double[][] val1 = get2();
-                                           c.v[0] = new double[0][0]; double[][] val2 = get2();
+                c.v[0] = new double[0][0]; double[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1.0; A val1 = get();
-                               c.v.a = 2.0; A val2 = get();
+                c.v.a = 2.0; A val2 = get();
 
                 assertEquals(val1.a, 2.0);
                 assertEquals(val2.a, 2.0);
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 1.0; double val1 = get1();
-                               c.v.a = 2.0; double val2 = get1();
+                c.v.a = 2.0; double val2 = get1();
                 c.v = new A(); c.v.a = 3.0; double val3 = get1();
 
                 assertEquals(val1, 1.0);
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1.0; c.v.next.a = 1.0; A val1 = get();
-                               c.v.a = 2.0; c.v.next.a = 2.0; A val2 = get();
+                c.v.a = 1.0; c.v.next.a = 1.0; A val1 = get();
+                c.v.a = 2.0; c.v.next.a = 2.0; A val2 = get();
 
                 assertEquals(val1.a, 2.0);
                 assertEquals(val2.a, 2.0);
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1.0; double val1 = get1();
-                               c.v.a = 2.0; double val2 = get1();
+                c.v.a = 1.0; double val1 = get1();
+                c.v.a = 2.0; double val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3.0; double val3 = get1();
+                c.v.a = 3.0; double val3 = get1();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1.0; double val1 = get(); double val2 = get1();
-                               c.v.a = 2.0; double val3 = get(); double val4 = get1();
+                c.v.a = 1.0; double val1 = get(); double val2 = get1();
+                c.v.a = 2.0; double val3 = get(); double val4 = get1();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val3, (isStableEnabled ? 1.0 : 2.0));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1.0; double val1 = get(); double val2 = get1();
-                               elem.a = 2.0; double val3 = get(); double val4 = get1();
+                elem.a = 1.0; double val1 = get(); double val2 = get1();
+                elem.a = 2.0; double val3 = get(); double val4 = get1();
 
                 assertEquals(val1, 1.0);
                 assertEquals(val3, (isServerWithStable ? 1.0 : 2.0));
diff --git a/hotspot/test/compiler/stable/TestStableFloat.java b/hotspot/test/compiler/stable/TestStableFloat.java
index 04acead..28f3427 100644
--- a/hotspot/test/compiler/stable/TestStableFloat.java
+++ b/hotspot/test/compiler/stable/TestStableFloat.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableFloat
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableFloat StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableFloat
- *           java/lang/invoke/TestStableFloat$FloatStable
- *           java/lang/invoke/TestStableFloat$StaticFloatStable
- *           java/lang/invoke/TestStableFloat$VolatileFloatStable
- *           java/lang/invoke/TestStableFloat$FloatArrayDim1
- *           java/lang/invoke/TestStableFloat$FloatArrayDim2
- *           java/lang/invoke/TestStableFloat$FloatArrayDim3
- *           java/lang/invoke/TestStableFloat$FloatArrayDim4
- *           java/lang/invoke/TestStableFloat$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableFloat$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableFloat$NestedStableField
- *           java/lang/invoke/TestStableFloat$NestedStableField$A
- *           java/lang/invoke/TestStableFloat$NestedStableField1
- *           java/lang/invoke/TestStableFloat$NestedStableField1$A
- *           java/lang/invoke/TestStableFloat$NestedStableField2
- *           java/lang/invoke/TestStableFloat$NestedStableField2$A
- *           java/lang/invoke/TestStableFloat$NestedStableField3
- *           java/lang/invoke/TestStableFloat$NestedStableField3$A
- *           java/lang/invoke/TestStableFloat$DefaultValue
- *           java/lang/invoke/TestStableFloat$DefaultStaticValue
- *           java/lang/invoke/TestStableFloat$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableFloat
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableFloat
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableFloat
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableFloat
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableFloat
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableFloat
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableFloat
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableFloat
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableFloat
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableFloat {
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static float get() { return c.v; }
         public static void test() throws Exception {
-                        float val1 = get();
+            float val1 = get();
             c.v = 1.0F; float val2 = get();
             assertEquals(val1, 0F);
             assertEquals(val2, 1.0F);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static float get() { return c.v; }
         public static void test() throws Exception {
-                        float val1 = get();
+            float val1 = get();
             c.v = 1.0F; float val2 = get();
             assertEquals(val1, 0F);
             assertEquals(val2, 1.0F);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1]; c.v[0] = 1.0F; float val1 = get();
-                                    c.v[0] = 2.0F; float val2 = get();
+                c.v[0] = 2.0F; float val2 = get();
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F));
 
                 c.v = new float[1]; c.v[0] = 3.0F; float val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 3.0F));
+                        : 3.0F));
             }
 
             {
                 c.v = new float[20]; c.v[10] = 1.0F; float val1 = get1();
-                                     c.v[10] = 2.0F; float val2 = get1();
+                c.v[10] = 2.0F; float val2 = get1();
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F));
 
                 c.v = new float[20]; c.v[10] = 3.0F; float val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 3.0F));
+                        : 3.0F));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1][1]; c.v[0][0] = 1.0F; float val1 = get();
-                                       c.v[0][0] = 2.0F; float val2 = get();
+                c.v[0][0] = 2.0F; float val2 = get();
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F));
 
                 c.v = new float[1][1]; c.v[0][0] = 3.0F; float val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 3.0F));
+                        : 3.0F));
 
                 c.v[0] = new float[1]; c.v[0][0] = 4.0F; float val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 4.0F));
+                        : 4.0F));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1][1][1]; c.v[0][0][0] = 1.0F; float val1 = get();
-                                          c.v[0][0][0] = 2.0F; float val2 = get();
+                c.v[0][0][0] = 2.0F; float val2 = get();
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F));
 
                 c.v = new float[1][1][1]; c.v[0][0][0] = 3.0F; float val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 3.0F));
+                        : 3.0F));
 
                 c.v[0] = new float[1][1]; c.v[0][0][0] = 4.0F; float val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 4.0F));
+                        : 4.0F));
 
                 c.v[0][0] = new float[1]; c.v[0][0][0] = 5.0F; float val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 5.0F));
+                        : 5.0F));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 1.0F; float val1 = get();
-                                             c.v[0][0][0][0] = 2.0F; float val2 = get();
+                c.v[0][0][0][0] = 2.0F; float val2 = get();
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F));
 
                 c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 3.0F; float val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 3.0F));
+                        : 3.0F));
 
                 c.v[0] = new float[1][1][1]; c.v[0][0][0][0] = 4.0F; float val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 4.0F));
+                        : 4.0F));
 
                 c.v[0][0] = new float[1][1]; c.v[0][0][0][0] = 5.0F; float val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 5.0F));
+                        : 5.0F));
 
                 c.v[0][0][0] = new float[1]; c.v[0][0][0][0] = 6.0F; float val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F)
-                                                    : 6.0F));
+                        : 6.0F));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1]; ((float[])c.v)[0] = 1.0F; float val1 = get();
-                                    ((float[])c.v)[0] = 2.0F; float val2 = get();
+                ((float[])c.v)[0] = 2.0F; float val2 = get();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, 2.0F);
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1][1]; ((float[][])c.v)[0][0] = 1.0F; float val1 = get();
-                                       ((float[][])c.v)[0][0] = 2.0F; float val2 = get();
+                ((float[][])c.v)[0][0] = 2.0F; float val2 = get();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, 2.0F);
@@ -432,7 +405,7 @@
 
             {
                 c.v = new float[1][1]; c.v[0] = new float[0]; float[] val1 = get1();
-                                       c.v[0] = new float[0]; float[] val2 = get1();
+                c.v[0] = new float[0]; float[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new float[1][1][1]; ((float[][][])c.v)[0][0][0] = 1.0F; float val1 = get();
-                                          ((float[][][])c.v)[0][0][0] = 2.0F; float val2 = get();
+                ((float[][][])c.v)[0][0][0] = 2.0F; float val2 = get();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, 2.0F);
@@ -468,14 +441,14 @@
 
             {
                 c.v = new float[1][1][1]; c.v[0][0] = new float[0]; float[] val1 = get1();
-                                          c.v[0][0] = new float[0]; float[] val2 = get1();
+                c.v[0][0] = new float[0]; float[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new float[1][1][1]; c.v[0] = new float[0][0]; float[][] val1 = get2();
-                                          c.v[0] = new float[0][0]; float[][] val2 = get2();
+                c.v[0] = new float[0][0]; float[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1.0F; A val1 = get();
-                               c.v.a = 2.0F; A val2 = get();
+                c.v.a = 2.0F; A val2 = get();
 
                 assertEquals(val1.a, 2.0F);
                 assertEquals(val2.a, 2.0F);
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 1.0F; float val1 = get1();
-                               c.v.a = 2.0F; float val2 = get1();
+                c.v.a = 2.0F; float val2 = get1();
                 c.v = new A(); c.v.a = 3.0F; float val3 = get1();
 
                 assertEquals(val1, 1.0F);
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1.0F; c.v.next.a = 1.0F; A val1 = get();
-                               c.v.a = 2.0F; c.v.next.a = 2.0F; A val2 = get();
+                c.v.a = 1.0F; c.v.next.a = 1.0F; A val1 = get();
+                c.v.a = 2.0F; c.v.next.a = 2.0F; A val2 = get();
 
                 assertEquals(val1.a, 2.0F);
                 assertEquals(val2.a, 2.0F);
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1.0F; float val1 = get1();
-                               c.v.a = 2.0F; float val2 = get1();
+                c.v.a = 1.0F; float val1 = get1();
+                c.v.a = 2.0F; float val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3.0F; float val3 = get1();
+                c.v.a = 3.0F; float val3 = get1();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1.0F; float val1 = get(); float val2 = get1();
-                               c.v.a = 2.0F; float val3 = get(); float val4 = get1();
+                c.v.a = 1.0F; float val1 = get(); float val2 = get1();
+                c.v.a = 2.0F; float val3 = get(); float val4 = get1();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1.0F; float val1 = get(); float val2 = get1();
-                               elem.a = 2.0F; float val3 = get(); float val4 = get1();
+                elem.a = 1.0F; float val1 = get(); float val2 = get1();
+                elem.a = 2.0F; float val3 = get(); float val4 = get1();
 
                 assertEquals(val1, 1.0F);
                 assertEquals(val3, (isServerWithStable ? 1.0F : 2.0F));
diff --git a/hotspot/test/compiler/stable/TestStableInt.java b/hotspot/test/compiler/stable/TestStableInt.java
index 2837bd3..831afd2 100644
--- a/hotspot/test/compiler/stable/TestStableInt.java
+++ b/hotspot/test/compiler/stable/TestStableInt.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableInt
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableInt StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableInt
- *           java/lang/invoke/TestStableInt$IntStable
- *           java/lang/invoke/TestStableInt$StaticIntStable
- *           java/lang/invoke/TestStableInt$VolatileIntStable
- *           java/lang/invoke/TestStableInt$IntArrayDim1
- *           java/lang/invoke/TestStableInt$IntArrayDim2
- *           java/lang/invoke/TestStableInt$IntArrayDim3
- *           java/lang/invoke/TestStableInt$IntArrayDim4
- *           java/lang/invoke/TestStableInt$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableInt$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableInt$NestedStableField
- *           java/lang/invoke/TestStableInt$NestedStableField$A
- *           java/lang/invoke/TestStableInt$NestedStableField1
- *           java/lang/invoke/TestStableInt$NestedStableField1$A
- *           java/lang/invoke/TestStableInt$NestedStableField2
- *           java/lang/invoke/TestStableInt$NestedStableField2$A
- *           java/lang/invoke/TestStableInt$NestedStableField3
- *           java/lang/invoke/TestStableInt$NestedStableField3$A
- *           java/lang/invoke/TestStableInt$DefaultValue
- *           java/lang/invoke/TestStableInt$DefaultStaticValue
- *           java/lang/invoke/TestStableInt$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableInt
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableInt
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableInt
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableInt
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableInt
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableInt
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableInt
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableInt
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableInt
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableInt {
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static int get() { return c.v; }
         public static void test() throws Exception {
-                        int val1 = get();
+            int val1 = get();
             c.v = 1; int val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static int get() { return c.v; }
         public static void test() throws Exception {
-                        int val1 = get();
+            int val1 = get();
             c.v = 1; int val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1]; c.v[0] = 1; int val1 = get();
-                                  c.v[0] = 2; int val2 = get();
+                c.v[0] = 2; int val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new int[1]; c.v[0] = 3; int val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
                 c.v = new int[20]; c.v[10] = 1; int val1 = get1();
-                                   c.v[10] = 2; int val2 = get1();
+                c.v[10] = 2; int val2 = get1();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new int[20]; c.v[10] = 3; int val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get();
-                                     c.v[0][0] = 2; int val2 = get();
+                c.v[0][0] = 2; int val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get();
-                                        c.v[0][0][0] = 2; int val2 = get();
+                c.v[0][0][0] = 2; int val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get();
-                                           c.v[0][0][0][0] = 2; int val2 = get();
+                c.v[0][0][0][0] = 2; int val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
 
                 c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 6));
+                        : 6));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1]; ((int[])c.v)[0] = 1; int val1 = get();
-                                  ((int[])c.v)[0] = 2; int val2 = get();
+                ((int[])c.v)[0] = 2; int val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1][1]; ((int[][])c.v)[0][0] = 1; int val1 = get();
-                                     ((int[][])c.v)[0][0] = 2; int val2 = get();
+                ((int[][])c.v)[0][0] = 2; int val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -432,7 +405,7 @@
 
             {
                 c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1();
-                                     c.v[0] = new int[0]; int[] val2 = get1();
+                c.v[0] = new int[0]; int[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new int[1][1][1]; ((int[][][])c.v)[0][0][0] = 1; int val1 = get();
-                                        ((int[][][])c.v)[0][0][0] = 2; int val2 = get();
+                ((int[][][])c.v)[0][0][0] = 2; int val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -468,14 +441,14 @@
 
             {
                 c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1();
-                                        c.v[0][0] = new int[0]; int[] val2 = get1();
+                c.v[0][0] = new int[0]; int[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2();
-                                        c.v[0] = new int[0][0]; int[][] val2 = get2();
+                c.v[0] = new int[0][0]; int[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1; A val1 = get();
-                               c.v.a = 2; A val2 = get();
+                c.v.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 1; int val1 = get1();
-                               c.v.a = 2; int val2 = get1();
+                c.v.a = 2; int val2 = get1();
                 c.v = new A(); c.v.a = 3; int val3 = get1();
 
                 assertEquals(val1, 1);
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1; c.v.next.a = 1; A val1 = get();
-                               c.v.a = 2; c.v.next.a = 2; A val2 = get();
+                c.v.a = 1; c.v.next.a = 1; A val1 = get();
+                c.v.a = 2; c.v.next.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1; int val1 = get1();
-                               c.v.a = 2; int val2 = get1();
+                c.v.a = 1; int val1 = get1();
+                c.v.a = 2; int val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3; int val3 = get1();
+                c.v.a = 3; int val3 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, (isStableEnabled ? 1 : 2));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1; int val1 = get(); int val2 = get1();
-                               c.v.a = 2; int val3 = get(); int val4 = get1();
+                c.v.a = 1; int val1 = get(); int val2 = get1();
+                c.v.a = 2; int val3 = get(); int val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isStableEnabled ? 1 : 2));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1; int val1 = get(); int val2 = get1();
-                               elem.a = 2; int val3 = get(); int val4 = get1();
+                elem.a = 1; int val1 = get(); int val2 = get1();
+                elem.a = 2; int val3 = get(); int val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isServerWithStable ? 1 : 2));
diff --git a/hotspot/test/compiler/stable/TestStableLong.java b/hotspot/test/compiler/stable/TestStableLong.java
index b6c2fbb..d162e53 100644
--- a/hotspot/test/compiler/stable/TestStableLong.java
+++ b/hotspot/test/compiler/stable/TestStableLong.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableLong
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableLong StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableLong
- *           java/lang/invoke/TestStableLong$LongStable
- *           java/lang/invoke/TestStableLong$StaticLongStable
- *           java/lang/invoke/TestStableLong$VolatileLongStable
- *           java/lang/invoke/TestStableLong$LongArrayDim1
- *           java/lang/invoke/TestStableLong$LongArrayDim2
- *           java/lang/invoke/TestStableLong$LongArrayDim3
- *           java/lang/invoke/TestStableLong$LongArrayDim4
- *           java/lang/invoke/TestStableLong$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableLong$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableLong$NestedStableField
- *           java/lang/invoke/TestStableLong$NestedStableField$A
- *           java/lang/invoke/TestStableLong$NestedStableField1
- *           java/lang/invoke/TestStableLong$NestedStableField1$A
- *           java/lang/invoke/TestStableLong$NestedStableField2
- *           java/lang/invoke/TestStableLong$NestedStableField2$A
- *           java/lang/invoke/TestStableLong$NestedStableField3
- *           java/lang/invoke/TestStableLong$NestedStableField3$A
- *           java/lang/invoke/TestStableLong$DefaultValue
- *           java/lang/invoke/TestStableLong$DefaultStaticValue
- *           java/lang/invoke/TestStableLong$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableLong
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableLong
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableLong
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableLong
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableLong
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableLong
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableLong
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableLong
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableLong
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableLong {
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static long get() { return c.v; }
         public static void test() throws Exception {
-                      long val1 = get();
+            long val1 = get();
             c.v = 1L; long val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1L);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static long get() { return c.v; }
         public static void test() throws Exception {
-                      long val1 = get();
+            long val1 = get();
             c.v = 1L; long val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1L);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1]; c.v[0] = 1; long val1 = get();
-                                   c.v[0] = 2; long val2 = get();
+                c.v[0] = 2; long val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new long[1]; c.v[0] = 3; long val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
                 c.v = new long[20]; c.v[10] = 1; long val1 = get1();
-                                    c.v[10] = 2; long val2 = get1();
+                c.v[10] = 2; long val2 = get1();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new long[20]; c.v[10] = 3; long val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1][1]; c.v[0][0] = 1; long val1 = get();
-                                      c.v[0][0] = 2; long val2 = get();
+                c.v[0][0] = 2; long val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new long[1][1]; c.v[0][0] = 3; long val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new long[1]; c.v[0][0] = 4; long val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1][1][1]; c.v[0][0][0] = 1; long val1 = get();
-                                         c.v[0][0][0] = 2; long val2 = get();
+                c.v[0][0][0] = 2; long val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new long[1][1][1]; c.v[0][0][0] = 3; long val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new long[1][1]; c.v[0][0][0] = 4; long val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new long[1]; c.v[0][0][0] = 5; long val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 1; long val1 = get();
-                                            c.v[0][0][0][0] = 2; long val2 = get();
+                c.v[0][0][0][0] = 2; long val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 3; long val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new long[1][1][1]; c.v[0][0][0][0] = 4; long val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new long[1][1]; c.v[0][0][0][0] = 5; long val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
 
                 c.v[0][0][0] = new long[1]; c.v[0][0][0][0] = 6; long val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 6));
+                        : 6));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1]; ((long[])c.v)[0] = 1; long val1 = get();
-                                   ((long[])c.v)[0] = 2; long val2 = get();
+                ((long[])c.v)[0] = 2; long val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1][1]; ((long[][])c.v)[0][0] = 1; long val1 = get();
-                                      ((long[][])c.v)[0][0] = 2; long val2 = get();
+                ((long[][])c.v)[0][0] = 2; long val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -432,7 +405,7 @@
 
             {
                 c.v = new long[1][1]; c.v[0] = new long[0]; long[] val1 = get1();
-                                     c.v[0] = new long[0]; long[] val2 = get1();
+                c.v[0] = new long[0]; long[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new long[1][1][1]; ((long[][][])c.v)[0][0][0] = 1L; long val1 = get();
-                                         ((long[][][])c.v)[0][0][0] = 2L; long val2 = get();
+                ((long[][][])c.v)[0][0][0] = 2L; long val2 = get();
 
                 assertEquals(val1, 1L);
                 assertEquals(val2, 2L);
@@ -468,14 +441,14 @@
 
             {
                 c.v = new long[1][1][1]; c.v[0][0] = new long[0]; long[] val1 = get1();
-                                         c.v[0][0] = new long[0]; long[] val2 = get1();
+                c.v[0][0] = new long[0]; long[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new long[1][1][1]; c.v[0] = new long[0][0]; long[][] val1 = get2();
-                                         c.v[0] = new long[0][0]; long[][] val2 = get2();
+                c.v[0] = new long[0][0]; long[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1; A val1 = get();
-                               c.v.a = 2; A val2 = get();
+                c.v.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 1; long val1 = get1();
-                               c.v.a = 2; long val2 = get1();
+                c.v.a = 2; long val2 = get1();
                 c.v = new A(); c.v.a = 3; long val3 = get1();
 
                 assertEquals(val1, 1);
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1; c.v.next.a = 1; A val1 = get();
-                               c.v.a = 2; c.v.next.a = 2; A val2 = get();
+                c.v.a = 1; c.v.next.a = 1; A val1 = get();
+                c.v.a = 2; c.v.next.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1; long val1 = get1();
-                               c.v.a = 2; long val2 = get1();
+                c.v.a = 1; long val1 = get1();
+                c.v.a = 2; long val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3; long val3 = get1();
+                c.v.a = 3; long val3 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, (isStableEnabled ? 1 : 2));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1; long val1 = get(); long val2 = get1();
-                               c.v.a = 2; long val3 = get(); long val4 = get1();
+                c.v.a = 1; long val1 = get(); long val2 = get1();
+                c.v.a = 2; long val3 = get(); long val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isStableEnabled ? 1 : 2));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1; long val1 = get(); long val2 = get1();
-                               elem.a = 2; long val3 = get(); long val4 = get1();
+                elem.a = 1; long val1 = get(); long val2 = get1();
+                elem.a = 2; long val3 = get(); long val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isServerWithStable ? 1 : 2));
diff --git a/hotspot/test/compiler/stable/TestStableMemoryBarrier.java b/hotspot/test/compiler/stable/TestStableMemoryBarrier.java
index f49b2ad..6b41340 100644
--- a/hotspot/test/compiler/stable/TestStableMemoryBarrier.java
+++ b/hotspot/test/compiler/stable/TestStableMemoryBarrier.java
@@ -28,66 +28,44 @@
  * @bug 8139758
  * @summary tests memory barrier correctly inserted for stable fields
  * @library /testlibrary /test/lib
+ * @modules java.base/jdk.internal.vm.annotation
  *
  * @run main/bootclasspath -Xcomp -XX:CompileOnly=::testCompile
- *                   java.lang.invoke.TestStableMemoryBarrier
+ *                         compiler.stable.TestStableMemoryBarrier
  *
  * @author hui.shi@linaro.org
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
 
-import java.lang.reflect.InvocationTargetException;
-
 public class TestStableMemoryBarrier {
-
     public static void main(String[] args) throws Exception {
-        run(NotDominate.class);
-
+        for (int i = 0; i < 1000000; i++) {
+            NotDominate.testCompile(i);
+        }
     }
-
     /* ====================================================
      * Stable field initialized in method, but its allocation
      * doesn't dominate MemBar Release at the end of method.
      */
-
-    static class NotDominate{
+    private static class NotDominate {
         public @Stable int v;
         public static int[] array = new int[100];
+
         public static NotDominate testCompile(int n) {
-           if ((n % 2) == 0) return null;
-           // add a loop here, trigger PhaseIdealLoop::verify_dominance
-           for (int i = 0; i < 100; i++) {
-              array[i] = n;
-           }
-           NotDominate nm = new NotDominate();
-           nm.v = n;
-           return nm;
-        }
-
-        public static void test() throws Exception {
-           for (int i = 0; i < 1000000; i++)
-               testCompile(i);
-        }
-    }
-
-    public static void run(Class<?> test) {
-        Throwable ex = null;
-        System.out.print(test.getName()+": ");
-        try {
-            test.getMethod("test").invoke(null);
-        } catch (InvocationTargetException e) {
-            ex = e.getCause();
-        } catch (Throwable e) {
-            ex = e;
-        } finally {
-            if (ex == null) {
-                System.out.println("PASSED");
-            } else {
-                System.out.println("FAILED");
-                ex.printStackTrace(System.out);
+            if ((n % 2) == 0) return null;
+            // add a loop here, trigger PhaseIdealLoop::verify_dominance
+            for (int i = 0; i < 100; i++) {
+                array[i] = n;
             }
+            NotDominate nm = new NotDominate();
+            nm.v = n;
+            return nm;
         }
+
+
     }
 }
+
diff --git a/hotspot/test/compiler/stable/TestStableObject.java b/hotspot/test/compiler/stable/TestStableObject.java
index b61736b..d16a544 100644
--- a/hotspot/test/compiler/stable/TestStableObject.java
+++ b/hotspot/test/compiler/stable/TestStableObject.java
@@ -26,65 +26,37 @@
 /*
  * @test TestStableObject
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableObject StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableObject
- *           java/lang/invoke/TestStableObject$ObjectStable
- *           java/lang/invoke/TestStableObject$StaticObjectStable
- *           java/lang/invoke/TestStableObject$VolatileObjectStable
- *           java/lang/invoke/TestStableObject$ObjectArrayDim1
- *           java/lang/invoke/TestStableObject$ObjectArrayDim2
- *           java/lang/invoke/TestStableObject$ObjectArrayDim3
- *           java/lang/invoke/TestStableObject$ObjectArrayDim4
- *           java/lang/invoke/TestStableObject$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableObject$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableObject$NestedStableField
- *           java/lang/invoke/TestStableObject$NestedStableField$A
- *           java/lang/invoke/TestStableObject$NestedStableField1
- *           java/lang/invoke/TestStableObject$NestedStableField1$A
- *           java/lang/invoke/TestStableObject$NestedStableField2
- *           java/lang/invoke/TestStableObject$NestedStableField2$A
- *           java/lang/invoke/TestStableObject$NestedStableField3
- *           java/lang/invoke/TestStableObject$NestedStableField3$A
- *           java/lang/invoke/TestStableObject$Values
- *           java/lang/invoke/TestStableObject$DefaultValue
- *           java/lang/invoke/TestStableObject$DefaultStaticValue
- *           java/lang/invoke/TestStableObject$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableObject
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableObject
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableObject
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableObject
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableObject
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableObject
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableObject
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableObject
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableObject
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableObject {
@@ -130,7 +102,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static Object get() { return c.v; }
         public static void test() throws Exception {
-                            Object val1 = get();
+            Object val1 = get();
             c.v = Values.A; Object val2 = get();
             assertEquals(val1, null);
             assertEquals(val2, Values.A);
@@ -160,7 +132,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static Object get() { return c.v; }
         public static void test() throws Exception {
-                            Object val1 = get();
+            Object val1 = get();
             c.v = Values.A; Object val2 = get();
             assertEquals(val1, null);
             assertEquals(val2, Values.A);
@@ -210,24 +182,24 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get();
-                                     c.v[0] = Values.B; Object val2 = get();
+                c.v[0] = Values.B; Object val2 = get();
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isServerWithStable ? Values.A : Values.B));
 
                 c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.C));
+                        : Values.C));
             }
 
             {
                 c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1();
-                                      c.v[10] = Values.B; Object val2 = get1();
+                c.v[10] = Values.B; Object val2 = get1();
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isServerWithStable ? Values.A : Values.B));
 
                 c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.C));
+                        : Values.C));
             }
 
             {
@@ -250,17 +222,17 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get();
-                                        c.v[0][0] = Values.B; Object val2 = get();
+                c.v[0][0] = Values.B; Object val2 = get();
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isServerWithStable ? Values.A : Values.B));
 
                 c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.C));
+                        : Values.C));
 
                 c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.D));
+                        : Values.D));
             }
 
             {
@@ -290,21 +262,21 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get();
-                                           c.v[0][0][0] = Values.B; Object val2 = get();
+                c.v[0][0][0] = Values.B; Object val2 = get();
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isServerWithStable ? Values.A : Values.B));
 
                 c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.C));
+                        : Values.C));
 
                 c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.D));
+                        : Values.D));
 
                 c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.E));
+                        : Values.E));
             }
 
             {
@@ -341,25 +313,25 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get();
-                                              c.v[0][0][0][0] = Values.B; Object val2 = get();
+                c.v[0][0][0][0] = Values.B; Object val2 = get();
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isServerWithStable ? Values.A : Values.B));
 
                 c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.C));
+                        : Values.C));
 
                 c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.D));
+                        : Values.D));
 
                 c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.E));
+                        : Values.E));
 
                 c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B)
-                                                    : Values.F));
+                        : Values.F));
             }
 
             {
@@ -400,7 +372,7 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1]; ((Object[])c.v)[0] = Values.A; Object val1 = get();
-                                     ((Object[])c.v)[0] = Values.B; Object val2 = get();
+                ((Object[])c.v)[0] = Values.B; Object val2 = get();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val2, Values.B);
@@ -427,7 +399,7 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1][1]; ((Object[][])c.v)[0][0] = Values.A; Object val1 = get();
-                                        ((Object[][])c.v)[0][0] = Values.B; Object val2 = get();
+                ((Object[][])c.v)[0][0] = Values.B; Object val2 = get();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val2, Values.B);
@@ -435,7 +407,7 @@
 
             {
                 c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1();
-                                     c.v[0] = new Object[0]; Object[] val2 = get1();
+                c.v[0] = new Object[0]; Object[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -463,7 +435,7 @@
         public static void test() throws Exception {
             {
                 c.v = new Object[1][1][1]; ((Object[][][])c.v)[0][0][0] = Values.A; Object val1 = get();
-                                           ((Object[][][])c.v)[0][0][0] = Values.B; Object val2 = get();
+                ((Object[][][])c.v)[0][0][0] = Values.B; Object val2 = get();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val2, Values.B);
@@ -471,14 +443,14 @@
 
             {
                 c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1();
-                                           c.v[0][0] = new Object[0]; Object[] val2 = get1();
+                c.v[0][0] = new Object[0]; Object[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2();
-                                           c.v[0] = new Object[0][0]; Object[][] val2 = get2();
+                c.v[0] = new Object[0][0]; Object[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -508,7 +480,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = Values.A; A val1 = get();
-                               c.v.a = Values.B; A val2 = get();
+                c.v.a = Values.B; A val2 = get();
 
                 assertEquals(val1.a, Values.B);
                 assertEquals(val2.a, Values.B);
@@ -516,7 +488,7 @@
 
             {
                 c.v = new A(); c.v.a = Values.A; Object val1 = get1();
-                               c.v.a = Values.B; Object val2 = get1();
+                c.v.a = Values.B; Object val2 = get1();
                 c.v = new A(); c.v.a = Values.C; Object val3 = get1();
 
                 assertEquals(val1, Values.A);
@@ -542,8 +514,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = Values.A; c.v.next.a = Values.A; A val1 = get();
-                               c.v.a = Values.B; c.v.next.a = Values.B; A val2 = get();
+                c.v.a = Values.A; c.v.next.a = Values.A; A val1 = get();
+                c.v.a = Values.B; c.v.next.a = Values.B; A val2 = get();
 
                 assertEquals(val1.a, Values.B);
                 assertEquals(val2.a, Values.B);
@@ -551,10 +523,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = Values.A; Object val1 = get1();
-                               c.v.a = Values.B; Object val2 = get1();
+                c.v.a = Values.A; Object val1 = get1();
+                c.v.a = Values.B; Object val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = Values.C; Object val3 = get1();
+                c.v.a = Values.C; Object val3 = get1();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
@@ -580,8 +552,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = Values.A; Object val1 = get(); Object val2 = get1();
-                               c.v.a = Values.B; Object val3 = get(); Object val4 = get1();
+                c.v.a = Values.A; Object val1 = get(); Object val2 = get1();
+                c.v.a = Values.B; Object val3 = get(); Object val4 = get1();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val3, (isStableEnabled ? Values.A : Values.B));
@@ -611,8 +583,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = Values.A; Object val1 = get(); Object val2 = get1();
-                               elem.a = Values.B; Object val3 = get(); Object val4 = get1();
+                elem.a = Values.A; Object val1 = get(); Object val2 = get1();
+                elem.a = Values.B; Object val3 = get(); Object val4 = get1();
 
                 assertEquals(val1, Values.A);
                 assertEquals(val3, (isServerWithStable ? Values.A : Values.B));
diff --git a/hotspot/test/compiler/stable/TestStableShort.java b/hotspot/test/compiler/stable/TestStableShort.java
index 1b0f127..617fb92 100644
--- a/hotspot/test/compiler/stable/TestStableShort.java
+++ b/hotspot/test/compiler/stable/TestStableShort.java
@@ -26,64 +26,37 @@
 /*
  * @test TestStableShort
  * @summary tests on stable fields and arrays
- * @library /testlibrary /test/lib
- * @build TestStableShort StableConfiguration sun.hotspot.WhiteBox
- * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassFileInstaller
- *           java/lang/invoke/StableConfiguration
- *           java/lang/invoke/TestStableShort
- *           java/lang/invoke/TestStableShort$ShortStable
- *           java/lang/invoke/TestStableShort$StaticShortStable
- *           java/lang/invoke/TestStableShort$VolatileShortStable
- *           java/lang/invoke/TestStableShort$ShortArrayDim1
- *           java/lang/invoke/TestStableShort$ShortArrayDim2
- *           java/lang/invoke/TestStableShort$ShortArrayDim3
- *           java/lang/invoke/TestStableShort$ShortArrayDim4
- *           java/lang/invoke/TestStableShort$ObjectArrayLowerDim0
- *           java/lang/invoke/TestStableShort$ObjectArrayLowerDim1
- *           java/lang/invoke/TestStableShort$NestedStableField
- *           java/lang/invoke/TestStableShort$NestedStableField$A
- *           java/lang/invoke/TestStableShort$NestedStableField1
- *           java/lang/invoke/TestStableShort$NestedStableField1$A
- *           java/lang/invoke/TestStableShort$NestedStableField2
- *           java/lang/invoke/TestStableShort$NestedStableField2$A
- *           java/lang/invoke/TestStableShort$NestedStableField3
- *           java/lang/invoke/TestStableShort$NestedStableField3$A
- *           java/lang/invoke/TestStableShort$DefaultValue
- *           java/lang/invoke/TestStableShort$DefaultStaticValue
- *           java/lang/invoke/TestStableShort$ObjectArrayLowerDim2
+ * @library /testlibrary /test/lib /
+ * @modules java.base/jdk.internal.vm.annotation
+ * @build sun.hotspot.WhiteBox
+ * @build compiler.stable.TestStableShort
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableShort
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:-TieredCompilation
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableShort
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableShort
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableShort
  *
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:+FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableShort
- * @run main/othervm -Xbootclasspath/a:.
- *                   -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
- *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- *                   -XX:-FoldStableValues
- *                   -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
- *                   java.lang.invoke.TestStableShort
- *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableShort
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp
+ *                         -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ *                         -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         compiler.stable.TestStableShort
  */
-package java.lang.invoke;
+
+package compiler.stable;
 
 import jdk.internal.vm.annotation.Stable;
-
 import java.lang.reflect.InvocationTargetException;
 
 public class TestStableShort {
@@ -127,7 +100,7 @@
         public static final DefaultValue c = new DefaultValue();
         public static short get() { return c.v; }
         public static void test() throws Exception {
-                     short val1 = get();
+            short val1 = get();
             c.v = 1; short val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -157,7 +130,7 @@
         public static final DefaultStaticValue c = new DefaultStaticValue();
         public static short get() { return c.v; }
         public static void test() throws Exception {
-                     short val1 = get();
+            short val1 = get();
             c.v = 1; short val2 = get();
             assertEquals(val1, 0);
             assertEquals(val2, 1);
@@ -207,24 +180,24 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1]; c.v[0] = 1; short val1 = get();
-                                    c.v[0] = 2; short val2 = get();
+                c.v[0] = 2; short val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new short[1]; c.v[0] = 3; short val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
                 c.v = new short[20]; c.v[10] = 1; short val1 = get1();
-                                     c.v[10] = 2; short val2 = get1();
+                c.v[10] = 2; short val2 = get1();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new short[20]; c.v[10] = 3; short val3 = get1();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
             }
 
             {
@@ -247,17 +220,17 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1][1]; c.v[0][0] = 1; short val1 = get();
-                                       c.v[0][0] = 2; short val2 = get();
+                c.v[0][0] = 2; short val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new short[1][1]; c.v[0][0] = 3; short val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new short[1]; c.v[0][0] = 4; short val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
             }
 
             {
@@ -287,21 +260,21 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1][1][1]; c.v[0][0][0] = 1; short val1 = get();
-                                          c.v[0][0][0] = 2; short val2 = get();
+                c.v[0][0][0] = 2; short val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new short[1][1][1]; c.v[0][0][0] = 3; short val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new short[1][1]; c.v[0][0][0] = 4; short val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new short[1]; c.v[0][0][0] = 5; short val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
             }
 
             {
@@ -338,25 +311,25 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 1; short val1 = get();
-                                             c.v[0][0][0][0] = 2; short val2 = get();
+                c.v[0][0][0][0] = 2; short val2 = get();
                 assertEquals(val1, 1);
                 assertEquals(val2, (isServerWithStable ? 1 : 2));
 
                 c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 3; short val3 = get();
                 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 3));
+                        : 3));
 
                 c.v[0] = new short[1][1][1]; c.v[0][0][0][0] = 4; short val4 = get();
                 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 4));
+                        : 4));
 
                 c.v[0][0] = new short[1][1]; c.v[0][0][0][0] = 5; short val5 = get();
                 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 5));
+                        : 5));
 
                 c.v[0][0][0] = new short[1]; c.v[0][0][0][0] = 6; short val6 = get();
                 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2)
-                                                    : 6));
+                        : 6));
             }
 
             {
@@ -397,7 +370,7 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1]; ((short[])c.v)[0] = 1; short val1 = get();
-                                    ((short[])c.v)[0] = 2; short val2 = get();
+                ((short[])c.v)[0] = 2; short val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -424,7 +397,7 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1][1]; ((short[][])c.v)[0][0] = 1; short val1 = get();
-                                       ((short[][])c.v)[0][0] = 2; short val2 = get();
+                ((short[][])c.v)[0][0] = 2; short val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -432,7 +405,7 @@
 
             {
                 c.v = new short[1][1]; c.v[0] = new short[0]; short[] val1 = get1();
-                                       c.v[0] = new short[0]; short[] val2 = get1();
+                c.v[0] = new short[0]; short[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -460,7 +433,7 @@
         public static void test() throws Exception {
             {
                 c.v = new short[1][1][1]; ((short[][][])c.v)[0][0][0] = 1; short val1 = get();
-                                          ((short[][][])c.v)[0][0][0] = 2; short val2 = get();
+                ((short[][][])c.v)[0][0][0] = 2; short val2 = get();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, 2);
@@ -468,14 +441,14 @@
 
             {
                 c.v = new short[1][1][1]; c.v[0][0] = new short[0]; short[] val1 = get1();
-                                          c.v[0][0] = new short[0]; short[] val2 = get1();
+                c.v[0][0] = new short[0]; short[] val2 = get1();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
 
             {
                 c.v = new short[1][1][1]; c.v[0] = new short[0][0]; short[][] val1 = get2();
-                                          c.v[0] = new short[0][0]; short[][] val2 = get2();
+                c.v[0] = new short[0][0]; short[][] val2 = get2();
 
                 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2)));
             }
@@ -505,7 +478,7 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.a = 1; A val1 = get();
-                               c.v.a = 2; A val2 = get();
+                c.v.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -513,7 +486,7 @@
 
             {
                 c.v = new A(); c.v.a = 1; short val1 = get1();
-                               c.v.a = 2; short val2 = get1();
+                c.v.a = 2; short val2 = get1();
                 c.v = new A(); c.v.a = 3; short val3 = get1();
 
                 assertEquals(val1, 1);
@@ -539,8 +512,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.next = new A();   c.v.next.next  = c.v;
-                               c.v.a = 1; c.v.next.a = 1; A val1 = get();
-                               c.v.a = 2; c.v.next.a = 2; A val2 = get();
+                c.v.a = 1; c.v.next.a = 1; A val1 = get();
+                c.v.a = 2; c.v.next.a = 2; A val2 = get();
 
                 assertEquals(val1.a, 2);
                 assertEquals(val2.a, 2);
@@ -548,10 +521,10 @@
 
             {
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 1; short val1 = get1();
-                               c.v.a = 2; short val2 = get1();
+                c.v.a = 1; short val1 = get1();
+                c.v.a = 2; short val2 = get1();
                 c.v = new A(); c.v.next = c.v;
-                               c.v.a = 3; short val3 = get1();
+                c.v.a = 3; short val3 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val2, (isStableEnabled ? 1 : 2));
@@ -577,8 +550,8 @@
         public static void test() throws Exception {
             {
                 c.v = new A(); c.v.left = c.v.right = c.v;
-                               c.v.a = 1; short val1 = get(); short val2 = get1();
-                               c.v.a = 2; short val3 = get(); short val4 = get1();
+                c.v.a = 1; short val1 = get(); short val2 = get1();
+                c.v.a = 2; short val3 = get(); short val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isStableEnabled ? 1 : 2));
@@ -608,8 +581,8 @@
             {
                 A elem = new A();
                 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
-                               elem.a = 1; short val1 = get(); short val2 = get1();
-                               elem.a = 2; short val3 = get(); short val4 = get1();
+                elem.a = 1; short val1 = get(); short val2 = get1();
+                elem.a = 2; short val3 = get(); short val4 = get1();
 
                 assertEquals(val1, 1);
                 assertEquals(val3, (isServerWithStable ? 1 : 2));
diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
index c1d6b05..45f08e6 100644
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.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,38 +26,50 @@
 /*
  * @test
  * @summary tests on constant folding of unsafe get operations
- * @library /testlibrary /test/lib
+ * @library /testlibrary
  *
  * @requires vm.flavor != "client"
  *
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.vm.annotation
+ *          java.base/jdk.internal.misc
  * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
- *                   -Xbatch -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:+UseUnalignedAccesses
- *                   java.lang.invoke.UnsafeGetConstantField
+ *                         -Xbatch -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         -XX:CompileCommand=dontinline,UnsafeGetConstantField.checkGetAddress()
+ *                         -XX:CompileCommand=dontinline,*.test*
+ *                         -XX:+UseUnalignedAccesses
+ *                         compiler.unsafe.UnsafeGetConstantField
+ *
  * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
- *                   -Xbatch -XX:-TieredCompilation
- *                   -XX:+FoldStableValues
- *                   -XX:-UseUnalignedAccesses
- *                   java.lang.invoke.UnsafeGetConstantField
+ *                         -Xbatch -XX:-TieredCompilation
+ *                         -XX:+FoldStableValues
+ *                         -XX:CompileCommand=dontinline,UnsafeGetConstantField.checkGetAddress()
+ *                         -XX:CompileCommand=dontinline,*.test*
+ *                         -XX:-UseUnalignedAccesses
+ *                         compiler.unsafe.UnsafeGetConstantField
  */
-package java.lang.invoke;
+package compiler.unsafe;
 
-import jdk.internal.vm.annotation.DontInline;
-import jdk.internal.vm.annotation.Stable;
-import jdk.internal.misc.Unsafe;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.FieldVisitor;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.vm.annotation.Stable;
 import jdk.test.lib.Asserts;
+import jdk.internal.misc.Unsafe;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
 public class UnsafeGetConstantField {
     static final Class<?> THIS_CLASS = UnsafeGetConstantField.class;
-
     static final Unsafe U = Unsafe.getUnsafe();
 
     public static void main(String[] args) {
@@ -75,7 +87,7 @@
             Asserts.assertEquals(checkGetAddress(), cookie);
         }
     }
-    @DontInline
+
     static long checkGetAddress() {
         return U.getAddress(nativeAddr);
     }
@@ -117,36 +129,65 @@
     static void runTest(JavaType t, int flags, boolean stable, boolean hasDefaultValue, String postfix) {
         Generator g = new Generator(t, flags, stable, hasDefaultValue, postfix);
         Test test = g.generate();
-        System.out.printf("type=%s flags=%d stable=%b default=%b post=%s\n",
+        System.err.printf("type=%s flags=%d stable=%b default=%b post=%s\n",
                           t.typeName, flags, stable, hasDefaultValue, postfix);
-        // Trigger compilation
-        for (int i = 0; i < 20_000; i++) {
-            Asserts.assertEQ(test.testDirect(), test.testUnsafe());
+        try {
+            Object expected = hasDefaultValue ? t.defaultValue : t.value;
+            // Trigger compilation
+            for (int i = 0; i < 20_000; i++) {
+                Asserts.assertEQ(expected, test.testDirect(), "i = "+ i +" direct read returns wrong value");
+                Asserts.assertEQ(expected, test.testUnsafe(), "i = "+ i +" unsafe read returns wrong value");
+            }
+
+            test.changeToDefault();
+            if (!hasDefaultValue && (stable || g.isFinal())) {
+                Asserts.assertEQ(t.value, test.testDirect(),
+                        "direct read doesn't return prev value");
+                // fails for getCharUnaligned due to JDK-8148518
+                if (!(t == JavaType.C && "Unaligned".equals(postfix))) {
+                    Asserts.assertEQ(test.testDirect(), test.testUnsafe());
+                }
+            } else {
+                Asserts.assertEQ(t.defaultValue, test.testDirect(),
+                        "direct read doesn't return default value");
+                Asserts.assertEQ(test.testDirect(), test.testUnsafe(),
+                        "direct and unsafe reads return different values");
+            }
+        } catch (Throwable e) {
+            try {
+                g.dump();
+            } catch (IOException io) {
+                io.printStackTrace();
+            }
+            throw e;
         }
     }
 
-    interface Test {
+    public interface Test {
         Object testDirect();
         Object testUnsafe();
+        void changeToDefault();
     }
 
     enum JavaType {
-        Z("Boolean", true),
-        B("Byte", new Byte((byte)-1)),
-        S("Short", new Short((short)-1)),
-        C("Char", Character.MAX_VALUE),
-        I("Int", -1),
-        J("Long", -1L),
-        F("Float", -1F),
-        D("Double", -1D),
-        L("Object", new Object());
+        Z("Boolean", true, false),
+        B("Byte", new Byte((byte) -1), new Byte((byte) 0)),
+        S("Short", new Short((short) -1), new Short((short) 0)),
+        C("Char", Character.MAX_VALUE, '\0'),
+        I("Int", -1, 0),
+        J("Long", -1L, 0L),
+        F("Float", -1F, 0F),
+        D("Double", -1D, 0D),
+        L("Object", "", null);
 
         String typeName;
         Object value;
+        Object defaultValue;
         String wrapper;
-        JavaType(String name, Object value) {
+        JavaType(String name, Object value, Object defaultValue) {
             this.typeName = name;
             this.value = value;
+            this.defaultValue = defaultValue;
             this.wrapper = internalName(value.getClass());
         }
 
@@ -154,7 +195,7 @@
             if (this == JavaType.L) {
                 return "Ljava/lang/Object;";
             } else {
-                return toString();
+                return name();
             }
         }
     }
@@ -177,6 +218,7 @@
      *   }
      *   public Object testDirect()  { return t.f; }
      *   public Object testUnsafe()  { return U.getInt(t, FIELD_OFFSET); }
+     *   public void changeToDefault() { U.putInt(t, 0, FIELD_OFFSET); }
      * }
      */
     static class Generator {
@@ -190,9 +232,11 @@
         final boolean hasDefaultValue;
         final String nameSuffix;
 
+        final String name;
         final String className;
         final String classDesc;
         final String fieldDesc;
+        final byte[] classFile;
 
         Generator(JavaType t, int flags, boolean stable, boolean hasDefaultValue, String suffix) {
             this.type = t;
@@ -202,9 +246,11 @@
             this.nameSuffix = suffix;
 
             fieldDesc = type.desc();
-            className = String.format("%s$Test%s%s__f=%d__s=%b__d=%b", internalName(THIS_CLASS), type.typeName,
-                                      suffix, flags, stable, hasDefaultValue);
+            name = String.format("Test%s%s__f=%d__s=%b__d=%b",
+                    type.typeName, suffix, flags, stable, hasDefaultValue);
+            className = "java/lang/invoke/" + name;
             classDesc = String.format("L%s;", className);
+            classFile = generateClassFile();
         }
 
         byte[] generateClassFile() {
@@ -228,7 +274,7 @@
 
             // Methods
             {   // <init>
-                MethodVisitor mv = cw.visitMethod(0, "<init>", "()V", null, null);
+                MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
                 mv.visitCode();
 
                 mv.visitVarInsn(ALOAD, 0);
@@ -266,6 +312,30 @@
                 mv.visitEnd();
             }
 
+            {   // public void changeToDefault() { U.putInt(t, FIELD_OFFSET, 0); }
+                MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "changeToDefault", "()V", null, null);
+                mv.visitCode();
+                getUnsafe(mv);
+                if (isStatic()) {
+                    mv.visitFieldInsn(GETSTATIC, className, "STATIC_BASE", "Ljava/lang/Object;");
+                } else {
+                    mv.visitFieldInsn(GETSTATIC, className, "t", classDesc);
+                }
+                mv.visitFieldInsn(GETSTATIC, className, "FIELD_OFFSET", "J");
+
+                if (type.defaultValue != null) {
+                    mv.visitLdcInsn(type.defaultValue);
+                } else {
+                    mv.visitInsn(ACONST_NULL);
+                }
+                String name = "put" + type.typeName + nameSuffix;
+                mv.visitMethodInsn(INVOKEVIRTUAL, UNSAFE_NAME, name, "(Ljava/lang/Object;J" + type.desc()+ ")V", false);
+                mv.visitInsn(RETURN);
+
+                mv.visitMaxs(0, 0);
+                mv.visitEnd();
+            }
+
             {   // <clinit>
                 MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
                 mv.visitCode();
@@ -305,7 +375,6 @@
         }
 
         Test generate() {
-            byte[] classFile = generateClassFile();
             Class<?> c = U.defineClass(className, classFile, 0, classFile.length, THIS_CLASS.getClassLoader(), null);
             try {
                 return (Test) c.newInstance();
@@ -360,20 +429,14 @@
             if (!isStatic()) {
                 mv.visitVarInsn(ALOAD, 0);
             }
-            switch (type) {
-                case L: {
-                    mv.visitTypeInsn(NEW, "java/lang/Object");
-                    mv.visitInsn(DUP);
-                    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
-
-                    break;
-                }
-                default: {
-                    mv.visitLdcInsn(type.value);
-                    break;
-                }
-            }
+            mv.visitLdcInsn(type.value);
             mv.visitFieldInsn((isStatic() ? PUTSTATIC : PUTFIELD), className, FIELD_NAME, fieldDesc);
         }
+
+        public void dump() throws IOException {
+            Path path = Paths.get(".", name + ".class").toAbsolutePath();
+            System.err.println("dumping test class to " + path);
+            Files.write(path, classFile);
+        }
     }
 }
diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java
index 1289046..ffafa07 100644
--- a/hotspot/test/gc/TestSmallHeap.java
+++ b/hotspot/test/gc/TestSmallHeap.java
@@ -31,6 +31,7 @@
  * @summary Verify that starting the VM with a small heap works
  * @library /testlibrary /test/lib
  * @modules java.management/sun.management
+ * @ignore 8076621
  * @build TestSmallHeap
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseParallelGC TestSmallHeap
diff --git a/hotspot/test/gc/metaspace/PerfCounter.java b/hotspot/test/gc/metaspace/PerfCounter.java
new file mode 100644
index 0000000..d39277c
--- /dev/null
+++ b/hotspot/test/gc/metaspace/PerfCounter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 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 sun.jvmstat.monitor.Monitor;
+
+/**
+ * Represents a performance counter in the JVM.
+ *
+ * See http://openjdk.java.net/groups/hotspot/docs/Serviceability.html#bjvmstat
+ * for more details about performance counters.
+ */
+public class PerfCounter {
+    private final Monitor monitor;
+    private final String name;
+
+    PerfCounter(Monitor monitor, String name) {
+        this.monitor = monitor;
+        this.name = name;
+    }
+
+    /**
+     * Returns the value of this performance counter as a long.
+     *
+     * @return The long value of this performance counter
+     * @throws RuntimeException If the value of the performance counter isn't a long
+     */
+    public long longValue() {
+        Object value = monitor.getValue();
+        if (value instanceof Long) {
+            return ((Long) value).longValue();
+        }
+        throw new RuntimeException("Expected " + monitor.getName() + " to have a long value");
+    }
+
+    /**
+     * Returns the name of the performance counter.
+     *
+     * @return The name of the performance counter.
+     */
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
diff --git a/hotspot/test/gc/metaspace/PerfCounters.java b/hotspot/test/gc/metaspace/PerfCounters.java
new file mode 100644
index 0000000..d6848f2
--- /dev/null
+++ b/hotspot/test/gc/metaspace/PerfCounters.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 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 sun.jvmstat.monitor.Monitor;
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.VmIdentifier;
+import jdk.test.lib.ProcessTools;
+
+/**
+ * PerfCounters can be used to get a performance counter from the currently
+ * executing VM.
+ *
+ * Throws a runtime exception if an error occurs while communicating with the
+ * currently executing VM.
+ */
+public class PerfCounters {
+    private final static MonitoredVm vm;
+
+    static {
+        try {
+            String pid = Integer.toString(ProcessTools.getProcessId());
+            VmIdentifier vmId = new VmIdentifier(pid);
+            MonitoredHost host = MonitoredHost.getMonitoredHost(vmId);
+            vm = host.getMonitoredVm(vmId);
+        } catch (Exception e) {
+            throw new RuntimeException("Could not connect to the VM");
+        }
+    }
+
+    /**
+     * Returns the performance counter with the given name.
+     *
+     * @param name The name of the performance counter.
+     * @throws IllegalArgumentException If no counter with the given name exists.
+     * @throws MonitorException If an error occurs while communicating with the VM.
+     * @return The performance counter with the given name.
+     */
+    public static PerfCounter findByName(String name)
+        throws MonitorException, IllegalArgumentException {
+        Monitor m = vm.findByName(name);
+        if (m == null) {
+            throw new IllegalArgumentException("Did not find a performance counter with name " + name);
+        }
+        return new PerfCounter(m, name);
+    }
+}
diff --git a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java
index fde6feb..bed5f7c 100644
--- a/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java
+++ b/hotspot/test/runtime/BadObjectClass/BootstrapRedefine.java
@@ -28,7 +28,6 @@
  * @library /testlibrary
  * @modules java.base/sun.misc
  *          java.management
- * @compile Object.java
  * @run main BootstrapRedefine
  */
 
@@ -37,8 +36,19 @@
 public class BootstrapRedefine {
 
     public static void main(String[] args) throws Exception {
-        String testClasses = System.getProperty("test.classes", ".");
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/p:" + testClasses, "-version");
+        String source = "package java.lang;" +
+                        "public class Object {" +
+                        "    void dummy1() { return; }" +
+                        "    void dummy2() { return; }" +
+                        "    void dummy3() { return; }" +
+                        "}";
+
+        ClassFileInstaller.writeClassToDisk("java/lang/Object",
+                                        InMemoryJavaCompiler.compile("java.lang.Object", source,
+                                        "-Xmodule:java.base"),
+                                        "mods/java.base");
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods", "-version");
         new OutputAnalyzer(pb.start())
             .shouldContain("Incompatible definition of java.lang.Object")
             .shouldHaveExitValue(1);
diff --git a/hotspot/test/runtime/BadObjectClass/Object.java b/hotspot/test/runtime/BadObjectClass/Object.java
deleted file mode 100644
index b2ad19b..0000000
--- a/hotspot/test/runtime/BadObjectClass/Object.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-/**
- * This is a fake java.lang.Object class.
- */
-public class Object {
-
-    // Add some methods
-    void dummy1() { return; }
-    void dummy2() { return; }
-    void dummy3() { return; }
-}
diff --git a/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppend.java b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppend.java
new file mode 100644
index 0000000..5dba459
--- /dev/null
+++ b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppend.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8087154
+ * @summary Uninitialized system property jdk.boot.class.path.append causes SIGSEGV
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ */
+
+import jdk.test.lib.*;
+
+// Test that system property jdk.boot.class.path.append is initialized.  Otherwise,
+// -XX:+PrintCompilation does causes a SIGSEGV.
+public class BootClassPathAppend {
+  public static void main(String[] args) throws Exception {
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+PrintCompilation", "-Xcomp", "-version");
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldContain("java.lang.Object");
+    output.shouldHaveExitValue(0);
+  }
+}
diff --git a/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java
new file mode 100644
index 0000000..1d18c3a
--- /dev/null
+++ b/hotspot/test/runtime/BootClassAppendProp/BootClassPathAppendProp.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+
+/*
+ * @test
+ * @build BootClassPathAppendProp
+ * @run main/othervm -Xbootclasspath/a:/usr/lib -showversion -Xbootclasspath/a:/i/dont/exist BootClassPathAppendProp
+ * @run main/othervm -Xpatch:/not/here -Xbootclasspath/a:/i/may/exist BootClassPathAppendProp
+ * @run main/othervm -Djdk.boot.class.path.append=newdir BootClassPathAppendProp
+ * @run main/othervm BootClassPathAppendProp
+ */
+
+// Test that property jdk.boot.class.path.append contains only the bootclasspath
+// info following the "modules" jimage file.
+public class BootClassPathAppendProp {
+    public static void main(String[] args) throws Exception {
+        // jdk.boot.class.path.append is a non-writeable, internal property.
+        // The call to System.getProperty should return null.
+        if (System.getProperty("jdk.boot.class.path.append") != null) {
+            throw new RuntimeException("Test failed, jdk.boot.class.path.append has value: " +
+                System.getProperty("jdk.boot.class.path.append"));
+        } else {
+            System.out.println("Test BootClassPathAppendProp passed");
+        }
+    }
+}
diff --git a/hotspot/test/runtime/BootClassAppendProp/SunBootClassPath.java b/hotspot/test/runtime/BootClassAppendProp/SunBootClassPath.java
new file mode 100644
index 0000000..e18b285
--- /dev/null
+++ b/hotspot/test/runtime/BootClassAppendProp/SunBootClassPath.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Make sure property sun.boot.class.path is null starting with JDK-9.
+ */
+
+// Test that the value of property sun.boot.class.path is null.
+public class SunBootClassPath {
+    public static void main(String[] args) throws Exception {
+        if (System.getProperty("sun.boot.class.path") != null) {
+            throw new RuntimeException("Test failed, sun.boot.class.path has value: " +
+                System.getProperty("sun.boot.class.path"));
+        } else {
+            System.out.println("Test SunBootClassPath passed");
+        }
+    }
+}
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
index 27ccc5d..dcbc353 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
@@ -27,8 +27,9 @@
  * @library /testlibrary /runtime/CommandLine/OptionsValidation/common
  * @modules java.base/sun.misc
  *          java.management
- *          jdk.attach
- *          jdk.management/sun.tools.attach
+ *          jdk.attach/sun.tools.attach
+ *          jdk.jvmstat/sun.jvmstat.monitor
+ * @build jdk.test.lib.* TestOptionsWithRanges
  * @run main/othervm/timeout=900 TestOptionsWithRanges
  */
 
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java
index 517f3a1..66c84a2 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java
@@ -26,9 +26,8 @@
  * @summary Test writeable VM Options with ranges.
  * @library /testlibrary /runtime/CommandLine/OptionsValidation/common
  * @modules java.base/sun.misc
+ *          jdk.attach/sun.tools.attach
  *          java.management
- *          jdk.attach
- *          jdk.management/sun.tools.attach
  * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestOptionsWithRangesDynamic
  */
 
diff --git a/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java
index 8a0b6f7..ab8955c 100644
--- a/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java
+++ b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.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
@@ -40,8 +40,18 @@
 public class BasicJarBuilder {
     private static final String classDir = System.getProperty("test.classes");
 
+    public static void build(boolean classesInWorkDir, String jarName,
+        String ...classNames) throws Exception {
+
+        if (classesInWorkDir) {
+            createSimpleJar(".", classDir + File.separator + jarName + ".jar", classNames);
+        } else {
+            build(jarName, classNames);
+        }
+    }
+
     public static void build(String jarName, String ...classNames) throws Exception {
-        createSimpleJar(".", classDir + File.separator + jarName + ".jar",
+        createSimpleJar(classDir, classDir + File.separator + jarName + ".jar",
             classNames);
     }
 
diff --git a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java
new file mode 100644
index 0000000..3b69f95
--- /dev/null
+++ b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java
@@ -0,0 +1,252 @@
+/*
+ * 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 Testing -Xbootclasspath/a support for CDS
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jvmstat/sun.jvmstat.monitor
+ * @ignore 8150683
+ * @compile javax/sound/sampled/MyClass.jasm
+ * @compile org/omg/CORBA/Context.jasm
+ * @compile nonjdk/myPackage/MyClass.java
+ * @build jdk.test.lib.* LoadClass
+ * @run main ClassFileInstaller LoadClass
+ * @run main/othervm BootAppendTests
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class BootAppendTests {
+    private static final String APP_CLASS = "LoadClass";
+    private static final String BOOT_APPEND_MODULE_CLASS = "javax/sound/sampled/MyClass";
+    private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS = "org/omg/CORBA/Context";
+    private static final String BOOT_APPEND_CLASS = "nonjdk/myPackage/MyClass";
+    private static final String BOOT_APPEND_MODULE_CLASS_NAME =
+        BOOT_APPEND_MODULE_CLASS.replace('/', '.');
+    private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME =
+        BOOT_APPEND_DUPLICATE_MODULE_CLASS.replace('/', '.');
+    private static final String BOOT_APPEND_CLASS_NAME =
+        BOOT_APPEND_CLASS.replace('/', '.');
+    private static final String[] ARCHIVE_CLASSES =
+        {BOOT_APPEND_MODULE_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS, BOOT_APPEND_CLASS};
+
+    private static final String modes[] = {"on", "off"};
+
+    private static String appJar;
+    private static String bootAppendJar;
+
+    public static void main(String... args) throws Exception {
+        dumpArchive();
+        testBootAppendModuleClass();
+        testBootAppendDuplicateModuleClass();
+        testBootAppendExcludedModuleClass();
+        testBootAppendDuplicateExcludedModuleClass();
+        testBootAppendClass();
+    }
+
+    static void dumpArchive() throws Exception {
+        // create the classlist
+        File classlist = new File(new File(System.getProperty("test.classes", ".")),
+                                  "BootAppendTest.classlist");
+        FileOutputStream fos = new FileOutputStream(classlist);
+        PrintStream ps = new PrintStream(fos);
+        for (String s : ARCHIVE_CLASSES) {
+            ps.println(s);
+        }
+        ps.close();
+        fos.close();
+
+        // build jar files
+        BasicJarBuilder.build(true, "app", APP_CLASS);
+        appJar = BasicJarBuilder.getTestJar("app.jar");
+        BasicJarBuilder.build("bootAppend",
+            BOOT_APPEND_MODULE_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS, BOOT_APPEND_CLASS);
+        bootAppendJar = BasicJarBuilder.getTestJar("bootAppend.jar");
+
+        // dump
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+            "-XX:SharedClassListFile=" + classlist.getPath(),
+            "-XX:+PrintSharedSpaces",
+            "-Xbootclasspath/a:" + bootAppendJar,
+            "-Xshare:dump");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Loading classes to share")
+              .shouldHaveExitValue(0);
+
+        // Make sure all the classes were successfully archived.
+        for (String archiveClass : ARCHIVE_CLASSES) {
+            output.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
+        }
+    }
+
+    // Test #1: If a class on -Xbootclasspath/a is from a package defined in
+    //          bootmodules, the class is not loaded at runtime.
+    //          Verify the behavior is the same when the class is archived
+    //          with CDS enabled at runtime.
+    //
+    //          The javax.sound.sampled package is defined in the java.desktop module.
+    //          The archived javax.sound.sampled.MyClass from the -Xbootclasspath/a
+    //          should not be loaded at runtime.
+    public static void testBootAppendModuleClass() throws Exception {
+        for (String mode : modes) {
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+                "-cp", appJar,
+                "-Xbootclasspath/a:" + bootAppendJar,
+                "-Xshare:" + mode,
+                APP_CLASS,
+                BOOT_APPEND_MODULE_CLASS_NAME);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("java.lang.ClassNotFoundException: javax.sound.sampled.MyClass");
+        }
+    }
+
+    // Test #2: If a class on -Xbootclasspath/a has the same fully qualified
+    //          name as a class defined in boot modules, the class is not loaded
+    //          from -Xbootclasspath/a. Verify the behavior is the same at runtime
+    //          when CDS is enabled.
+    //
+    //          The org.omg.CORBA.Context is a boot module class. The class on
+    //          the -Xbootclasspath/a path that has the same fully-qualified name
+    //          should not be loaded at runtime when CDS is enabled.
+    //          The one from the boot modules should be loaded instead.
+    public static void testBootAppendDuplicateModuleClass() throws Exception {
+        for (String mode : modes) {
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+                "-XX:+TraceClassLoading",
+                "-cp", appJar,
+                "-Xbootclasspath/a:" + bootAppendJar,
+                "-Xshare:" + mode,
+                APP_CLASS,
+                BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("[classload] org.omg.CORBA.Context source: jrt:/java.corba");
+        }
+    }
+
+    // Test #3: If a class on -Xbootclasspath/a is from a package defined in boot modules,
+    //          the class can be loaded from -Xbootclasspath/a when the module is excluded
+    //          using -limitmods. Verify the behavior is the same at runtime when CDS is
+    //          enabled.
+    //
+    //          The java.desktop module is excluded using -limitmods at runtime,
+    //          javax.sound.sampled.MyClass is archived from -Xbootclasspath/a. It can be
+    //          loaded from the archive at runtime.
+    public static void testBootAppendExcludedModuleClass() throws Exception {
+        for (String mode : modes) {
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+                "-XX:+TraceClassLoading",
+                "-cp", appJar,
+                "-Xbootclasspath/a:" + bootAppendJar,
+                "-limitmods", "java.base",
+                "-Xshare:" + mode,
+                APP_CLASS,
+                BOOT_APPEND_MODULE_CLASS_NAME);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("[classload] javax.sound.sampled.MyClass");
+
+            // When CDS is enabled, the shared class should be loaded from the archive.
+            if (mode.equals("on")) {
+                output.shouldContain("[classload] javax.sound.sampled.MyClass source: shared objects file");
+            }
+        }
+    }
+
+    // Test #4: If a class on -Xbootclasspath/a has the same fully qualified
+    //          name as a class defined in boot modules, the class is loaded
+    //          from -Xbootclasspath/a when the boot module is excluded using
+    //          -limitmods. Verify the behavior is the same at runtime when CDS is
+    //          enabled.
+    //
+    //          The org.omg.CORBA.Context is a boot module class. The class
+    //          on -Xbootclasspath/a that has the same fully-qualified name
+    //          as org.omg.CORBA.Context can be loaded at runtime when
+    //          java.corba is excluded.
+    public static void testBootAppendDuplicateExcludedModuleClass() throws Exception {
+        for (String mode : modes) {
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+                "-XX:+TraceClassLoading",
+                "-cp", appJar,
+                "-Xbootclasspath/a:" + bootAppendJar,
+                "-limitmods", "java.base",
+                "-Xshare:" + mode,
+                APP_CLASS,
+                BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("[classload] org.omg.CORBA.Context");
+            output.shouldMatch(".*\\[classload\\] org.omg.CORBA.Context source:.*bootAppend.jar");
+        }
+    }
+
+    // Test #5: If a class on -Xbootclasspath/a is not from named modules,
+    //          the class can be loaded at runtime. Verify the behavior is
+    //          the same at runtime when CDS is enabled.
+    //
+    //          The nonjdk.myPackage is not defined in named modules. The
+    //          archived nonjdk.myPackage.MyClass from -Xbootclasspath/a
+    //          can be loaded at runtime when CDS is enabled.
+    public static void testBootAppendClass() throws Exception {
+        for (String mode : modes) {
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./BootAppendTests.jsa",
+                "-XX:+TraceClassLoading",
+                "-cp", appJar,
+                "-Xbootclasspath/a:" + bootAppendJar,
+                "-Xshare:" + mode,
+                APP_CLASS,
+                BOOT_APPEND_CLASS_NAME);
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("[classload] nonjdk.myPackage.MyClass");
+
+            // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded
+            // from the shared archive.
+            if (mode.equals("on")) {
+                output.shouldContain(
+                    "[classload] nonjdk.myPackage.MyClass source: shared objects file");
+            }
+        }
+    }
+}
diff --git a/hotspot/test/runtime/SharedArchiveFile/LoadClass.java b/hotspot/test/runtime/SharedArchiveFile/LoadClass.java
new file mode 100644
index 0000000..417f924
--- /dev/null
+++ b/hotspot/test/runtime/SharedArchiveFile/LoadClass.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @summary Load the class specifiecd by the argument
+ *   Input: className
+ */
+public class LoadClass {
+    public static void main(String args[]) {
+        Class c = null;
+        try {
+            c = Class.forName(args[0]);
+        } catch (ClassNotFoundException e) {
+            System.out.println(e);
+        }
+        if (c != null) {
+            System.out.println(c + " loaded.");
+        }
+    }
+}
diff --git a/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java
index 55e3524..45f7451 100644
--- a/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java
+++ b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java
@@ -60,24 +60,6 @@
       output.shouldNotContain("Usage:");           // Should not print JVM help message
       output.shouldHaveExitValue(0);               // Should report success in error code.
 
-      // (2) With an invalid archive (boot class path has been prepended)
-      pb = ProcessTools.createJavaProcessBuilder(
-          "-Xbootclasspath/p:foo.jar",
-          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=" + filename,
-          "-XX:+PrintSharedArchiveAndExit", "-version");
-      output = new OutputAnalyzer(pb.start());
-      output.shouldContain("archive is invalid");
-      output.shouldNotContain("java version");     // Should not print JVM version
-      output.shouldHaveExitValue(1);               // Should report failure in error code.
-
-      pb = ProcessTools.createJavaProcessBuilder(
-          "-Xbootclasspath/p:foo.jar",
-          "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=" + filename,
-          "-XX:+PrintSharedArchiveAndExit");
-      output = new OutputAnalyzer(pb.start());
-      output.shouldContain("archive is invalid");
-      output.shouldNotContain("Usage:");           // Should not print JVM help message
-      output.shouldHaveExitValue(1);               // Should report failure in error code.
     } catch (RuntimeException e) {
       e.printStackTrace();
       output.shouldContain("Unable to use shared archive");
diff --git a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java
index 50906ea..67059bf 100644
--- a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.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
@@ -32,6 +32,7 @@
  * @library /testlibrary /test/lib
  * @modules java.base/sun.misc
  *          java.management
+ *          jdk.jartool/sun.tools.jar
  * @build SharedStringsWb SharedStrings BasicJarBuilder sun.hotspot.WhiteBox
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main SharedStrings
@@ -40,7 +41,7 @@
 
 public class SharedStrings {
     public static void main(String[] args) throws Exception {
-        BasicJarBuilder.build("whitebox", "sun/hotspot/WhiteBox");
+        BasicJarBuilder.build(true, "whitebox", "sun/hotspot/WhiteBox");
 
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
             "-XX:+UnlockDiagnosticVMOptions",
diff --git a/hotspot/test/runtime/SharedArchiveFile/javax/sound/sampled/MyClass.jasm b/hotspot/test/runtime/SharedArchiveFile/javax/sound/sampled/MyClass.jasm
new file mode 100644
index 0000000..5e6078c
--- /dev/null
+++ b/hotspot/test/runtime/SharedArchiveFile/javax/sound/sampled/MyClass.jasm
@@ -0,0 +1,46 @@
+/*
+ * 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/sound/sampled;
+
+public class MyClass
+    version 51:0
+{
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+    aload_0;
+    invokespecial   Method java/lang/Object."<init>":"()V";
+    return;
+}
+
+
+public Method toString:"()Ljava/lang/String;"
+    stack 1 locals 1
+{
+    ldc String "hi";
+    areturn; 
+}
+
+}
diff --git a/hotspot/test/runtime/SharedArchiveFile/nonjdk/myPackage/MyClass.java b/hotspot/test/runtime/SharedArchiveFile/nonjdk/myPackage/MyClass.java
new file mode 100644
index 0000000..265457c
--- /dev/null
+++ b/hotspot/test/runtime/SharedArchiveFile/nonjdk/myPackage/MyClass.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 nonjdk.myPackage;
+
+public class MyClass {
+    public String toString() {
+        return "hi";
+    }
+}
diff --git a/hotspot/test/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm b/hotspot/test/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm
new file mode 100644
index 0000000..c3424b9
--- /dev/null
+++ b/hotspot/test/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm
@@ -0,0 +1,46 @@
+/*
+ * 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 org/omg/CORBA;
+
+public class Context 
+    version 51:0
+{
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+    aload_0;
+    invokespecial   Method java/lang/Object."<init>":"()V";
+    return;
+}
+
+
+public Method toString:"()Ljava/lang/String;"
+    stack 1 locals 1
+{
+    ldc String "hi";
+    areturn; 
+}
+
+}
diff --git a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java
new file mode 100644
index 0000000..7e39301
--- /dev/null
+++ b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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
+ * @modules java.base/jdk.internal.loader
+ *          java.desktop
+ * @library /testlibrary
+ * @run main/othervm GetSysPkgTest
+ */
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import jdk.test.lib.*;
+
+// Test that JVM get_system_package() returns the module location for defined packages.
+public class GetSysPkgTest {
+
+    private static Object invoke(Method m, Object obj, Object... args) throws Throwable {
+        try {
+            return m.invoke(obj, args);
+        } catch (InvocationTargetException e) {
+            throw e.getCause();
+        }
+    }
+
+    private static Method findMethod(String name) {
+        for (Method m : jdk.internal.loader.BootLoader.class.getDeclaredMethods()) {
+            if (m.getName().equals(name)) {
+                m.setAccessible(true);
+                return m;
+            }
+        }
+        throw new RuntimeException("Failed to find method " + name + " in java.lang.reflect.Module");
+    }
+
+    // Throw RuntimeException if getSystemPackageLocation() does not return
+    // the expected location.
+    static void getPkg(String name, String expected_loc) throws Throwable {
+        String loc = (String)invoke(findMethod("getSystemPackageLocation"), null, name);
+        if (loc == null) {
+            if (expected_loc == null) return;
+            System.out.println("Expected location: " + expected_loc +
+                ", for package: " + name + ", got: null");
+        } else if (expected_loc == null) {
+            System.out.println("Expected location: null, for package: " +
+                name + ", got: " + loc);
+        } else if (!loc.equals(expected_loc)) {
+            System.out.println("Expected location: " +
+                expected_loc + ", for package: " + name + ", got: " + loc);
+        } else {
+            return;
+        }
+        throw new RuntimeException();
+    }
+
+    public static void main(String args[]) throws Throwable {
+        if (args.length == 0 || !args[0].equals("do_tests")) {
+
+            // Create a package found via -Xbootclasspath/a
+            String source = "package BootLdr_package; " +
+                            "public class BootLdrPkg { " +
+                            "    public int mth() { return 4; } " +
+                            "}";
+            byte[] klassbuf =
+                InMemoryJavaCompiler.compile("BootLdr_package.BootLdrPkg", source);
+            ClassFileInstaller.writeClassToDisk("BootLdr_package/BootLdrPkg", klassbuf, "bl_dir");
+
+            // Create a package found via -cp.
+            source = "package GetSysPkg_package; " +
+                     "public class GetSysClass { " +
+                     "    public int mth() { return 4; } " +
+                     "}";
+            klassbuf =
+                InMemoryJavaCompiler.compile("GetSysPkg_package.GetSysClass", source);
+            ClassFileInstaller.writeClassToDisk("GetSysPkg_package/GetSysClass", klassbuf);
+
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:bl_dir",
+                "-XaddExports: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);
+            return;
+        }
+
+        getPkg("java/lang", "jrt:/java.base");
+        getPkg("javax/script", null);          // Package not defined
+
+        // Test a package that does not yet have any referenced classes.
+        // Note: if another class in com/sun/crypto/provider/ happens to get
+        //       loaded or if class PrivateKeyInfo disappears from this package
+        //       then this test will fail.
+        getPkg("com/sun/crypto/provider", null);
+        // Now make sure a class in the package is referenced.
+        Class newClass = Class.forName("com.sun.crypto.provider.PrivateKeyInfo");
+        getPkg("com/sun/crypto/provider", "jrt:/java.base");
+
+        getPkg("java/nio/charset", "jrt:/java.base");
+
+        // Test a package in a module not owned by boot loader.
+        Class clss = Class.forName("javax.activation.DataHandler");
+        if (clss == null)
+            throw new RuntimeException("Could not find class javax.activation.DataHandler");
+        getPkg("javax/activation", null);       // Not owned by boot loader
+
+        // Test a package not in jimage file.
+        clss = Class.forName("GetSysPkg_package.GetSysClass");
+        if (clss == null)
+            throw new RuntimeException("Could not find class GetSysPkg_package.GetSysClass");
+        getPkg("GetSysPkg_package", null);
+
+        // Access a class with a package in a boot loader module other than java.base
+        clss = Class.forName("java.awt.Button");
+        if (clss == null)
+            throw new RuntimeException("Could not find class java.awt.Button");
+        getPkg("java/awt", "jrt:/java.desktop");
+
+        // Test getting the package location from a class found via -Xbootclasspath/a
+        clss = Class.forName("BootLdr_package.BootLdrPkg");
+        if (clss == null)
+            throw new RuntimeException("Could not find class BootLdr_package.BootLdrPkg");
+        String bootldrPkg = (String)invoke(findMethod("getSystemPackageLocation"), null, "BootLdr_package");
+        if (bootldrPkg == null) {
+            throw new RuntimeException("Expected BootLdr_package to return non-null value");
+        }
+        if (!bootldrPkg.equals("bl_dir")) {
+            throw new RuntimeException("Expected BootLdr_package to return bl_dir, got: " + bootldrPkg);
+        }
+
+        // Test when package's class reference is an array.
+        // Note: if another class in javax/crypto happens to get loaded
+        //       or if class AEADBadTagException disappears from this package
+        //       then this test will fail.
+        getPkg("javax/crypto", null);
+        javax.crypto.AEADBadTagException[] blah = new javax.crypto.AEADBadTagException[3];
+        getPkg("javax/crypto", "jrt:/java.base");
+
+    }
+}
diff --git a/hotspot/test/runtime/logging/ModulesTest.java b/hotspot/test/runtime/logging/ModulesTest.java
new file mode 100644
index 0000000..3547a06
--- /dev/null
+++ b/hotspot/test/runtime/logging/ModulesTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary modules=debug should have logging from statements in the code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run main ModulesTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class ModulesTest {
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-Xlog:modules=trace", "-version");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("define_javabase_module(): Definition of module:");
+        output.shouldContain("define_javabase_module(): creation of package");
+        output.shouldContain("define_module(): creation of module");
+        output.shouldContain("define_module(): creation of package");
+        output.shouldContain("set_bootloader_unnamed_module(): recording unnamed");
+        output.shouldContain("add_module_exports(): package");
+        output.shouldContain("add_reads_module(): Adding read from module");
+        output.shouldContain("Setting package: class:");
+        output.shouldHaveExitValue(0);
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccModuleTest.java b/hotspot/test/runtime/modules/AccModuleTest.java
new file mode 100644
index 0000000..f1f8ab0
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccModuleTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * @compile acc_module.jcod
+ * @build AccModuleTest
+ * @run main AccModuleTest
+ */
+
+import java.io.File;
+import jdk.test.lib.*;
+
+public class AccModuleTest {
+
+    public static void main(String args[]) throws Throwable {
+        System.out.println("Test that ACC_MODULE in class access flags does not cause ClassFormatError");
+        Class clss = Class.forName("acc_module");
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java
new file mode 100644
index 0000000..ec88eef
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java
@@ -0,0 +1,138 @@
+/*
+ * 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
+ * @summary Test that if module m1 can not read module m2, then class p1.c1
+ *          in module m1 can not access p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build CheckRead
+ * @run main/othervm -Xbootclasspath/a:. CheckRead
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+//                  defines m2 --> packages p2
+//                  defines m3 --> packages p3
+//
+// m1 can not read m2
+// package p2 in m2 is exported to m1
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2.
+// Access denied since m1 can not read m2.
+//
+public class CheckRead {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publicly defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m3
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m3")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base, m2
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .requires("m2")
+                        .conceals("p3")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+        map.put("m3", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1, m2 and m3
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m3") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m1 but m2 is not readable from m1)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("cannot access")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      CheckRead test = new CheckRead();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java
new file mode 100644
index 0000000..7ccf918
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java
@@ -0,0 +1,138 @@
+/*
+ * 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
+ * @summary Test that if module m1 can not read module m2, then class p1.c1
+ *          in module m1 can not access p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build DiffCL_CheckRead
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_CheckRead
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+//                  defines m3 --> packages p3
+//
+// m1 can not read m2
+// package p2 in m2 is exported to m1
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2.
+// Access denied since m1 can not read m2.
+//
+public class DiffCL_CheckRead {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publicly defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m3
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m3")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base, m2
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .requires("m2")
+                        .conceals("p3")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+        map.put("m3", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1, m2 and m3
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("m3") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m1 but m2 is not readable from m1)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("cannot access")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      DiffCL_CheckRead test = new DiffCL_CheckRead();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java
new file mode 100644
index 0000000..c815a85
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java
@@ -0,0 +1,140 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, but package p2 in m2
+ *          is exported specifically to module m3, then class p1.c1 in m1 can not
+ *          access p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build DiffCL_ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+//                  defines m3 --> packages p3
+//
+// m1 can read m2
+// package p2 in m2 is exported to m3
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access denied since although m1 can read m2, p2 is exported only to m3.
+//
+public class DiffCL_ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2, m3
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .requires("m3")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base, m3
+        // Packages:          p2
+        // Packages exported: p2 is exported to m3
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m3")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base, m2
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .requires("m2")
+                        .conceals("p3")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+        map.put("m3", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("m3") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m3 not to m1)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      DiffCL_ExpQualOther test = new DiffCL_ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java
new file mode 100644
index 0000000..c1c38fd
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java
@@ -0,0 +1,120 @@
+/*
+ * 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
+ * @summary class p1.c1 defined in m1 tries to access p2.c2 defined in m2.
+ *          Access allowed since m1 can read m2 and package p2 is exported to m1.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build DiffCL_ExpQualToM1
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_ExpQualToM1
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported to m1
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access allowed since m1 can read m2 and package p2 is exported to m1.
+//
+public class DiffCL_ExpQualToM1 {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported to unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: package p2 is exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      DiffCL_ExpQualToM1 test = new DiffCL_ExpQualToM1();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java
new file mode 100644
index 0000000..a866833
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java
@@ -0,0 +1,121 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, and package p2 in m2 is
+ *          exported unqualifiedly, then class p1.c1 in m1 can read p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build DiffCL_ExpUnqual
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_ExpUnqual
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported to m1
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access allowed since m1 can read m2 and package p2 is exported
+// unqualifiedly.
+//
+public class DiffCL_ExpUnqual {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: package p2 is exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      DiffCL_ExpUnqual test = new DiffCL_ExpUnqual();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java
new file mode 100644
index 0000000..d4f3d62
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, but package p2 in m2 is not
+ *          exported, then class p1.c1 in m1 can not read p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build DiffCL_PkgNotExp
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_PkgNotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is not exported
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access denied since p2 is not exported.
+//
+public class DiffCL_PkgNotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      DiffCL_PkgNotExp test = new DiffCL_PkgNotExp();
+      test.createLayerOnBoot();
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java
new file mode 100644
index 0000000..6df74bf
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java
@@ -0,0 +1,230 @@
+/*
+ * 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
+ * @summary class p1.c1 defined in m1 tries to access p2.c2 defined in unnamed module.
+ * @library /testlibrary /test/lib
+ * @modules java.base/jdk.internal.module
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @compile p1/c1ReadEdgeDiffLoader.java
+ * @compile p1/c1Loose.java
+ * @build DiffCL_Umod
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_Umod
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+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.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+//                  package p1 in m1 is exported unqualifiedly
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in
+// in unnamed module.
+//
+// Three access attempts occur in this test:
+//   1. The first access is not allowed because a strict module
+//      cannot read an unnamed module.
+//   2. In this scenario a strict module establishes readability
+//      to the particular unnamed module it is trying to access.
+//      Access is allowed.
+//   3. Module m1 in the test_looseModuleLayer() method
+//      is transitioned to a loose module, access
+//      to all unnamed modules is allowed.
+//
+public class DiffCL_Umod {
+
+ // Create Layers over the boot layer to test different
+ // accessing scenarios of a named module to an unnamed module.
+
+ // Module m1 is a strict module and has not established
+ // readability to an unnamed module that p2.c2 is defined in.
+ public void test_strictModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MyDiffClassLoader.loader1 = new MyDiffClassLoader();
+     MyDiffClassLoader.loader2 = new MyDiffClassLoader();
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader2
+     // to achieve differing class loaders.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", MyDiffClassLoader.loader1);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1
+     Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+
+     // Attempt access
+     try {
+         p1_c1_class.newInstance();
+         throw new RuntimeException("Test Failed, strict module m1 should not be able " +
+                                    "to access public type p2.c2 defined in unnamed module");
+     } catch (IllegalAccessError e) {
+     }
+}
+
+ // Module m1 is a strict module and has established
+ // readability to an unnamed module that p2.c2 is defined in.
+ public void test_strictModuleUnnamedReadableLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MyDiffClassLoader.loader1 = new MyDiffClassLoader();
+     MyDiffClassLoader.loader2 = new MyDiffClassLoader();
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader2
+     // to achieve differing class loaders.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", MyDiffClassLoader.loader1);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1ReadEdgeDiffLoader
+     Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1ReadEdgeDiffLoader");
+
+     try {
+        // Read edge between m1 and the unnamed module that loads p2.c2 is established in
+        // c1ReadEdgeDiffLoader's ctor before attempting access.
+        p1_c1_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, module m1 has established readability to p2/c2 loader's " +
+                                    "unnamed module, access should be allowed: " + e.getMessage());
+     }
+ }
+
+ // Module m1 is a loose module and thus can read all unnamed modules.
+ public void test_looseModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MyDiffClassLoader.loader1 = new MyDiffClassLoader();
+     MyDiffClassLoader.loader2 = new MyDiffClassLoader();
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader2
+     // to achieve differing class loaders.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", MyDiffClassLoader.loader1);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1Loose
+     Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1Loose");
+
+     // change m1 to be a loose module
+     Module m1 = layer.findModule("m1").get();
+     jdk.internal.module.Modules.addReads(m1, null);
+
+     try {
+         p1_c1_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, loose module m1 should be able to access " +
+                                    "public type p2.c2 defined in unnamed module: " + e.getMessage());
+     }
+ }
+
+ public static void main(String args[]) throws Throwable {
+   DiffCL_Umod test = new DiffCL_Umod();
+   test.test_strictModuleLayer();                // access denied
+   test.test_strictModuleUnnamedReadableLayer(); // access allowed
+   test.test_looseModuleLayer();                 // access allowed
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java
new file mode 100644
index 0000000..5cd133d
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java
@@ -0,0 +1,173 @@
+/*
+ * 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
+ * @summary class p3.c3 defined in module m1 tries to access c4 defined in an unnamed package
+ *          and an unnamed module.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile c4.java
+ * @compile p3/c3.jcod
+ * @compile p3/c3ReadEdgeDiffLoader.jcod
+ * @build DiffCL_UmodUpkg
+ * @run main/othervm -Xbootclasspath/a:. DiffCL_UmodUpkg
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p3
+//                  package p3 in m1 is exported unqualifiedly
+//
+// class p3.c3 defined in m1 tries to access c4 defined in
+// in unnamed module.
+//
+// Two access attempts occur in this test:
+//   1. The first access is not allowed because a strict module
+//      cannot read an unnamed module.
+//   2. In this scenario a strict module establishes readability
+//      to the particular unnamed module it is trying to access.
+//      Access is allowed.
+//
+public class DiffCL_UmodUpkg {
+
+ // Create Layers over the boot layer to test different
+ // accessing scenarios of a named module to an unnamed module.
+
+ // Module m1 is a strict module and has not established
+ // readability to an unnamed module that c4 is defined in.
+ public void test_strictModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p3
+     // Packages exported: p3 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p3")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MyDiffClassLoader.loader1 = new MyDiffClassLoader();
+     MyDiffClassLoader.loader2 = new MyDiffClassLoader();
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader2
+     // to achieve differing class loaders.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", MyDiffClassLoader.loader1);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p3.c3
+     Class p3_c3_class = MyDiffClassLoader.loader1.loadClass("p3.c3");
+
+     // Attempt access
+     try {
+         p3_c3_class.newInstance();
+         throw new RuntimeException("Test Failed, strict module m1 should not be able to access " +
+                                    "public type c4 defined in unnamed module");
+     } catch (IllegalAccessError e) {
+     }
+}
+
+ // Module m1 is a strict module and has established
+ // readability to an unnamed module that c4 is defined in.
+ public void test_strictModuleUnnamedReadableLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p3
+     // Packages exported: p3 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p3")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MyDiffClassLoader.loader1 = new MyDiffClassLoader();
+     MyDiffClassLoader.loader2 = new MyDiffClassLoader();
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader2
+     // to achieve differing class loaders.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", MyDiffClassLoader.loader1);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p3.c3ReadEdgeDiffLoader
+     Class p3_c3_class = MyDiffClassLoader.loader1.loadClass("p3.c3ReadEdgeDiffLoader");
+
+     try {
+        // Read edge between m1 and the unnamed module that loads c4 is established in
+        // C3ReadEdgeDiffLoader's ctor before attempting access.
+        p3_c3_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, module m1 has established readability to " +
+                                    "c4 loader's unnamed module, access should be allowed: " + e.getMessage());
+     }
+ }
+
+ public static void main(String args[]) throws Throwable {
+   DiffCL_UmodUpkg test = new DiffCL_UmodUpkg();
+   test.test_strictModuleLayer();                // access denied
+   test.test_strictModuleUnnamedReadableLayer(); // access allowed
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java
new file mode 100644
index 0000000..4645d09
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java
@@ -0,0 +1,140 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, but package p2 in m2
+ *          is exported specifically to module m3, then class p1.c1 in m1 can not
+ *          access p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+//                  defines m2 --> packages p2
+//                  defines m3 --> packages p3
+//
+// m1 can read m2
+// package p2 in m2 is exported to m3
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access denied since although m1 can read m2, p2 is exported only to m3.
+//
+public class ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2, m3
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .requires("m3")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported to m3
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m3")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base, m2
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .requires("m2")
+                        .conceals("p3")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+        map.put("m3", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m3") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m3 not to m1)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ExpQualOther test = new ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java
new file mode 100644
index 0000000..fa0b094
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java
@@ -0,0 +1,110 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, AND package p2 in m2 is
+ *          exported qualifiedly to m1, then class p1.c1 in m1 can read p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build ExpQualToM1
+ * @run main/othervm -Xbootclasspath/a:. ExpQualToM1
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+public class ExpQualToM1 {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported qualifiedly to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ExpQualToM1 test = new ExpQualToM1();
+      test.createLayerOnBoot();
+    }
+
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java
new file mode 100644
index 0000000..a7c74ba
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java
@@ -0,0 +1,109 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, AND package p2 in module2 is
+ *          exported unqualifiedly, then class p1.c1 in m1 can read p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build ExpUnqual
+ * @run main/othervm -Xbootclasspath/a:. ExpUnqual
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+public class ExpUnqual {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported unqualifiedly
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported unqualifiedly.");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ExpUnqual test = new ExpUnqual();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java
new file mode 100644
index 0000000..cb09a53
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test if package p2 in module m2 is exported to all unnamed,
+ *          then class p1.c1 in an unnamed module can read p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @compile -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED ExportAllUnnamed.java
+ * @run main/othervm -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED -Xbootclasspath/a:. ExportAllUnnamed
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+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.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported unqualifiedly
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2
+// Access allowed, an unnamed module can read all modules and p2 in module
+//           m2 is exported to all unnamed modules.
+
+public class ExportAllUnnamed {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported unqualifiedly
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        Class p2_c2_class = MySameClassLoader.loader1.loadClass("p2.c2");
+        Module m2 = p2_c2_class.getModule();
+
+        // Export m2/p2 to all unnamed modules.
+        jdk.internal.module.Modules.addExportsToAllUnnamed(m2, "p2");
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, unnamed module failed to access public type p2.c2 " +
+                                       "that was exported to all unnamed");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ExportAllUnnamed test = new ExportAllUnnamed();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/ModuleLibrary.java b/hotspot/test/runtime/modules/AccessCheck/ModuleLibrary.java
new file mode 100644
index 0000000..54872b9
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/ModuleLibrary.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleReader;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * A container of modules that acts as a ModuleFinder for testing
+ * purposes.
+ */
+
+class ModuleLibrary implements ModuleFinder {
+    private final Map<String, ModuleReference> namesToReference = new HashMap<>();
+
+    private ModuleLibrary() { }
+
+    void add(ModuleDescriptor... descriptors) {
+        for (ModuleDescriptor descriptor: descriptors) {
+            String name = descriptor.name();
+            if (!namesToReference.containsKey(name)) {
+                //modules.add(descriptor);
+
+                URI uri = URI.create("module:/" + descriptor.name());
+
+                Supplier<ModuleReader> supplier = () -> {
+                    throw new UnsupportedOperationException();
+                };
+
+                ModuleReference mref = new ModuleReference(descriptor, uri, supplier);
+
+                namesToReference.put(name, mref);
+            }
+        }
+    }
+
+    static ModuleLibrary of(ModuleDescriptor... descriptors) {
+        ModuleLibrary ml = new ModuleLibrary();
+        ml.add(descriptors);
+        return ml;
+    }
+
+    @Override
+    public Optional<ModuleReference> find(String name) {
+        return Optional.ofNullable(namesToReference.get(name));
+    }
+
+    @Override
+    public Set<ModuleReference> findAll() {
+        return new HashSet<>(namesToReference.values());
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java
new file mode 100644
index 0000000..b8a5617
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java
@@ -0,0 +1,123 @@
+/*
+ * 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
+ * @summary Test that if module m1 can read module m2, but package p2 in m2 is not
+ *          exported, then class p1.c1 in m1 can not read p2.c2 in m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build PkgNotExp
+ * @run main/othervm -Xbootclasspath/a:. PkgNotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+//                  defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is not exported
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access denied since p2 is not exported.
+//
+public class PkgNotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 and m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      PkgNotExp test = new PkgNotExp();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod.java b/hotspot/test/runtime/modules/AccessCheck/Umod.java
new file mode 100644
index 0000000..639891b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod.java
@@ -0,0 +1,221 @@
+/*
+ * 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
+ * @summary class p1.c1 defined in m1 tries to access p2.c2 defined in unnamed module.
+ * @library /testlibrary /test/lib
+ * @modules java.base/jdk.internal.module
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @compile p1/c1ReadEdge.java
+ * @compile p1/c1Loose.java
+ * @build Umod
+ * @run main/othervm -Xbootclasspath/a:. Umod
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Module;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+//                  package p1 in m1 is exported unqualifiedly
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in
+// in unnamed module.
+//
+// Three access attempts occur in this test:
+//   1. The first access is not allowed because a strict module
+//      cannot read an unnamed module.
+//   2. In this scenario a strict module establishes readability
+//      to the particular unnamed module it is trying to access.
+//      Access is allowed.
+//   3. Module m1 in the test_looseModuleLayer() method
+//      is transitioned to a loose module, access
+//      to all unnamed modules is allowed.
+//
+public class Umod {
+
+ // Create Layers over the boot layer to test different
+ // accessing scenarios of a named module to an unnamed module.
+
+ // Module m1 is a strict module and has not established
+ // readability to an unnamed module that p2.c2 is defined in.
+ public void test_strictModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader.
+     MySameClassLoader loader = new MySameClassLoader();
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", loader);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == loader);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1
+     Class p1_c1_class = loader.loadClass("p1.c1");
+
+     // Attempt access
+     try {
+         p1_c1_class.newInstance();
+         throw new RuntimeException("Test Failed, strict module m1, type p1.c1, should not be able " +
+                                    "to access public type p2.c2 defined in unnamed module");
+     } catch (IllegalAccessError e) {
+     }
+ }
+
+ // Module m1 is a strict module and has established
+ // readability to an unnamed module that p2.c2 is defined in.
+ public void test_strictModuleUnnamedReadableLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MySameClassLoader loader = new MySameClassLoader();
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", loader);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == loader);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1ReadEdge
+     Class p1_c1_class = loader.loadClass("p1.c1ReadEdge");
+
+     try {
+       // Read edge between m1 and the unnamed module that loads p2.c2 is established in
+       // c1ReadEdge's ctor before attempting access.
+       p1_c1_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, strict module m1, type p1.c1ReadEdge, should be able to acccess public type " +
+                                    "p2.c2 defined in unnamed module: " + e.getMessage());
+     }
+}
+
+ // Module m1 is a loose module and thus can read all unnamed modules.
+ public void test_looseModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p1
+     // Packages exported: p1 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p1")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MySameClassLoader loader = new MySameClassLoader();
+     // map module m1 to class loader.
+     // class c2 will be loaded in an unnamed module/loader.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", loader);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == loader);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p1.c1Loose
+     Class p1_c1_class = loader.loadClass("p1.c1Loose");
+
+     // change m1 to be a loose module
+     Module m1 = layer.findModule("m1").get();
+     jdk.internal.module.Modules.addReads(m1, null);
+
+     try {
+         p1_c1_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, strict module m1, type p1.c1Loose, should be able to acccess public type " +
+                                    "p2.c2 defined in unnamed module: " + e.getMessage());
+     }
+ }
+
+ public static void main(String args[]) throws Throwable {
+   Umod test = new Umod();
+   test.test_strictModuleLayer();                // access denied
+   test.test_strictModuleUnnamedReadableLayer(); // access allowed
+   test.test_looseModuleLayer();                 // access allowed
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java
new file mode 100644
index 0000000..34ea50f
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java
@@ -0,0 +1,127 @@
+/*
+ * 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
+ * @summary class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2.
+ *          Access is denied, since an unnamed module can read all modules but p2 in module
+ *          m2 is exported specifically to module m1, not to all modules.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build UmodDiffCL_ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. UmodDiffCL_ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is not exported
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2
+// Access denied, an unnamed module can read all modules but p2 in module
+//             m2 is exported specifically to module m1 not to all modules.
+//
+public class UmodDiffCL_ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        // NOTE: module m1 does not define a package named p1.
+        //       p1 will be loaded in an unnamed module.
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m1, not unqualifiedly");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodDiffCL_ExpQualOther test = new UmodDiffCL_ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java
new file mode 100644
index 0000000..52d253b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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
+ * @summary class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2.
+ *          Access allowed, an unnamed module can read all modules and p2 in module m2
+ *          which is exported unqualifiedly.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build UmodDiffCL_ExpUnqual
+ * @run main/othervm -Xbootclasspath/a:. UmodDiffCL_ExpUnqual
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported unqualifiedly.
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2
+// Access allowed, an unnamed module can read all modules and p2 in module
+//              m2 which is exported unqualifiedly.
+//
+public class UmodDiffCL_ExpUnqual {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // NOTE: module m1 does not define a package named p1.
+        //       p1 will be loaded in an unnamed module.
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, p1.c1 defined in unnamed module can access p2.c2 in module m2");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodDiffCL_ExpUnqual test = new UmodDiffCL_ExpUnqual();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java
new file mode 100644
index 0000000..ebe3e5d
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary class p1.c1 defined in unnamed module tries to access p2.c2 defined in m2.
+ *          Access is denied since even though unnamed module can read all modules, p2
+ *          in module m2 is not exported at all.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p1/c1.java
+ * @build UmodDiffCL_PkgNotExp
+ * @run main/othervm -Xbootclasspath/a:. UmodDiffCL_PkgNotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+// ClassLoader2 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is not exported
+//
+// class p1.c1 defined in unnamed module tries to access p2.c2 defined in m2
+// Access denied since even though unnamed module can read all modules, p2
+// in module m2 is not exported at all.
+//
+public class UmodDiffCL_PkgNotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        // NOTE: module m1 does not define a package named p1.
+        //       p1 will be loaded in an unnamed module.
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported to an unnamed module)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodDiffCL_PkgNotExp test = new UmodDiffCL_PkgNotExp();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_Umod.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_Umod.java
new file mode 100644
index 0000000..6fd2679
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_Umod.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary class p1.c1 defined in an unnamed module tries to access p2.c2
+ *          defined in an unnamed module. Access allowed since unnamed module
+ *          can read unnamed module even when class p1.c1 is loaded by
+ *          a different loader than p2.c2.
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build UmodDiffCL_Umod
+ * @run main/othervm -Xbootclasspath/a:. UmodDiffCL_Umod
+ */
+
+import myloaders.MyDiffClassLoader;
+
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in
+// in an unnamed module.
+// Access allowed since unnamed module can read unnamed module even when
+//                class p1.c1 is loaded by a different loader than p2.c2
+//                and all packages in an unnamed module are exported unqualifiedly.
+public class UmodDiffCL_Umod {
+
+    public static void main(String args[]) throws Throwable {
+        Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, unnamed module can access unnamed module");
+        }
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_UmodUpkg.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_UmodUpkg.java
new file mode 100644
index 0000000..909ab0f
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_UmodUpkg.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary class p3.c3 defined in a named package in an unnamed module tries to access c4
+ *          defined in an unnamed package in an unnamed module.  Access allowed since
+ *          any class in an unnamed module can read an unnamed module.
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile c4.java
+ * @compile p3/c3.jcod
+ * @build UmodDiffCL_UmodUpkg
+ * @run main/othervm -Xbootclasspath/a:. UmodDiffCL_UmodUpkg
+ */
+
+import myloaders.MyDiffClassLoader;
+
+public class UmodDiffCL_UmodUpkg {
+
+    public void testAccess() throws Throwable {
+
+        Class p3_c3_class = MyDiffClassLoader.loader1.loadClass("p3.c3");
+        try {
+            p3_c3_class.newInstance();
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+              throw new RuntimeException("Test Failed, public type c3 defined in an unnamed module " +
+                                         "should be able to access public type c4 defined in an unnamed module");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodDiffCL_UmodUpkg test = new UmodDiffCL_UmodUpkg();
+      test.testAccess();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java
new file mode 100644
index 0000000..97f781c
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java
@@ -0,0 +1,167 @@
+/*
+ * 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
+ * @summary class p3.c3 defined in module m1 tries to access c4 defined in unnamed module.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile c4.java
+ * @compile p3/c3.jcod
+ * @compile p3/c3ReadEdge.jcod
+ * @build UmodUPkg
+ * @run main/othervm -Xbootclasspath/a:. UmodUPkg
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+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.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> packages p3
+//                  package p3 in m1 is exported unqualifiedly
+//
+// class p3.c3 defined in m1 tries to access c4 defined in
+// in unnamed module.
+//
+// Two access attempts occur in this test:
+//   1. The first access is not allowed because a strict module
+//      cannot read an unnamed module.
+//   2. In this scenario a strict module establishes readability
+//      to the particular unnamed module it is trying to access.
+//      Access is allowed.
+//
+public class UmodUPkg {
+
+ // Create Layers over the boot layer to test different
+ // accessing scenarios of a named module to an unnamed module.
+
+ // Module m1 is a strict module and has not established
+ // readability to an unnamed module that c4 is defined in.
+ public void test_strictModuleLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p3
+     // Packages exported: p3 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p3")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     // map module m1 to class loader.
+     // class c4 will be loaded in an unnamed module/loader.
+     MySameClassLoader loader = new MySameClassLoader();
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", loader);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == loader);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p3.c3
+     Class p3_c3_class = loader.loadClass("p3.c3");
+
+     // Attempt access
+     try {
+         p3_c3_class.newInstance();
+         throw new RuntimeException("Test Failed, strict module m1, type p3.c3, should not be able to access " +
+                                    "public type c4 defined in unnamed module");
+     } catch (IllegalAccessError e) {
+     }
+ }
+
+ // Module m1 is a strict module and has established
+ // readability to an unnamed module that c4 is defined in.
+ public void test_strictModuleUnnamedReadableLayer() throws Throwable {
+
+     // Define module:     m1
+     // Can read:          java.base
+     // Packages:          p3
+     // Packages exported: p3 is exported unqualifiedly
+     ModuleDescriptor descriptor_m1 =
+             new ModuleDescriptor.Builder("m1")
+                     .requires("java.base")
+                     .exports("p3")
+                     .build();
+
+     // Set up a ModuleFinder containing all modules for this layer.
+     ModuleFinder finder = ModuleLibrary.of(descriptor_m1);
+
+     // Resolves "m1"
+     Configuration cf = Layer.boot()
+             .configuration()
+             .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+     MySameClassLoader loader = new MySameClassLoader();
+     // map module m1 to class loader.
+     // class c4 will be loaded in an unnamed module/loader.
+     Map<String, ClassLoader> map = new HashMap<>();
+     map.put("m1", loader);
+
+     // Create Layer that contains m1
+     Layer layer = Layer.boot().defineModules(cf, map::get);
+
+     assertTrue(layer.findLoader("m1") == loader);
+     assertTrue(layer.findLoader("java.base") == null);
+
+     // now use the same loader to load class p3.c3ReadEdge
+     Class p3_c3_class = loader.loadClass("p3.c3ReadEdge");
+
+     try {
+        // Read edge between m1 and the unnamed module that loads c4 is established in
+        // c3ReadEdge's ctor before attempting access.
+        p3_c3_class.newInstance();
+     } catch (IllegalAccessError e) {
+         throw new RuntimeException("Test Failed, module m1, type p3.c3ReadEdge, has established readability to " +
+                                    "c4 loader's unnamed module, access should be allowed: " + e.getMessage());
+     }
+ }
+
+ public static void main(String args[]) throws Throwable {
+   UmodUPkg test = new UmodUPkg();
+   test.test_strictModuleLayer();                // access denied
+   test.test_strictModuleUnnamedReadableLayer(); // access allowed
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java
new file mode 100644
index 0000000..299a41f
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * @summary class c5 defined in an unnamed module tries to access p6.c6 defined in m2.
+ *          Access is denied, since an unnamed module can read all modules but p6 in module
+ *          m2 is exported specifically to module m1, not to all modules.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkgDiffCL_ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkgDiffCL_ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+// ClassLoader2 --> defines m2 --> packages p6
+//
+// m1 can read m2
+// package p6 in m2 is not exported
+//
+// class c5 defined in an unnamed module tries to access p6.c6 defined in m2
+// Access denied, an unnamed module can read all modules but p6 in module
+//             m2 is exported specifically to module m1 not to all modules.
+//
+public class UmodUpkgDiffCL_ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p6
+        // Packages exported: p6 exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p6", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class c5
+        Class c5_class = MyDiffClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p6 in m2 is exported to m1, not unqualifiedly");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkgDiffCL_ExpQualOther test = new UmodUpkgDiffCL_ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java
new file mode 100644
index 0000000..9210c29
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java
@@ -0,0 +1,127 @@
+/*
+ * 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
+ * @summary class c5 in an unnamed module can read module m2, but package p6 in module m2 is not exported.
+ *          Access denied since even though unnamed module can read all modules, p6 in module m2 is not exported at all.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkgDiffCL_NotExp
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkgDiffCL_NotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MyDiffClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+// ClassLoader2 --> defines m2 --> packages p6
+//
+// m1 can read m2
+// package p6 in m2 is not exported
+//
+// class c5 defined in unnamed module tries to access p6.c6 defined in m2
+// Access denied since even though unnamed module can read all modules, p6
+// in module m2 is not exported at all.
+//
+public class UmodUpkgDiffCL_NotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p6
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p6")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MyDiffClassLoader.loader1);
+        map.put("m2", MyDiffClassLoader.loader2);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MyDiffClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MyDiffClassLoader.loader2);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class c5
+        // NOTE: module m1 does not define any packages.
+        //       c5 will be loaded in an unnamed module.
+        Class c5_class = MyDiffClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p6 in m2 is not exported to " +
+                                       "an unnamed module that c5 is defined within)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkgDiffCL_NotExp test = new UmodUpkgDiffCL_NotExp();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_Umod.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_Umod.java
new file mode 100644
index 0000000..5973895
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_Umod.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test public type c5 defined in an unnamed package and unnamed module can
+ *          access public type p6.c6 defined in an unnamed module.
+ * @compile myloaders/MyDiffClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkgDiffCL_Umod
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkgDiffCL_Umod
+ */
+
+import myloaders.MyDiffClassLoader;
+
+public class UmodUpkgDiffCL_Umod {
+
+    public void testAccess() throws Throwable {
+
+        Class c5_class = MyDiffClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+              throw new RuntimeException("Test Failed, public type c5 defined in an unnamed package and unnamed "
+                      + "module should be able to access public type p6.c6 defined in an unnamed module");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkgDiffCL_Umod test = new UmodUpkgDiffCL_Umod();
+      test.testAccess();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java
new file mode 100644
index 0000000..1084294
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * @summary Test that if class c5 in an unnamed module can read package p6 in module m2, but package p6 in module m2 is
+ *          exported qualifiedly to module m3, then class c5 in an unnamed module can not read p6.c6 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkg_ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkg_ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p6
+//                  defines m3 --> packages p3
+//
+// m1 can read m2
+// package p6 in m2 is exported to m3
+//
+// class c5 defined in m1 tries to access p6.c6 defined in m2
+// Access denied since although m1 can read m2, p6 is exported only to m3.
+//
+public class UmodUpkg_ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1 (need to define m1 to establish the Layer successfully)
+        // Can read:          java.base, m2, m3
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .requires("m3")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p6
+        // Packages exported: p6 is exported to m3
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p6", "m3")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+        map.put("m3", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1, m2 and m3
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m3") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class c5
+        Class c5_class = MySameClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p6 in m2 is exported to m3, not unqualifiedly to everyone)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkg_ExpQualOther test = new UmodUpkg_ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java
new file mode 100644
index 0000000..8ee6e92
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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
+ * @summary Test if package p6 in module m2 is not exported, then class c5
+ *          in an unnamed module can not access p6.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkg_NotExp
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkg_NotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p6
+//
+// m1 can read m2
+// package p6 in m2 is not exported
+//
+// class c5 defined in an unnamed module tries to access p6.c2 defined in m2
+// Access denied since p6 is not exported.
+//
+public class UmodUpkg_NotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p6
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p6")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 and m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class c5
+        Class c5_class = MySameClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p6 in m2 is not exported)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkg_NotExp test = new UmodUpkg_NotExp();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_Umod.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_Umod.java
new file mode 100644
index 0000000..7a96e5c
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_Umod.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test public type c5 defined in an unnamed package and unnamed module can
+ *          access public type p6.c6 defined in an unnamed module.
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p6/c6.java
+ * @compile c5.java
+ * @build UmodUpkg_Umod
+ * @run main/othervm -Xbootclasspath/a:. UmodUpkg_Umod
+ */
+
+import myloaders.MySameClassLoader;
+
+public class UmodUpkg_Umod {
+
+    public void testAccess() throws Throwable {
+
+        Class c5_class = MySameClassLoader.loader1.loadClass("c5");
+        try {
+            c5_class.newInstance();
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+              throw new RuntimeException("Test Failed, public type c5 defined in an unnamed package and unnamed "
+                      + "module should be able to access public type c6 defined in an unnamed module");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      UmodUpkg_Umod test = new UmodUpkg_Umod();
+      test.testAccess();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java
new file mode 100644
index 0000000..fe2fb7b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * @summary Test that if package p2 in module m2 is exported to module m3,
+ *          then class p1.c1 in an unnamed module can not read p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build Umod_ExpQualOther
+ * @run main/othervm -Xbootclasspath/a:. Umod_ExpQualOther
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p2
+//                  defines m3 --> packages p3
+//
+// m1 can read m2
+// package p2 in m2 is exported to m3
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access denied since although m1 can read m2, p2 is exported only to m3.
+//
+public class Umod_ExpQualOther {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1 (need to define m1 to establish the Layer successfully)
+        // Can read:          java.base, m2, m3
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .requires("m3")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported to m3
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m3")
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+        map.put("m3", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1, m2 and m3
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m3") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is exported to m3, not unqualifiedly to everyone)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      Umod_ExpQualOther test = new Umod_ExpQualOther();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java
new file mode 100644
index 0000000..445713c
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java
@@ -0,0 +1,121 @@
+/*
+ * 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
+ * @summary Test if package p2 in module m2 is exported unqualifiedly,
+ *          then class p1.c1 in an unnamed module can read p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build Umod_ExpUnqual
+ * @run main/othervm -Xbootclasspath/a:. Umod_ExpUnqual
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported unqualifiedly
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2
+// Access allowed, an unnamed module can read all modules and p2 in module
+//           m2 which is exported unqualifiedly.
+
+public class Umod_ExpUnqual {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: p2 is exported unqualifiedly
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to differing class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an unnamed module can access public type " +
+                                       "p2.c2 since it is exported unqualifiedly");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      Umod_ExpUnqual test = new Umod_ExpUnqual();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java
new file mode 100644
index 0000000..7a346cf
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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
+ * @summary Test if package p2 in module m2 is not exported, then class p1.c1
+ *          in an unnamed module can not access p2.c2 in module m2.
+ * @library /testlibrary /test/lib
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build Umod_PkgNotExp
+ * @run main/othervm -Xbootclasspath/a:. Umod_PkgNotExp
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+// ClassLoader1 --> defines m1 --> no packages
+//                  defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is not exported
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in m2
+// Access denied since p2 is not exported.
+//
+public class Umod_PkgNotExp {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          none
+        // Packages exported: none
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: none
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .conceals("p2")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.empty(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", MySameClassLoader.loader1);
+        map.put("m2", MySameClassLoader.loader1);
+
+        // Create Layer that contains m1 and m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+
+        assertTrue(layer.findLoader("m1") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("m2") == MySameClassLoader.loader1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported)");
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+          if (!e.getMessage().contains("does not export")) {
+              throw new RuntimeException("Wrong message: " + e.getMessage());
+          }
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      Umod_PkgNotExp test = new Umod_PkgNotExp();
+      test.createLayerOnBoot();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_UmodUpkg.java b/hotspot/test/runtime/modules/AccessCheck/Umod_UmodUpkg.java
new file mode 100644
index 0000000..23abc1e
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_UmodUpkg.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary class p3.c3 defined in an unnamed module tries to access c4 defined in an unnamed package
+ *          and an unnamed module.
+ *          Access allowed since any class in an unnamed module can read an unnamed module.
+ * @compile myloaders/MySameClassLoader.java
+ * @compile c4.java
+ * @compile p3/c3.jcod
+ * @build Umod_UmodUpkg
+ * @run main/othervm -Xbootclasspath/a:. Umod_UmodUpkg
+ */
+
+import myloaders.MySameClassLoader;
+
+public class Umod_UmodUpkg {
+
+    public void testAccess() throws Throwable {
+
+        Class p3_c3_class = MySameClassLoader.loader1.loadClass("p3.c3");
+        try {
+            p3_c3_class.newInstance();
+        } catch (IllegalAccessError e) {
+          System.out.println(e.getMessage());
+              throw new RuntimeException("Test Failed, public type c3 defined in an unnamed module should be able " +
+                                         "to access public type c4 defined in an unnamed module");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      Umod_UmodUpkg test = new Umod_UmodUpkg();
+      test.testAccess();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/c4.java b/hotspot/test/runtime/modules/AccessCheck/c4.java
new file mode 100644
index 0000000..f2840b6
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/c4.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck* tests.
+
+public class c4 {
+    public void method4() { }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/c5.java b/hotspot/test/runtime/modules/AccessCheck/c5.java
new file mode 100644
index 0000000..1a3c25a
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/c5.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+import p6.c6;
+
+public class c5 {
+
+    public c5 () {
+        p6.c6 c6_obj = new p6.c6();
+        c6_obj.method6();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/myloaders/MyDiffClassLoader.java b/hotspot/test/runtime/modules/AccessCheck/myloaders/MyDiffClassLoader.java
new file mode 100644
index 0000000..6362759
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/myloaders/MyDiffClassLoader.java
@@ -0,0 +1,72 @@
+/*
+ * 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 myloaders;
+
+import java.io.*;
+import java.lang.module.ModuleReference;
+
+// Declare a MyDiffClassLoader class to be used to map modules to.
+// This class loader will also be used to load classes within modules.
+public class MyDiffClassLoader extends ClassLoader
+{
+    public static MyDiffClassLoader loader1 = new MyDiffClassLoader();
+    public static MyDiffClassLoader loader2 = new MyDiffClassLoader();
+
+    public Class loadClass(String name) throws ClassNotFoundException {
+        if (!name.equals("p1.c1") &&
+            !name.equals("p1.c1ReadEdgeDiffLoader") &&
+            !name.equals("p1.c1Loose") &&
+            !name.equals("p2.c2") &&
+            !name.equals("p3.c3") &&
+            !name.equals("p3.c3ReadEdgeDiffLoader") &&
+            !name.equals("c4") &&
+            !name.equals("c5") &&
+            !name.equals("p6.c6")) {
+            return super.loadClass(name);
+        }
+        if ((name.equals("p2.c2") || name.equals("c4") || name.equals("p6.c6")) &&
+            (this == MyDiffClassLoader.loader1)) {
+            return MyDiffClassLoader.loader2.loadClass(name);
+        }
+
+        byte[] data = getClassData(name);
+        return defineClass(name, data, 0, data.length);
+    }
+    byte[] getClassData(String name) {
+        try {
+           String TempName = name.replaceAll("\\.", "/");
+           String currentDir = System.getProperty("test.classes");
+           String filename = currentDir + File.separator + TempName + ".class";
+           FileInputStream fis = new FileInputStream(filename);
+           byte[] b = new byte[5000];
+           int cnt = fis.read(b, 0, 5000);
+           byte[] c = new byte[cnt];
+           for (int i=0; i<cnt; i++) c[i] = b[i];
+              return c;
+        } catch (IOException e) {
+           return null;
+        }
+    }
+
+    public void register(ModuleReference mref) { }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/myloaders/MySameClassLoader.java b/hotspot/test/runtime/modules/AccessCheck/myloaders/MySameClassLoader.java
new file mode 100644
index 0000000..bc13e6b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/myloaders/MySameClassLoader.java
@@ -0,0 +1,68 @@
+/*
+ * 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 myloaders;
+
+import java.io.*;
+import java.lang.module.ModuleReference;
+
+// Declare a MySameClassLoader class to be used to map modules to the same
+// class loader.  This class loader will also be used to load classes
+// within modules.
+public class MySameClassLoader extends ClassLoader
+{
+    public static MySameClassLoader loader1 = new MySameClassLoader();
+
+    public Class loadClass(String name) throws ClassNotFoundException {
+        // override all classloaders
+        if (!name.equals("p1.c1") &&
+            !name.equals("p1.c1ReadEdge") &&
+            !name.equals("p1.c1Loose") &&
+            !name.equals("p2.c2") &&
+            !name.equals("p3.c3") &&
+            !name.equals("p3.c3ReadEdge") &&
+            !name.equals("c4") &&
+            !name.equals("c5") &&
+            !name.equals("p6.c6")) {
+            return super.loadClass(name);
+        }
+        byte[] data = getClassData(name);
+        return defineClass(name, data, 0, data.length);
+    }
+    byte[] getClassData(String name) {
+        try {
+           String TempName = name.replaceAll("\\.", "/");
+           String currentDir = System.getProperty("test.classes");
+           String filename = currentDir + File.separator + TempName + ".class";
+           FileInputStream fis = new FileInputStream(filename);
+           byte[] b = new byte[5000];
+           int cnt = fis.read(b, 0, 5000);
+           byte[] c = new byte[cnt];
+           for (int i=0; i<cnt; i++) c[i] = b[i];
+              return c;
+        } catch (IOException e) {
+           return null;
+        }
+    }
+
+    public void register(ModuleReference mref) { }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p1/c1.java b/hotspot/test/runtime/modules/AccessCheck/p1/c1.java
new file mode 100644
index 0000000..fbe692a
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p1/c1.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+
+package p1;
+
+import p2.c2;
+
+public class c1 {
+
+    public c1 () {
+        p2.c2 c2_obj = new p2.c2();
+        c2_obj.method2();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p1/c1Loose.java b/hotspot/test/runtime/modules/AccessCheck/p1/c1Loose.java
new file mode 100644
index 0000000..3722927
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p1/c1Loose.java
@@ -0,0 +1,33 @@
+/*
+ * 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 p1;
+
+import p2.c2;
+
+public class c1Loose {
+    public c1Loose() {
+        // Attempt access - access should succeed since m1 is a loose module
+        p2.c2 c2_obj = new p2.c2();
+        c2_obj.method2();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdge.java b/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdge.java
new file mode 100644
index 0000000..55d4a8b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdge.java
@@ -0,0 +1,41 @@
+/*
+ * 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 p1;
+
+import java.lang.reflect.*;
+import p2.c2;
+
+public class c1ReadEdge {
+    public c1ReadEdge() {
+        // Establish read edge from module m1, where c1ReadEdge is defined,
+        // to the unnamed module, where p2.c2 will be defined.
+        Module m1 = c1ReadEdge.class.getModule();
+        ClassLoader loader = c1ReadEdge.class.getClassLoader();
+        Module unnamed_module = loader.getUnnamedModule();
+        m1.addReads(unnamed_module);
+
+        // Attempt access - access should succeed
+        p2.c2 c2_obj = new p2.c2();
+        c2_obj.method2();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdgeDiffLoader.java b/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdgeDiffLoader.java
new file mode 100644
index 0000000..daaee58
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p1/c1ReadEdgeDiffLoader.java
@@ -0,0 +1,61 @@
+/*
+ * 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 p1;
+
+import java.lang.reflect.*;
+import myloaders.MyDiffClassLoader;
+import p2.c2;
+
+public class c1ReadEdgeDiffLoader {
+    public c1ReadEdgeDiffLoader() {
+        // The goal is to establish a read edge between module m1
+        // which is the module where p1.c1ReadEdgeDiffLoader is defined,
+        // and the unnamed module that defines p2.c2.  This must be
+        // done in 2 steps:
+        //
+        // Step #1: Establish a read edge between m1, where c1ReadEdgeDiffLoader
+        //          is defined, and the System ClassLoader's unnamed module,
+        //          where MyDiffClassLoader is defined. This read edge
+        //          is needed before we can obtain MyDiffClassLoader.loader2's unnamed module.
+        //
+        // Step #2: Establish a read edge between m1, where c1ReadEdgeDiffLoader
+        //          is defined, and the MyDiffClassLoader.loader2's unnamed module,
+        //          where p2.c2 will be defined.
+
+        // Step #1: read edge m1 -> System ClassLoader's unnamed module
+        Module m1 = c1ReadEdgeDiffLoader.class.getModule();
+        ClassLoader system_loader = ClassLoader.getSystemClassLoader();
+        Module unnamed_module1 = system_loader.getUnnamedModule();
+        m1.addReads(unnamed_module1);
+
+        // Step #2: read edge m1 -> MyDiffClassLoader.loader2's unnamed module
+        ClassLoader loader2 = MyDiffClassLoader.loader2;
+        Module unnamed_module2 = loader2.getUnnamedModule();
+        m1.addReads(unnamed_module2);
+
+        // Attempt access - access should succeed since m1 can read
+        //                  MyDiffClassLoader.loader2's unnamed module
+        p2.c2 c2_obj = new p2.c2();
+        c2_obj.method2();
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p2/c2.java b/hotspot/test/runtime/modules/AccessCheck/p2/c2.java
new file mode 100644
index 0000000..3d21e32
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p2/c2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+
+package p2;
+
+public class c2 {
+    public void method2() { }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p3/c3.jcod b/hotspot/test/runtime/modules/AccessCheck/p3/c3.jcod
new file mode 100644
index 0000000..10c97a7
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p3/c3.jcod
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/* Small class used by multiple hotspot/runtime/modules/AccessCheck* tests.
+ * package p3;
+ *
+ * public class c3 {
+ *
+ *     public c3 () {
+ *         c4 c4_obj = new c4();
+ *         c4_obj.method4();
+ *     }
+ * }
+ */
+
+class p3/c3 {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [19] { // Constant Pool
+    ; // first element is empty
+    Method #6 #13; // #1     at 0x0A
+    class #14; // #2     at 0x0F
+    Method #2 #13; // #3     at 0x12
+    Method #2 #15; // #4     at 0x17
+    class #16; // #5     at 0x1C
+    class #17; // #6     at 0x1F
+    Utf8 "<init>"; // #7     at 0x22
+    Utf8 "()V"; // #8     at 0x2B
+    Utf8 "Code"; // #9     at 0x31
+    Utf8 "LineNumberTable"; // #10     at 0x38
+    Utf8 "SourceFile"; // #11     at 0x4A
+    Utf8 "c3.java"; // #12     at 0x57
+    NameAndType #7 #8; // #13     at 0x61
+    Utf8 "c4"; // #14     at 0x66
+    NameAndType #18 #8; // #15     at 0x6E
+    Utf8 "p3/c3"; // #16     at 0x73
+    Utf8 "java/lang/Object"; // #17     at 0x7B
+    Utf8 "method4"; // #18     at 0x8E
+  } // Constant Pool
+
+  0x0021; // access
+  #5;// this_cpx
+  #6;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0xA4
+      0x0001; // access
+      #7; // name_cpx
+      #8; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 53) { // Code at 0xAC
+          2; // max_stack
+          2; // max_locals
+          Bytes[17]{
+            0x2AB70001BB000259;
+            0xB700034C2BB60004;
+            0xB1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 18) { // LineNumberTable at 0xCF
+              [4] { // LineNumberTable
+                0  4; //  at 0xDB
+                4  5; //  at 0xDF
+                12  6; //  at 0xE3
+                16  7; //  at 0xE7
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#11, 2) { // SourceFile at 0xE9
+      #12;
+    } // end SourceFile
+  } // Attributes
+} // end class p3/c3
diff --git a/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdge.jcod b/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdge.jcod
new file mode 100644
index 0000000..50df618
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdge.jcod
@@ -0,0 +1,142 @@
+/*
+ * 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.lang.reflect.*;
+ * public class c3ReadEdge {
+ *    public c3ReadEdge() {
+ *       // Establish read edge from module m1, where c3ReadEdge is defined,
+ *       // to the unnamed module, where c4 will be defined.
+ *       Module m1 = c3ReadEdge.class.getModule();
+ *       ClassLoader loader = c3ReadEdge.class.getClassLoader();
+ *       Module unnamed_module = loader.getUnnamedModule();
+ *       m1.addReads(unnamed_module);
+ *       // Attempt access - access should succeed
+ *       c4 c4_obj = new c4();
+ *       c4_obj.method4();
+ *   }
+ * }
+ */
+
+class p3/c3ReadEdge {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [40] { // Constant Pool
+    ; // first element is empty
+    Method #10 #17; // #1     at 0x0A
+    class #18; // #2     at 0x0F
+    Method #19 #20; // #3     at 0x12
+    Method #19 #21; // #4     at 0x17
+    Method #22 #23; // #5     at 0x1C
+    Method #24 #25; // #6     at 0x21
+    class #26; // #7     at 0x26
+    Method #7 #17; // #8     at 0x29
+    Method #7 #27; // #9     at 0x2E
+    class #28; // #10     at 0x33
+    Utf8 "<init>"; // #11     at 0x36
+    Utf8 "()V"; // #12     at 0x3F
+    Utf8 "Code"; // #13     at 0x45
+    Utf8 "LineNumberTable"; // #14     at 0x4C
+    Utf8 "SourceFile"; // #15     at 0x5E
+    Utf8 "c3ReadEdge.java"; // #16     at 0x6B
+    NameAndType #11 #12; // #17     at 0x7D
+    Utf8 "p3/c3ReadEdge"; // #18     at 0x82
+    class #29; // #19     at 0x92
+    NameAndType #30 #31; // #20     at 0x95
+    NameAndType #32 #33; // #21     at 0x9A
+    class #34; // #22     at 0x9F
+    NameAndType #35 #31; // #23     at 0xA2
+    class #36; // #24     at 0xA7
+    NameAndType #37 #38; // #25     at 0xAA
+    Utf8 "c4"; // #26     at 0xAF
+    NameAndType #39 #12; // #27     at 0xB7
+    Utf8 "java/lang/Object"; // #28     at 0xBC
+    Utf8 "java/lang/Class"; // #29     at 0xCF
+    Utf8 "getModule"; // #30     at 0xE1
+    Utf8 "()Ljava/lang/reflect/Module;"; // #31     at 0xED
+    Utf8 "getClassLoader"; // #32     at 0x010C
+    Utf8 "()Ljava/lang/ClassLoader;"; // #33     at 0x011D
+    Utf8 "java/lang/ClassLoader"; // #34     at 0x0139
+    Utf8 "getUnnamedModule"; // #35     at 0x0151
+    Utf8 "java/lang/reflect/Module"; // #36     at 0x0164
+    Utf8 "addReads"; // #37     at 0x017F
+    Utf8 "(Ljava/lang/reflect/Module;)Ljava/lang/reflect/Module;"; // #38     at 0x018A
+    Utf8 "method4"; // #39     at 0x01C3
+  } // Constant Pool
+
+  0x0021; // access
+  #2;// this_cpx
+  #10;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0x01D9
+      0x0001; // access
+      #11; // name_cpx
+      #12; // sig_cpx
+      [1] { // Attributes
+        Attr(#13, 94) { // Code at 0x01E1
+          2; // max_stack
+          5; // max_locals
+          Bytes[42]{
+            0x2AB700011202B600;
+            0x034C1202B600044D;
+            0x2CB600054E2B2DB6;
+            0x000657BB000759B7;
+            0x00083A041904B600;
+            0x09B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#14, 34) { // LineNumberTable at 0x021D
+              [8] { // LineNumberTable
+                0  32; //  at 0x0229
+                4  38; //  at 0x022D
+                10  39; //  at 0x0231
+                16  40; //  at 0x0235
+                21  41; //  at 0x0239
+                27  44; //  at 0x023D
+                36  45; //  at 0x0241
+                41  46; //  at 0x0245
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#15, 2) { // SourceFile at 0x0247
+      #16;
+    } // end SourceFile
+  } // Attributes
+} // end class p3/c3ReadEdge
diff --git a/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdgeDiffLoader.jcod b/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdgeDiffLoader.jcod
new file mode 100644
index 0000000..103f7ee
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p3/c3ReadEdgeDiffLoader.jcod
@@ -0,0 +1,175 @@
+/*
+ * 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.lang.reflect.*;
+ * import myloaders.MyDiffClassLoader;
+ *
+ * public class c3ReadEdgeDiffLoader {
+ *    public c3ReadEdgeDiffLoader() {
+ *       // The goal is to establish a read edge between module m1
+ *       // which is the module where p3.c3ReadEdgeDiffLoader is defined,
+ *       // and the unnamed module that defines c4.  This must be
+ *       // done in 2 steps:
+ *       //
+ *       // Step #1: Establish a read edge between m1, where c3ReadEdgeDiffLoader
+ *       //          is defined, and the System ClassLoader's unnamed module,
+ *       //          where MyDiffClassLoader is defined. This read edge
+ *       //          is needed before we can obtain MyDiffClassLoader.loader2's unnamed module.
+ *       //
+ *       // Step #2: Establish a read edge between m1, where c3ReadEdgeDiffLoader
+ *       //          is defined, and the MyDiffClassLoader.loader2's unnamed module,
+ *       //          where c4 will be defined.
+ *
+ *       // Step #1: read edge m1 -> System ClassLoader's unnamed module
+ *       Module m1 = c3ReadEdgeDiffLoader.class.getModule();
+ *       ClassLoader system_loader = ClassLoader.getSystemClassLoader();
+ *       Module unnamed_module1 = system_loader.getUnnamedModule();
+ *       m1.addReads(unnamed_module1);
+ *
+ *       // Step #2: read edge m1 -> MyDiffClassLoader.loader2's unnamed module
+ *       ClassLoader loader2 = MyDiffClassLoader.loader2;
+ *       Module unnamed_module2 = loader2.getUnnamedModule();
+ *       m1.addReads(unnamed_module2);
+ *
+ *       // Attempt access - should succeed since m1 can read
+ *       //                  MyDiffClassLoader.loader2's unnamed module
+ *       c4 c4_obj = new c4();
+ *       c4_obj.method4();
+ *   }
+ * }
+ */
+
+class p3/c3ReadEdgeDiffLoader {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [46] { // Constant Pool
+    ; // first element is empty
+    Method #11 #18; // #1     at 0x0A
+    class #19; // #2     at 0x0F
+    Method #20 #21; // #3     at 0x12
+    Method #22 #23; // #4     at 0x17
+    Method #22 #24; // #5     at 0x1C
+    Method #25 #26; // #6     at 0x21
+    Field #27 #28; // #7     at 0x26
+    class #29; // #8     at 0x2B
+    Method #8 #18; // #9     at 0x2E
+    Method #8 #30; // #10     at 0x33
+    class #31; // #11     at 0x38
+    Utf8 "<init>"; // #12     at 0x3B
+    Utf8 "()V"; // #13     at 0x44
+    Utf8 "Code"; // #14     at 0x4A
+    Utf8 "LineNumberTable"; // #15     at 0x51
+    Utf8 "SourceFile"; // #16     at 0x63
+    Utf8 "c3ReadEdgeDiffLoader.java"; // #17     at 0x70
+    NameAndType #12 #13; // #18     at 0x8C
+    Utf8 "p3/c3ReadEdgeDiffLoader"; // #19     at 0x91
+    class #32; // #20     at 0xAB
+    NameAndType #33 #34; // #21     at 0xAE
+    class #35; // #22     at 0xB3
+    NameAndType #36 #37; // #23     at 0xB6
+    NameAndType #38 #34; // #24     at 0xBB
+    class #39; // #25     at 0xC0
+    NameAndType #40 #41; // #26     at 0xC3
+    class #42; // #27     at 0xC8
+    NameAndType #43 #44; // #28     at 0xCB
+    Utf8 "c4"; // #29     at 0xD0
+    NameAndType #45 #13; // #30     at 0xD8
+    Utf8 "java/lang/Object"; // #31     at 0xDD
+    Utf8 "java/lang/Class"; // #32     at 0xF0
+    Utf8 "getModule"; // #33     at 0x0102
+    Utf8 "()Ljava/lang/reflect/Module;"; // #34     at 0x010E
+    Utf8 "java/lang/ClassLoader"; // #35     at 0x012D
+    Utf8 "getSystemClassLoader"; // #36     at 0x0145
+    Utf8 "()Ljava/lang/ClassLoader;"; // #37     at 0x015C
+    Utf8 "getUnnamedModule"; // #38     at 0x0178
+    Utf8 "java/lang/reflect/Module"; // #39     at 0x018B
+    Utf8 "addReads"; // #40     at 0x01A6
+    Utf8 "(Ljava/lang/reflect/Module;)Ljava/lang/reflect/Module;"; // #41     at 0x01B1
+    Utf8 "myloaders/MyDiffClassLoader"; // #42     at 0x01EA
+    Utf8 "loader2"; // #43     at 0x0208
+    Utf8 "Lmyloaders/MyDiffClassLoader;"; // #44     at 0x0212
+    Utf8 "method4"; // #45     at 0x0232
+  } // Constant Pool
+
+  0x0021; // access
+  #2;// this_cpx
+  #11;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [1] { // methods
+    { // Member at 0x0248
+      0x0001; // access
+      #12; // name_cpx
+      #13; // sig_cpx
+      [1] { // Attributes
+        Attr(#14, 123) { // Code at 0x0250
+          2; // max_stack
+          7; // max_locals
+          Bytes[59]{
+            0x2AB700011202B600;
+            0x034CB800044D2CB6;
+            0x00054E2B2DB60006;
+            0x57B200073A041904;
+            0xB600053A052B1905;
+            0xB6000657BB000859;
+            0xB700093A061906B6;
+            0x000AB1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#15, 46) { // LineNumberTable at 0x029D
+              [11] { // LineNumberTable
+                0  33; //  at 0x02A9
+                4  34; //  at 0x02AD
+                10  36; //  at 0x02B1
+                14  37; //  at 0x02B5
+                19  39; //  at 0x02B9
+                25  41; //  at 0x02BD
+                30  42; //  at 0x02C1
+                37  46; //  at 0x02C5
+                44  49; //  at 0x02C9
+                53  50; //  at 0x02CD
+                58  51; //  at 0x02D1
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#16, 2) { // SourceFile at 0x02D3
+      #17;
+    } // end SourceFile
+  } // Attributes
+} // end class p3/c3ReadEdgeDiffLoader
diff --git a/hotspot/test/runtime/modules/AccessCheck/p6/c6.java b/hotspot/test/runtime/modules/AccessCheck/p6/c6.java
new file mode 100644
index 0000000..37c1161
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p6/c6.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+
+package p6;
+
+public class c6 {
+    public void method6() { }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheckAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheckAllUnnamed.java
new file mode 100644
index 0000000..a97f7cc
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckAllUnnamed.java
@@ -0,0 +1,117 @@
+/*
+ * 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.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+/*
+ * @test
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 AccessCheckAllUnnamed
+ */
+
+public class AccessCheckAllUnnamed {
+
+    // Test a series of error conditions for API JVM_AddModuleExportsToAllUnnamed
+    // and then test that a class in the unnamed module can access a package in a
+    // named module that has been exported to all unnamed modules.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for AccessCheckWorks and assume it's also used to
+        // load class p2.c2.
+        ClassLoader this_cldr = AccessCheckAllUnnamed.class.getClassLoader();
+
+        // Define a module for p3.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p3" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/there", new String[] { "p3" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        try {
+            ModuleHelper.AddModuleExportsToAllUnnamed((Module)null, "p2");
+            throw new RuntimeException("Failed to get the expected NPE for null module");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAllUnnamed(m2, null);
+            throw new RuntimeException("Failed to get the expected NPE for null package");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAllUnnamed(this_cldr, "p2");
+            throw new RuntimeException("Failed to get the expected IAE for bad module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAllUnnamed(m2, "p3");
+            throw new RuntimeException("Failed to get the expected IAE for package in other module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAllUnnamed(m2, "p4");
+            throw new RuntimeException("Failed to get the expected IAE for package not in module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export package p2 in m2 to allUnnamed.
+        ModuleHelper.AddModuleExportsToAllUnnamed(m2, "p2");
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should succeed because
+        // p1 is in an unnamed module and p2.c2 is exported to all unnamed modules.
+        Class p1_c1_class = Class.forName("p1.c1");
+        try {
+            Object c1_obj = p1_c1_class.newInstance();
+        } catch (IllegalAccessError f) {
+            throw new RuntimeException(
+                "Class in unnamed module could not access package p2 exported to all unnamed modules");
+        }
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccessCheckExp.java b/hotspot/test/runtime/modules/AccessCheckExp.java
new file mode 100644
index 0000000..304af7f
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckExp.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
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 AccessCheckExp
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class AccessCheckExp {
+
+    // Test that if module1 can read module2, but package p2 in module2 is not
+    // exported then class p1.c1 in module1 can not read p2.c2 in module2.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for AccessCheckExp and assume it's also used to
+        // load classes p1.c1 and p2.c2.
+        ClassLoader this_cldr = AccessCheckExp.class.getClassLoader();
+
+        // Define a module for p1.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p1" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/here", new String[] { "p1" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        // Make package p1 in m1 visible to everyone.
+        ModuleHelper.AddModuleExportsToAll(m1, "p1");
+
+        // p1.c1's ctor tries to call a method in p2.c2, but p2.c2 is not
+        // exported.  So should get IllegalAccessError.
+        ModuleHelper.AddReadsModule(m1, m2);
+
+        Class p1_c1_class = Class.forName("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported");
+        } catch (IllegalAccessError f) {
+            System.out.println(f.getMessage());
+            if (!f.getMessage().contains("does not export")) {
+                throw new RuntimeException("Wrong message: " + f.getMessage());
+            }
+        }
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccessCheckJavaBase.java b/hotspot/test/runtime/modules/AccessCheckJavaBase.java
new file mode 100644
index 0000000..764f9fb
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckJavaBase.java
@@ -0,0 +1,58 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @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 AccessCheckJavaBase
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class AccessCheckJavaBase {
+
+    // Test that a class defined to module2 always can read java.base.
+    public static void main(String args[]) throws Throwable {
+        // Get the class loader for AccessCheckJavaBase and assume it's also used to
+        // load class p2.c2.
+        ClassLoader this_cldr = AccessCheckJavaBase.class.getClassLoader();
+
+        // Define a module for p2.
+        Object m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+
+        // p2.c2 can read its superclass java.lang.Object defined within java.base
+        try {
+            Class p2_c2_class = Class.forName("p2.c2");
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed" + e.getMessage());
+        }
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheckRead.java b/hotspot/test/runtime/modules/AccessCheckRead.java
new file mode 100644
index 0000000..8158582
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckRead.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
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 AccessCheckRead
+ */
+
+import jdk.test.lib.*;
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class AccessCheckRead {
+
+    // Test that a class in a package in module1 cannot access a class in
+    // a package n module2 if module1 cannot read module2.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for AccessCheckRead and assume it's also used to
+        // load classes p1.c1 and p2.c2.
+        ClassLoader this_cldr = AccessCheckRead.class.getClassLoader();
+
+        // Define a module for p1.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p1" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/here", new String[] { "p1" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        // Make package p1 in m1 visible to everyone.
+        ModuleHelper.AddModuleExportsToAll(m1, "p1");
+
+        Class p1_c1_class = Class.forName("p1.c1");
+
+        // p1.c1's ctor tries to call a method in p2.c2, but p1's module
+        // cannot read p2's module.  So should get IllegalAccessError.
+        try {
+            p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (m1 can't read m2)");
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not read") ||
+                e.getMessage().contains("strict")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheckSuper.java b/hotspot/test/runtime/modules/AccessCheckSuper.java
new file mode 100644
index 0000000..bd2065b
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckSuper.java
@@ -0,0 +1,71 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p3/c3.java
+ * @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 AccessCheckSuper
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class AccessCheckSuper {
+
+    // Test that when a class cannot access its super class the message
+    // contains  both "superclass" text and module text.
+    public static void main(String args[]) throws Throwable {
+
+        // Get the class loader for AccessCheckSuper and assume it's also used to
+        // load class p2.c2 and class p3.c3.
+        ClassLoader this_cldr = AccessCheckSuper.class.getClassLoader();
+
+        // Define a module for p2.
+        Object m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+
+        // Define a module for p3.
+        Object m3 = ModuleHelper.ModuleObject("module3", this_cldr, new String[] { "p3" });
+        assertNotNull(m3, "Module should not be null");
+        ModuleHelper.DefineModule(m3, "9.0", "m3/there", new String[] { "p3" });
+
+        // Since a readability edge has not been established between module2
+        // and module3, p3.c3 cannot read its superclass p2.c2.
+        try {
+            Class p3_c3_class = Class.forName("p3.c3");
+            throw new RuntimeException("Failed to get IAE (can't read superclass)");
+        } catch (IllegalAccessError e) {
+            if (!e.getMessage().contains("superclass access check failed") ||
+                !e.getMessage().contains("does not read")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheckUnnamed.java b/hotspot/test/runtime/modules/AccessCheckUnnamed.java
new file mode 100644
index 0000000..0451489
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckUnnamed.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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.Module;
+import static jdk.test.lib.Asserts.*;
+
+/*
+ * @test
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 AccessCheckUnnamed
+ */
+
+public class AccessCheckUnnamed {
+
+    // Test that a class in the unnamed module can not access a package in a
+    // named module that has not been unqualifiedly exported.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for AccessCheckWorks and assume it's also used to
+        // load class p2.c2.
+        ClassLoader this_cldr = AccessCheckUnnamed.class.getClassLoader();
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should fail because
+        // p1 is in the unnamed module and p2.c2 is not unqualifiedly exported.
+        Class p1_c1_class = Class.forName("p1.c1");
+        try {
+            Object c1_obj = p1_c1_class.newInstance();
+            throw new RuntimeException("Failed to get IAE (p2 in m2 is not exported to unnamed module)");
+        } catch (IllegalAccessError f) {
+            System.out.println(f.getMessage());
+            if (!f.getMessage().contains("does not export p2 to unnamed module")) {
+                throw new RuntimeException("Wrong message: " + f.getMessage());
+            }
+        }
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/AccessCheckWorks.java b/hotspot/test/runtime/modules/AccessCheckWorks.java
new file mode 100644
index 0000000..3a13b04
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheckWorks.java
@@ -0,0 +1,79 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 AccessCheckWorks
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class AccessCheckWorks {
+
+    // Check that a class in a package in module1 can successfully access a
+    // class in module2 when module1 can read module2 and the class's package
+    // has been exported.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for AccessCheckWorks and assume it's also used to
+        // load classes p1.c1 and p2.c2.
+        ClassLoader this_cldr = AccessCheckWorks.class.getClassLoader();
+
+        // Define a module for p1.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p1" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/here", new String[] { "p1" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        // Make package p1 in m1 visible to everyone.
+        ModuleHelper.AddModuleExportsToAll(m1, "p1");
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should work because
+        // p1's module can read p2's module and p2 is exported to p1's module.
+        ModuleHelper.AddReadsModule(m1, m2);
+        ModuleHelper.AddModuleExports(m2, "p2", m1);
+        Class p1_c1_class = Class.forName("p1.c1");
+        p1_c1_class.newInstance();
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/CCE_module_msg.java b/hotspot/test/runtime/modules/CCE_module_msg.java
new file mode 100644
index 0000000..54ece08
--- /dev/null
+++ b/hotspot/test/runtime/modules/CCE_module_msg.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @run main/othervm CCE_module_msg
+ */
+
+// Test that the message in a runtime ClassCastException contains module info.
+public class CCE_module_msg {
+
+    public static void main(String[] args) {
+        invalidCastTest();
+    }
+
+    public static void invalidCastTest() {
+        java.lang.Object instance = new java.lang.Object();
+        int left = 23;
+        int right = 42;
+        try {
+            for (int i = 0; i < 1; i += 1) {
+                left = ((Derived) instance).method(left, right);
+            }
+            throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
+        } catch (ClassCastException cce) {
+            System.out.println(cce.getMessage());
+            if (!cce.getMessage().contains("java.lang.Object (in module: java.base) cannot be cast")) {
+                throw new RuntimeException("Wrong message: " + cce.getMessage());
+            }
+        }
+    }
+}
+
+class Derived extends java.lang.Object {
+    public int method(int left, int right) {
+        return right;
+    }
+}
diff --git a/hotspot/test/runtime/modules/ExportTwice.java b/hotspot/test/runtime/modules/ExportTwice.java
new file mode 100644
index 0000000..b33b55e
--- /dev/null
+++ b/hotspot/test/runtime/modules/ExportTwice.java
@@ -0,0 +1,92 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 ExportTwice
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class ExportTwice {
+
+    // Check that a package can not be exported unqualifiedly, and then exported
+    // to a specific package.
+    // Also, check that a package can be exported to a specific package and then
+    // exported unqualifiedly.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2, m3;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for ExportTwice and assume it's also used to
+        // load classes p1.c1 and p2.c2.
+        ClassLoader this_cldr = ExportTwice.class.getClassLoader();
+
+        // Define a module for p1.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p1" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/here", new String[] { "p1" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        // Define a module for p3.
+        m3 = ModuleHelper.ModuleObject("module3", this_cldr, new String[] { "p3" });
+        assertNotNull(m3, "Module should not be null");
+        ModuleHelper.DefineModule(m3, "9.0", "m3/there", new String[] { "p3" });
+        ModuleHelper.AddReadsModule(m3, jlObject_jlrM);
+
+        // Make package p1 in m1 visible to everyone.
+        ModuleHelper.AddModuleExportsToAll(m1, "p1");
+
+        // Try to export p1 only to m2 after it was exported unqualifiedly.  It
+        // should silently succeed.
+        ModuleHelper.AddModuleExports(m1, "p1", m2);
+
+        // Export p2 to m3 then export it again unqualifiedly.
+        ModuleHelper.AddModuleExports(m2, "p2", m3);
+        ModuleHelper.AddModuleExportsToAll(m2, "p2");
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should work because
+        // p1's module can read p2's module and p2 is now exported unqualifiedly.
+        ModuleHelper.AddReadsModule(m1, m2);
+        Class p1_c1_class = Class.forName("p1.c1");
+        p1_c1_class.newInstance();
+    }
+}
diff --git a/hotspot/test/runtime/modules/JVMAddModuleExportToAllUnnamed.java b/hotspot/test/runtime/modules/JVMAddModuleExportToAllUnnamed.java
new file mode 100644
index 0000000..b7b34b7
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMAddModuleExportToAllUnnamed.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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @build sun.hotspot.WhiteBox
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @compile/module=java.base java/lang/reflect/ModuleHelper.java
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI JVMAddModuleExportToAllUnnamed
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class JVMAddModuleExportToAllUnnamed {
+
+    // Check that a class in a package in module1 cannot access a class
+    // that is in the unnamed module if the accessing package is strict.
+    public static void main(String args[]) throws Throwable {
+        Object m1;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for JVMAddModuleExportToAllUnnamed and assume it's also used to
+        // load class p1.c1.
+        ClassLoader this_cldr = JVMAddModuleExportToAllUnnamed.class.getClassLoader();
+
+        // Define a module for p1.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p1" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/here", new String[] { "p1" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Make package p1 in m1 visible to everyone.
+        ModuleHelper.AddModuleExportsToAll(m1, "p1");
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should not work
+        // because p2 is in the unnamed module and p1.c1 is strict.
+        try {
+            Class p1_c1_class = Class.forName("p1.c1");
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            System.out.println(e.getMessage());
+            if (!e.getMessage().contains("does not read unnamed module")) {
+                throw new RuntimeException("Wrong message: " + e.getMessage());
+            }
+        }
+    }
+}
diff --git a/hotspot/test/runtime/modules/JVMAddModuleExports.java b/hotspot/test/runtime/modules/JVMAddModuleExports.java
new file mode 100644
index 0000000..330dd92
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMAddModuleExports.java
@@ -0,0 +1,145 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @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 JVMAddModuleExports
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+public class JVMAddModuleExports {
+
+    public static void main(String args[]) throws Throwable {
+        MyClassLoader from_cl = new MyClassLoader();
+        MyClassLoader to_cl = new MyClassLoader();
+        Module from_module, to_module;
+
+        from_module = ModuleHelper.ModuleObject("from_module", from_cl, new String[] { "mypackage", "this/package" });
+        assertNotNull(from_module, "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 should not be null");
+        ModuleHelper.DefineModule(to_module, "9.0", "to_module/here", new String[] { "yourpackage", "that/package" });
+
+        // Null from_module argument, expect an NPE
+        try {
+            ModuleHelper.AddModuleExports((Module)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 {
+            ModuleHelper.AddModuleExports(from_module, "mypackage", (Module)null);
+            throw new RuntimeException("Failed to get the expected NPE for null to_module");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Bad from_module argument, expect an IAE
+        try {
+            ModuleHelper.AddModuleExports(to_cl, "mypackage", to_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Null package argument, expect an NPE
+        try {
+            ModuleHelper.AddModuleExports(from_module, null, to_module);
+            throw new RuntimeException("Failed to get the expected NPE");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Bad to_module argument, expect an IAE
+        try {
+            ModuleHelper.AddModuleExports(from_module, "mypackage", from_cl);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Exporting a package to the same module
+        ModuleHelper.AddModuleExports(from_module, "mypackage", from_module);
+
+        // Export a package that does not exist to to_module
+        try {
+            ModuleHelper.AddModuleExports(from_module, "notmypackage", to_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export a package, that is not in from_module, to to_module
+        try {
+            ModuleHelper.AddModuleExports(from_module, "yourpackage", to_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export a package, that does not exist, to from_module
+        try {
+            ModuleHelper.AddModuleExports(from_module, "notmypackage", from_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export a package, that is not in from_module, to from_module
+        try {
+            ModuleHelper.AddModuleExports(from_module, "that/package", from_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export the same package twice to the same module
+        ModuleHelper.AddModuleExports(from_module, "this/package", to_module);
+        ModuleHelper.AddModuleExports(from_module, "this/package", to_module);
+
+        // Export a package, using '.' instead of '/'
+        try {
+            ModuleHelper.AddModuleExports(from_module, "this.package", to_module);
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export a package to the unnamed module and then to a specific module.
+        // The qualified export should be ignored.
+        ModuleHelper.AddModuleExportsToAll(to_module, "that/package");
+        ModuleHelper.AddModuleExports(to_module, "that/package", from_module);
+    }
+
+    static class MyClassLoader extends ClassLoader { }
+}
diff --git a/hotspot/test/runtime/modules/JVMAddModuleExportsToAll.java b/hotspot/test/runtime/modules/JVMAddModuleExportsToAll.java
new file mode 100644
index 0000000..f41d401
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMAddModuleExportsToAll.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Module;
+import static jdk.test.lib.Asserts.*;
+
+/*
+ * @test
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @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 JVMAddModuleExportsToAll
+ */
+
+public class JVMAddModuleExportsToAll {
+
+    // Test a series of error conditions for API JVM_AddModuleExportsToAll()
+    // and then test that a class in the unnamed module can access a package in
+    // a named module that has been exported unqualifiedly.
+    public static void main(String args[]) throws Throwable {
+        Object m1, m2, m3;
+
+        // Get the java.lang.reflect.Module object for module java.base.
+        Class jlObject = Class.forName("java.lang.Object");
+        Object jlObject_jlrM = jlObject.getModule();
+        assertNotNull(jlObject_jlrM, "jlrModule object of java.lang.Object should not be null");
+
+        // Get the class loader for JVMAddModuleExportsToAll and assume it's also used to
+        // load class p2.c2.
+        ClassLoader this_cldr = JVMAddModuleExportsToAll.class.getClassLoader();
+
+        // Define a module for p3.
+        m1 = ModuleHelper.ModuleObject("module1", this_cldr, new String[] { "p3" });
+        assertNotNull(m1, "Module should not be null");
+        ModuleHelper.DefineModule(m1, "9.0", "m1/there", new String[] { "p3" });
+        ModuleHelper.AddReadsModule(m1, jlObject_jlrM);
+
+        // Define a module for p2.
+        m2 = ModuleHelper.ModuleObject("module2", this_cldr, new String[] { "p2" });
+        assertNotNull(m2, "Module should not be null");
+        ModuleHelper.DefineModule(m2, "9.0", "m2/there", new String[] { "p2" });
+        ModuleHelper.AddReadsModule(m2, jlObject_jlrM);
+
+        try {
+            ModuleHelper.AddModuleExportsToAll((Module)null, "p2");
+            throw new RuntimeException("Failed to get the expected NPE for null module");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAll(m2, null);
+            throw new RuntimeException("Failed to get the expected NPE for null package");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        try { // Expect IAE when passing a ClassLoader object instead of a java.lang.reflect.Module object.
+            ModuleHelper.AddModuleExportsToAll(this_cldr, "p2");
+            throw new RuntimeException("Failed to get the expected IAE for bad module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAll(m2, "p3");
+            throw new RuntimeException("Failed to get the expected IAE for package that is in another module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            ModuleHelper.AddModuleExportsToAll(m2, "p4");
+            throw new RuntimeException("Failed to get the expected IAE for package not in any module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Export package p2 in m2 unqualifiedly. Then, do a qualified export
+        // of p2 in m2 to m3.  This should not affect the unqualified export.
+        m3 = ModuleHelper.ModuleObject("module3", this_cldr, new String[] { "p4" });
+        assertNotNull(m3, "Module m3 should not be null");
+        ModuleHelper.DefineModule(m3, "9.0", "m3/there", new String[] { "p4" });
+        ModuleHelper.AddModuleExportsToAll(m2, "p2");
+        ModuleHelper.AddModuleExports(m2, "p2", m3);
+
+        // p1.c1's ctor tries to call a method in p2.c2.  This should succeed because
+        // p1 is in an unnamed module and p2.c2 is exported unqualifiedly.
+        Class p1_c1_class = Class.forName("p1.c1");
+        try {
+            Object c1_obj = p1_c1_class.newInstance();
+        } catch (IllegalAccessError f) {
+            throw new RuntimeException(
+                "Class in unnamed module could not access package p2 exported unqualifieldly");
+        }
+    }
+}
+
diff --git a/hotspot/test/runtime/modules/JVMAddModulePackage.java b/hotspot/test/runtime/modules/JVMAddModulePackage.java
new file mode 100644
index 0000000..430c67c
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMAddModulePackage.java
@@ -0,0 +1,129 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @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 JVMAddModulePackage
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+public class JVMAddModulePackage {
+
+    public static void main(String args[]) throws Throwable {
+        MyClassLoader cl1 = new MyClassLoader();
+        MyClassLoader cl3 = new MyClassLoader();
+        Object module1, module2, module3;
+        boolean result;
+
+        module1 = ModuleHelper.ModuleObject("module1", cl1, new String[] { "mypackage" });
+        assertNotNull(module1, "Module should not be null");
+        ModuleHelper.DefineModule(module1, "9.0", "module1/here", new String[] { "mypackage" });
+        module2 = ModuleHelper.ModuleObject("module2", cl1, new String[] { "yourpackage" });
+        assertNotNull(module2, "Module should not be null");
+        ModuleHelper.DefineModule(module2, "9.0", "module2/here", new String[] { "yourpackage" });
+        module3 = ModuleHelper.ModuleObject("module3", cl3, new String[] { "package/num3" });
+        assertNotNull(module3, "Module should not be null");
+        ModuleHelper.DefineModule(module3, "9.0", "module3/here", new String[] { "package/num3" });
+
+        // Simple call
+        ModuleHelper.AddModulePackage(module1, "new_package");
+
+        // Add a package and export it
+        ModuleHelper.AddModulePackage(module1, "package/num3");
+        ModuleHelper.AddModuleExportsToAll(module1, "package/num3");
+
+        // Null module argument, expect an NPE
+        try {
+            ModuleHelper.AddModulePackage(null, "new_package");
+            throw new RuntimeException("Failed to get the expected NPE");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Bad module argument, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(cl1, "new_package");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Null package argument, expect an NPE
+        try {
+            ModuleHelper.AddModulePackage(module1, null);
+            throw new RuntimeException("Failed to get the expected NPE");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Existing package, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(module1, "yourpackage");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Invalid package name, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(module1, "your.package");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Invalid package name, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(module1, ";your/package");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Invalid package name, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(module1, "7[743");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Empty package name, expect an IAE
+        try {
+            ModuleHelper.AddModulePackage(module1, "");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+    }
+
+    static class MyClassLoader extends ClassLoader { }
+}
+
diff --git a/hotspot/test/runtime/modules/JVMAddReadsModule.java b/hotspot/test/runtime/modules/JVMAddReadsModule.java
new file mode 100644
index 0000000..78f1d3b
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMAddReadsModule.java
@@ -0,0 +1,83 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @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 JVMAddReadsModule
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+public class JVMAddReadsModule {
+
+    public static void main(String args[]) throws Throwable {
+        MyClassLoader from_cl = new MyClassLoader();
+        MyClassLoader to_cl = new MyClassLoader();
+        Object from_module, to_module;
+
+        from_module = ModuleHelper.ModuleObject("from_module", from_cl, new String[] { "mypackage" });
+        assertNotNull(from_module, "Module should not be null");
+        ModuleHelper.DefineModule(from_module, "9.0", "from_module/here", new String[] { "mypackage" });
+
+        to_module = ModuleHelper.ModuleObject("to_module", to_cl, new String[] { "yourpackage" });
+        assertNotNull(to_module, "Module should not be null");
+        ModuleHelper.DefineModule(to_module, "9.0", "to_module/here", new String[] { "yourpackage" });
+
+        // Null from_module argument, expect an NPE
+        try {
+            ModuleHelper.AddReadsModule(null, to_module);
+            throw new RuntimeException("Failed to get the expected NPE");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Null to_module argument, do not expect an NPE
+        try {
+            ModuleHelper.AddReadsModule(from_module, null);
+        } catch(NullPointerException e) {
+            throw new RuntimeException("Unexpected NPE was thrown");
+        }
+
+        // Null from_module and to_module arguments, expect an NPE
+        try {
+            ModuleHelper.AddReadsModule(null, null);
+            throw new RuntimeException("Failed to get the expected NPE");
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // Both modules are the same, should not throw an exception
+        ModuleHelper.AddReadsModule(from_module, from_module);
+
+        // Duplicate calls, should not throw an exception
+        ModuleHelper.AddReadsModule(from_module, to_module);
+        ModuleHelper.AddReadsModule(from_module, to_module);
+    }
+
+    static class MyClassLoader extends ClassLoader { }
+}
diff --git a/hotspot/test/runtime/modules/JVMCanReadModule.java b/hotspot/test/runtime/modules/JVMCanReadModule.java
new file mode 100644
index 0000000..ca131df
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMCanReadModule.java
@@ -0,0 +1,96 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @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
new file mode 100644
index 0000000..77d3c0f
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMDefineModule.java
@@ -0,0 +1,262 @@
+/*
+ * 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 /testlibrary  /test/lib /compiler/whitebox ..
+ * @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 JVMDefineModule
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+public class JVMDefineModule {
+
+    public static void main(String args[]) throws Throwable {
+        MyClassLoader cl = new MyClassLoader();
+        Object m;
+
+        // NULL classloader argument, expect success
+        m = ModuleHelper.ModuleObject("mymodule", null, new String[] { "mypackage" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackage" });
+
+/* Invalid test, won't compile.
+        // Invalid classloader argument, expect an IAE
+        try {
+            m = ModuleHelper.ModuleObject("mymodule1", new Object(), new String[] { "mypackage1" });
+            ModuleHelper.DefineModule(m,  "9.0", "mymodule/here", new String[] { "mypackage1" });
+            throw new RuntimeException("Failed to get expected IAE for bad loader");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+*/
+
+        // NULL package argument, should not throw an exception
+        m = ModuleHelper.ModuleObject("mymodule2", cl, new String[] { "nullpkg" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "mymodule2/here", null);
+
+        // Null module argument, expect an NPE
+        try {
+            ModuleHelper.DefineModule(null,  "9.0", "mymodule/here", new String[] { "mypackage1" });
+            throw new RuntimeException("Failed to get expected NPE for null module");
+        } catch(NullPointerException e) {
+            if (!e.getMessage().contains("Null module object")) {
+              throw new RuntimeException("Failed to get expected IAE message for null module: " + e.getMessage());
+            }
+            // Expected
+        }
+
+        // Invalid module argument, expect an IAE
+        try {
+            ModuleHelper.DefineModule(new Object(),  "9.0", "mymodule/here", new String[] { "mypackage1" });
+            throw new RuntimeException("Failed to get expected IAE or NPE for bad module");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("module is not a subclass")) {
+              throw new RuntimeException("Failed to get expected IAE message for bad module: " + e.getMessage());
+            }
+        }
+
+        // NULL module name, expect an IAE or NPE
+        try {
+            m = ModuleHelper.ModuleObject(null, cl, new String[] { "mypackage2" });
+            ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackage2" });
+            throw new RuntimeException("Failed to get expected NPE for NULL module");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        } catch(NullPointerException e) {
+            // Expected
+        }
+
+        // module name is java.base, expect an IAE
+        m = ModuleHelper.ModuleObject("java.base", cl, new String[] { "mypackage3" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackage3" });
+            throw new RuntimeException("Failed to get expected IAE for java.base, not defined with boot class loader");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Class loader must be the boot class loader")) {
+              throw new RuntimeException("Failed to get expected IAE message for java.base: " + e.getMessage());
+            }
+        }
+
+        // Duplicates in package list, expect an IAE
+        m = ModuleHelper.ModuleObject("module.x", cl, new String[] { "mypackage4", "mypackage5" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackage4", "mypackage5", "mypackage4" });
+            throw new RuntimeException("Failed to get IAE for duplicate packages");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Duplicate package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for duplicate package: " + e.getMessage());
+            }
+        }
+
+        // Empty entry in package list, expect an IAE
+        m = ModuleHelper.ModuleObject("module.y", cl, new String[] { "mypackageX", "mypackageY" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "mymodule/here", new String[] { "mypackageX", "", "mypackageY" });
+            throw new RuntimeException("Failed to get IAE for empty package");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Invalid package name")) {
+              throw new RuntimeException("Failed to get expected IAE message empty package entry: " + e.getMessage());
+            }
+        }
+
+        // Duplicate module name, expect an IAE
+        m = ModuleHelper.ModuleObject("module.name", cl, new String[] { "mypackage6" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6a" });
+            throw new RuntimeException("Failed to get IAE for duplicate module");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Module module.name is already defined")) {
+              throw new RuntimeException("Failed to get expected IAE message for duplicate module: " + e.getMessage());
+            }
+        }
+
+        // Package is already defined for class loader, expect an IAE
+        m = ModuleHelper.ModuleObject("dupl.pkg.module", cl, new String[] { "mypackage6b" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
+            throw new RuntimeException("Failed to get IAE for existing package");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Package mypackage6 for module dupl.pkg.module already exists for class loader")) {
+              throw new RuntimeException("Failed to get expected IAE message for duplicate package: " + e.getMessage());
+            }
+        }
+
+        // Empty module name, expect an IAE
+        try {
+            m = ModuleHelper.ModuleObject("", cl, new String[] { "mypackage8" });
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage8" });
+            throw new RuntimeException("Failed to get expected IAE for empty module name");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Bad module name, expect an IAE
+        try {
+            m = ModuleHelper.ModuleObject("bad;name", cl, new String[] { "mypackage9" });
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage9" });
+            throw new RuntimeException("Failed to get expected IAE for bad;name");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Bad module name, expect an IAE
+        try {
+            m = ModuleHelper.ModuleObject(".leadingdot", cl, new String[] { "mypackage9a" });
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage9a" });
+            throw new RuntimeException("Failed to get expected IAE for .leadingdot");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Bad module name, expect an IAE
+        try {
+            m = ModuleHelper.ModuleObject("trailingdot.", cl, new String[] { "mypackage9b" });
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage9b" });
+            throw new RuntimeException("Failed to get expected IAE for trailingdot.");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Bad module name, expect an IAE
+        m = ModuleHelper.ModuleObject("consecutive..dots", cl, new String[] { "mypackage9c" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage9c" });
+            throw new RuntimeException("Failed to get expected IAE for consecutive..dots");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+
+        // module name with multiple dots, should be okay
+        m = ModuleHelper.ModuleObject("more.than.one.dat", cl, new String[] { "mypackage9d" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage9d" });
+
+        // Zero length package list, should be okay
+        m = ModuleHelper.ModuleObject("zero.packages", cl, new String[] { });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { });
+
+        // Invalid package name, expect an IAE
+        m = ModuleHelper.ModuleObject("module5", cl, new String[] { "your.package" });
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "your.package" });
+            throw new RuntimeException("Failed to get expected IAE for your.package");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Invalid package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for bad package name: " + e.getMessage());
+            }
+        }
+
+        // Invalid package name, expect an IAE
+        m = ModuleHelper.ModuleObject("module6", cl, new String[] { "foo" }); // Name irrelevant
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { ";your/package" });
+            throw new RuntimeException("Failed to get expected IAE for ;your.package");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Invalid package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for bad package name: " + e.getMessage());
+            }
+        }
+
+        // Invalid package name, expect an IAE
+        m = ModuleHelper.ModuleObject("module7", cl, new String[] { "foo" }); // Name irrelevant
+        try {
+            ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "7[743" });
+            throw new RuntimeException("Failed to get expected IAE for package 7[743");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("Invalid package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for bad package name: " + e.getMessage());
+            }
+        }
+
+        // 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");
+        ModuleHelper.DefineModule(m, null, "module8/here", new String[] { "a_package_8" });
+
+        // module version that is "", should be okay
+        m = ModuleHelper.ModuleObject("module9", cl, new String[] { "a_package_9" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "", "module9/here", new String[] { "a_package_9" });
+
+        // module location that is null, should be okay
+        m = ModuleHelper.ModuleObject("module10", cl, new String[] { "a_package_10" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", null, new String[] { "a_package_10" });
+
+        // module location that is "", should be okay
+        m = ModuleHelper.ModuleObject("module11", cl, new String[] { "a_package_11" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "", new String[] { "a_package_11" });
+    }
+
+    static class MyClassLoader extends ClassLoader { }
+}
diff --git a/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java b/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java
new file mode 100644
index 0000000..25065e2
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMGetModuleByPkgName.java
@@ -0,0 +1,90 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @compile p2/c2.java
+ * @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 JVMGetModuleByPkgName
+ */
+
+import static jdk.test.lib.Asserts.*;
+import java.lang.ClassLoader;
+import java.lang.reflect.Module;
+
+public class JVMGetModuleByPkgName {
+
+    public static void main(String args[]) throws Throwable {
+
+        Module javaBase = ModuleHelper.GetModuleByPackageName(null, "java/lang");
+        if (!javaBase.getName().equals("java.base")) {
+            throw new RuntimeException(
+                "Failed to get module java.base for package java/lang");
+        }
+
+        if (ModuleHelper.GetModuleByPackageName(null, "bad.package.name") != null) {
+            throw new RuntimeException("Failed to get null for bad.package.name");
+        }
+
+        ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
+        if (ModuleHelper.GetModuleByPackageName(systemLoader, "java/lang") != null) {
+            throw new RuntimeException(
+                "Failed to get null for systemClassLoader and java/lang");
+        }
+
+        try {
+            ModuleHelper.GetModuleByPackageName(systemLoader, null);
+            throw new RuntimeException(
+                "Failed to throw NullPointerException for null package name");
+        } catch(NullPointerException e) {
+             // Expected
+        }
+
+        Module unnamedModule = ModuleHelper.GetModuleByPackageName(systemLoader, "");
+        if (unnamedModule.isNamed()) {
+            throw new RuntimeException(
+                "Unexpected named module returned for unnamed package");
+        }
+
+        p2.c2 obj = new p2.c2();
+        unnamedModule = ModuleHelper.GetModuleByPackageName(systemLoader, "p2");
+        if (unnamedModule.isNamed()) {
+            throw new RuntimeException(
+                "Unexpected named module returned for package p2 in unnamed module");
+        }
+
+        MyClassLoader cl1 = new MyClassLoader();
+        Module module1 = (Module)ModuleHelper.ModuleObject("module1", cl1, new String[] { "mypackage" });
+        assertNotNull(module1, "Module should not be null");
+        ModuleHelper.DefineModule(module1, "9.0", "module1/here", new String[] { "mypackage" });
+        if (ModuleHelper.GetModuleByPackageName(cl1, "mypackage") != module1) {
+            throw new RuntimeException("Wrong module returned for cl1 mypackage");
+        }
+    }
+
+    static class MyClassLoader extends ClassLoader { }
+}
diff --git a/hotspot/test/runtime/modules/JVMIsExportedToModule.java b/hotspot/test/runtime/modules/JVMIsExportedToModule.java
new file mode 100644
index 0000000..0e35b7d
--- /dev/null
+++ b/hotspot/test/runtime/modules/JVMIsExportedToModule.java
@@ -0,0 +1,123 @@
+/*
+ * 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 /testlibrary /test/lib /compiler/whitebox ..
+ * @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/LoadUnloadModuleStress.java b/hotspot/test/runtime/modules/LoadUnloadModuleStress.java
new file mode 100644
index 0000000..53d45c9
--- /dev/null
+++ b/hotspot/test/runtime/modules/LoadUnloadModuleStress.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Ensure module information is cleaned when owning class loader unloads
+ * @library /testlibrary /test/lib /compiler/whitebox ..
+ * @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 -Xmx64m -Xmx64m LoadUnloadModuleStress 15000
+ */
+
+import java.lang.ref.WeakReference;
+
+import static jdk.test.lib.Asserts.*;
+
+public class LoadUnloadModuleStress {
+    private static long timeout;
+    private static long timeStamp;
+
+    public static byte[] garbage;
+    public static volatile WeakReference<MyClassLoader> clweak;
+
+    public static Object createModule() throws Throwable {
+        MyClassLoader cl = new MyClassLoader();
+        Object module = ModuleHelper.ModuleObject("mymodule", cl, new String [] {"PackageA"});
+        assertNotNull(module);
+        ModuleHelper.DefineModule(module, "9.0", "mymodule", new String[] { "PackageA" });
+        clweak = new WeakReference<>(cl);
+        return module;
+    }
+
+    public static void main(String args[]) throws Throwable {
+        timeout = Long.valueOf(args[0]);
+        timeStamp = System.currentTimeMillis();
+
+        while(System.currentTimeMillis() - timeStamp < timeout) {
+            WeakReference<Object> modweak = new WeakReference<>(createModule());
+
+            while(clweak.get() != null) {
+                garbage = new byte[8192];
+                System.gc();
+            }
+            assertNull(modweak.get());
+        }
+    }
+    static class MyClassLoader extends ClassLoader { }
+}
diff --git a/hotspot/test/runtime/modules/ModuleHelper.java b/hotspot/test/runtime/modules/ModuleHelper.java
new file mode 100644
index 0000000..2761b48
--- /dev/null
+++ b/hotspot/test/runtime/modules/ModuleHelper.java
@@ -0,0 +1,104 @@
+/*
+ * 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.net.URI;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Module;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import sun.hotspot.WhiteBox;
+
+public class ModuleHelper {
+
+    public static void DefineModule(Object module, String version, String location,
+                                    String[] pkgs) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.DefineModule(module, version, location, pkgs);
+    }
+
+    public static void AddModuleExports(Object from, String pkg, Object to) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.AddModuleExports(from, pkg, to);
+        java.lang.reflect.ModuleHelper.addExportsNoSync((Module)from, pkg, (Module)to);
+    }
+
+    public static void AddReadsModule(Object from, Object to) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.AddReadsModule(from, to);
+        java.lang.reflect.ModuleHelper.addReadsNoSync((Module)from, (Module)to);
+    }
+
+    public static void AddModulePackage(Object m, String pkg) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.AddModulePackage(m, pkg);
+        java.lang.reflect.ModuleHelper.addPackageNoSync((Module)m, pkg);
+    }
+
+    public static Module GetModuleByPackageName(Object ldr, String pkg) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        return (Module)wb.GetModuleByPackageName(ldr, pkg);
+    }
+
+    public static void AddModuleExportsToAllUnnamed(Object m, String pkg) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.AddModuleExportsToAllUnnamed(m, pkg);
+        //java.lang.reflect.ModuleHelper.addExportsToAllUnnamedNoSync((Module)m, pkg);
+    }
+
+    public static void AddModuleExportsToAll(Object m, String pkg) throws Throwable {
+        WhiteBox wb = WhiteBox.getWhiteBox();
+        wb.AddModuleExportsToAll(m, pkg);
+        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) {
+            for (String pkg: pkgs) {
+                pkg_set.add(pkg.replace('/', '.'));
+            }
+        } else {
+            pkg_set = Collections.emptySet();
+        }
+
+        ModuleDescriptor descriptor =
+            new ModuleDescriptor.Builder(name).conceals(pkg_set).build();
+        URI uri = URI.create("module:/" + name);
+
+        return java.lang.reflect.ModuleHelper.newModule(loader, descriptor);
+    }
+
+}
diff --git a/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java b/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java
new file mode 100644
index 0000000..3dd36ca
--- /dev/null
+++ b/hotspot/test/runtime/modules/Visibility/XbootcpNoVisibility.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Ensure that a class defined within a java.base package can not
+ *          be located via -Xbootclasspath/a
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main/othervm XbootcpNoVisibility
+ */
+
+import jdk.test.lib.*;
+
+public class XbootcpNoVisibility {
+    public static void main(String args[]) throws Exception {
+
+        String Vis3_B_src =
+                "package sun.util;" +
+                "public class Vis3_B { public void m() { System.out.println(\"In B's m()\"); } }";
+
+        ClassFileInstaller.writeClassToDisk("sun/util/Vis3_B",
+            InMemoryJavaCompiler.compile("sun.util.Vis3_B", Vis3_B_src), System.getProperty("test.classes"));
+
+        String Vis3_A_src =
+                "import sun.util.*;" +
+                "public class Vis3_A {" +
+                "    public static void main(String args[]) throws Exception {" +
+                        // Try loading a class within a named package in a module which has been defined
+                        // to the boot loader. In this situation, the class should only be attempted
+                        // to be loaded from the boot loader's module path which consists of:
+                        //   [-Xpatch]; exploded build | "modules" jimage
+                        //
+                        // Since the class is located on the boot loader's append path via
+                        // -Xbootclasspath/a specification, it should not be found.
+                "       try {" +
+                "               sun.util.Vis3_B b = new sun.util.Vis3_B();" +
+                "       } catch (NoClassDefFoundError e) {" +
+                "               System.out.println(\"XbootcpNoVisibility PASSED - " +
+                                                "test should throw exception\\n\");" +
+                "               return;" +
+                "       }" +
+                "       throw new RuntimeException(\"XbootcpNoVisibility FAILED - " +
+                                                    "test should have thrown exception\");" +
+                "    }" +
+                "}";
+
+        ClassFileInstaller.writeClassToDisk("Vis3_A",
+                InMemoryJavaCompiler.compile("Vis3_A", Vis3_A_src), System.getProperty("test.classes"));
+
+        new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
+                "-Xbootclasspath/a:.",
+                "Vis3_A")
+            .start()).shouldContain("XbootcpNoVisibility PASSED");
+    }
+}
diff --git a/hotspot/test/runtime/modules/Visibility/XbootcpVisibility.java b/hotspot/test/runtime/modules/Visibility/XbootcpVisibility.java
new file mode 100644
index 0000000..5eb8882
--- /dev/null
+++ b/hotspot/test/runtime/modules/Visibility/XbootcpVisibility.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Ensure that a package whose module has not been defined to the boot loader
+ *          is correctly located with -Xbootclasspath/a
+ * @requires !(os.family == "windows")
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main/othervm XbootcpVisibility
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import jdk.test.lib.*;
+
+public class XbootcpVisibility {
+
+    public static void main(String[] args) throws Throwable {
+
+        String Vis1_B_src =
+                "package p2;" +
+                "public class Vis1_B { public void m() { System.out.println(\"In B's m()\"); } }";
+
+        ClassFileInstaller.writeClassToDisk("p2/Vis1_B",
+            InMemoryJavaCompiler.compile("p2.Vis1_B", Vis1_B_src), System.getProperty("test.classes"));
+        ClassFileInstaller.writeClassToDisk("p2/Vis1_B", "mods1");
+
+        String Vis1_C_src =
+                "package p2;" +
+                "public class Vis1_C { public void m() { System.out.println(\"In C's m()\"); } }";
+
+        ClassFileInstaller.writeClassToDisk("p2/Vis1_C",
+            InMemoryJavaCompiler.compile("p2.Vis1_C", Vis1_C_src), System.getProperty("test.classes"));
+        ClassFileInstaller.writeClassToDisk("p2/Vis1_C", "mods1");
+
+        String Vis1_A_src =
+            "public class Vis1_A {" +
+            "    public static void main(String args[]) throws Exception {" +
+            // Try loading a class within a named package
+            // in the unnamed module.
+            // Ensure the class can still be loaded successfully by the
+            // boot loader since it is located on -Xbootclasspath/a.
+            "        try {" +
+            "            p2.Vis1_B b = new p2.Vis1_B();" +
+            "            if (b.getClass().getClassLoader() != null) {" +
+            "              throw new RuntimeException(\"XbootcpVisibility FAILED - class B " +
+                                                      "should be loaded by boot class loader\\n\");" +
+            "            }" +
+            "            b.m();" +
+            // Now that the package p2 has been recorded in the
+            // unnamed module within the boot loader's PackageEntryTable,
+            // ensure that a different class within the same package
+            // can be located on -Xbootclasspath/a as well.
+            "            p2.Vis1_C c = new p2.Vis1_C();" +
+            "            if (c.getClass().getClassLoader() != null) {" +
+            "              throw new RuntimeException(\"XbootcpVisibility FAILED - class C " +
+                                                       "should be loaded by boot class loader\\n\");" +
+            "            }" +
+            "            c.m();" +
+            "        } catch (Exception e) {" +
+            "            System.out.println(e);" +
+            "            throw new RuntimeException(\"XbootcpVisibility FAILED - " +
+                                                     "test should not throw exception\\n\");" +
+            "        }" +
+            "        System.out.println(\"XbootcpVisibility PASSED\\n\");" +
+            "    }" +
+            "}";
+
+        ClassFileInstaller.writeClassToDisk("Vis1_A",
+                InMemoryJavaCompiler.compile("Vis1_A", Vis1_A_src), System.getProperty("test.classes"));
+
+        // Make sure the classes are actually being loaded from mods1
+        Files.delete(Paths.get(System.getProperty("test.classes") +  File.separator +
+                                                               "p2" + File.separator + "Vis1_B.class"));
+        Files.delete(Paths.get(System.getProperty("test.classes") +  File.separator +
+                                                               "p2" + File.separator + "Vis1_C.class"));
+
+        new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
+                "-Xbootclasspath/a:nonexistent.jar",
+                "-Xbootclasspath/a:mods1",
+                "Vis1_A")
+            .start()).shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java b/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java
new file mode 100644
index 0000000..1fe53d1
--- /dev/null
+++ b/hotspot/test/runtime/modules/Visibility/XpatchVisibility.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Ensure that a newly introduced java.base package placed within the -Xpatch directory
+ *          is considered part of the boot loader's visibility boundary
+ * @requires !(os.family == "windows")
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main/othervm XpatchVisibility
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import jdk.test.lib.*;
+
+public class XpatchVisibility {
+
+    public static void main(String[] args) throws Throwable {
+
+      String Vis2_B_src =
+              "package p2;" +
+              "public class Vis2_B {" +
+              "    public void m() {" +
+              "        System.out.println(\"In B's m()\");" +
+              "    }" +
+              "}";
+
+      String Vis2_A_src =
+              "import p2.*;" +
+              "public class Vis2_A {" +
+              "    public static void main(String args[]) throws Exception {" +
+                      // Try loading a class within a newly introduced java.base
+                      // package.  Make sure the class can be found via -Xpatch.
+              "        try {" +
+              "            p2.Vis2_B b = new p2.Vis2_B();" +
+              "            if (b.getClass().getClassLoader() != null) {" +
+              "                throw new RuntimeException(\"XpatchVisibility FAILED - class B " +
+                                                           "should be loaded by boot class loader\\n\");" +
+              "            }" +
+              "            b.m();" +
+              "        } catch (Throwable e) {" +
+              "            throw new RuntimeException(\"XpatchVisibility FAILED - test " +
+                                                       "should not throw an error or exception\\n\");" +
+              "        }" +
+              "        System.out.println(\"XpatchVisibility PASSED\\n\");" +
+              "    }" +
+              "}";
+
+      ClassFileInstaller.writeClassToDisk("p2/Vis2_B",
+          InMemoryJavaCompiler.compile("p2.Vis2_B", Vis2_B_src), System.getProperty("test.classes"));
+      ClassFileInstaller.writeClassToDisk("p2/Vis2_B", "mods2/java.base");
+
+      ClassFileInstaller.writeClassToDisk("Vis2_A",
+          InMemoryJavaCompiler.compile("Vis2_A", Vis2_A_src), System.getProperty("test.classes"));
+
+      // Make sure the classes are actually being loaded from mods2
+      Files.delete(Paths.get(System.getProperty("test.classes") +  File.separator +
+                                                           "p2" + File.separator + "Vis2_B.class"));
+
+      new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
+              "-Xpatch:mods2",
+              "-XaddExports:java.base/p2=ALL-UNNAMED",
+              "Vis2_A")
+          .start()).shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java b/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java
new file mode 100644
index 0000000..014476c
--- /dev/null
+++ b/hotspot/test/runtime/modules/Xpatch/Xpatch2Dirs.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Make sure -Xpatch works with multiple directories.
+ * @library /testlibrary
+ * @compile Xpatch2DirsMain.java
+ * @run main Xpatch2Dirs
+ */
+
+import jdk.test.lib.*;
+import java.io.File;
+
+public class Xpatch2Dirs {
+
+    public static void main(String[] args) throws Exception {
+        String source1 = "package javax.naming.spi; "               +
+                        "public class NamingManager { "             +
+                        "    static { "                             +
+                        "        System.out.println(\"I pass one!\"); " +
+                        "    } "                                    +
+                        "}";
+        String source2 = "package java.beans; "                     +
+                        "public class Encoder { "                   +
+                        "    static { "                             +
+                        "        System.out.println(\"I pass two!\"); " +
+                        "    } "                                    +
+                        "}";
+
+        ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source1, "-Xmodule:java.naming"),
+             "mods/java.naming");
+
+        ClassFileInstaller.writeClassToDisk("java/beans/Encoder",
+             InMemoryJavaCompiler.compile("java.beans.Encoder", source2, "-Xmodule:java.desktop"),
+             "mods2/java.desktop");
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+             "-Xpatch:mods" + File.pathSeparator + "mods2",
+             "Xpatch2DirsMain", "javax.naming.spi.NamingManager", "java.beans.Encoder");
+
+        OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("I pass one!");
+        oa.shouldContain("I pass two!");
+        oa.shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java b/hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java
new file mode 100644
index 0000000..9691156
--- /dev/null
+++ b/hotspot/test/runtime/modules/Xpatch/Xpatch2DirsMain.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+// This loads the class affected by the -Xpatch option.  For the test to pass
+// it must load both classes from the -Xpatch directory, not the jimage file.
+public class Xpatch2DirsMain {
+    public static void main(String[] args) throws Exception {
+        Class.forName(args[0]);
+        Class.forName(args[1]);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchMain.java b/hotspot/test/runtime/modules/Xpatch/XpatchMain.java
new file mode 100644
index 0000000..5509cbc
--- /dev/null
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchMain.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// This loads the class affected by the -Xpatch option.  For the test to pass
+// it must load the class from the -Xpatch directory, not the jimage file.
+public class XpatchMain {
+    public static void main(String[] args) throws Exception {
+        Class.forName(args[0]);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTest.java b/hotspot/test/runtime/modules/Xpatch/XpatchTest.java
new file mode 100644
index 0000000..ddc873f
--- /dev/null
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8130399
+ * @summary Make sure -Xpatch works for modules besides java.base.
+ * @library /testlibrary
+ * @compile XpatchMain.java
+ * @run main XpatchTest
+ */
+
+import jdk.test.lib.*;
+
+public class XpatchTest {
+
+    public static void main(String[] args) throws Exception {
+        String source = "package javax.naming.spi; "                +
+                        "public class NamingManager { "             +
+                        "    static { "                             +
+                        "        System.out.println(\"I pass!\"); " +
+                        "    } "                                    +
+                        "}";
+
+        ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             "mods/java.naming");
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
+             "XpatchMain", "javax.naming.spi.NamingManager");
+
+        new OutputAnalyzer(pb.start())
+            .shouldContain("I pass!")
+            .shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java b/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java
new file mode 100644
index 0000000..02edebf
--- /dev/null
+++ b/hotspot/test/runtime/modules/Xpatch/XpatchTraceCL.java
@@ -0,0 +1,83 @@
+/*
+ * 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 8069469
+ * @summary Make sure -XX:+TraceClassLoading works properly with "modules" jimage,
+            -Xpatch, and with -Xbootclasspath/a
+ * @library /testlibrary
+ * @compile XpatchMain.java
+ * @run main XpatchTraceCL
+ */
+
+import java.io.File;
+import jdk.test.lib.*;
+
+public class XpatchTraceCL {
+
+    public static void main(String[] args) throws Exception {
+        String source = "package javax.naming.spi; "                +
+                        "public class NamingManager { "             +
+                        "    static { "                             +
+                        "        System.out.println(\"I pass!\"); " +
+                        "    } "                                    +
+                        "}";
+
+        // Test -XX:+TraceClassLoading output for -Xpatch
+        ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+             InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+             "mods/java.naming");
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:mods",
+             "-XX:+TraceClassLoading", "XpatchMain", "javax.naming.spi.NamingManager");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        // "modules" jimage case.
+        output.shouldContain("[classload] java.lang.Thread source: jrt:/java.base");
+        // -Xpatch case.
+        output.shouldContain("[classload] javax.naming.spi.NamingManager source: mods" +
+            File.separator + "java.naming");
+        // -cp case.
+        output.shouldContain("[classload] XpatchMain source: file");
+
+        // Test -XX:+TraceClassLoading output for -Xbootclasspath/a
+        source = "package XpatchTraceCL_pkg; "                 +
+                 "public class ItIsI { "                          +
+                 "    static { "                                  +
+                 "        System.out.println(\"I also pass!\"); " +
+                 "    } "                                         +
+                 "}";
+
+        ClassFileInstaller.writeClassToDisk("XpatchTraceCL_pkg/ItIsI",
+             InMemoryJavaCompiler.compile("XpatchTraceCL_pkg.ItIsI", source),
+             "xbcp");
+
+        pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:xbcp",
+             "-XX:+TraceClassLoading", "XpatchMain", "XpatchTraceCL_pkg.ItIsI");
+        output = new OutputAnalyzer(pb.start());
+        // -Xbootclasspath/a case.
+        output.shouldContain("[classload] XpatchTraceCL_pkg.ItIsI source: xbcp");
+        output.shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/runtime/modules/XpatchCDS.java b/hotspot/test/runtime/modules/XpatchCDS.java
new file mode 100644
index 0000000..4c80bec
--- /dev/null
+++ b/hotspot/test/runtime/modules/XpatchCDS.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * @run main XpatchCDS
+ */
+
+import java.io.File;
+import jdk.test.lib.*;
+
+public class XpatchCDS {
+
+    public static void main(String args[]) throws Throwable {
+        System.out.println("Test that -Xpatch and -Xshare:dump are incompatibable");
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xpatch:.", "-Xshare:dump");
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Cannot use the following option when dumping the shared archive: -Xpatch");
+
+        System.out.println("Test that -Xpatch and -Xshare:on are incompatibable");
+        String filename = "Xpatch.jsa";
+        pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=" + filename,
+            "-Xshare:dump");
+        output = new OutputAnalyzer(pb.start());
+        output.shouldContain("ro space:"); // Make sure archive got created.
+
+        pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=" + filename,
+            "-Xshare:on",
+            "-Xpatch:.",
+            "-version");
+        output = new OutputAnalyzer(pb.start());
+        output.shouldContain("The shared archive file cannot be used with -Xpatch");
+
+        output.shouldHaveExitValue(1);
+    }
+}
diff --git a/hotspot/test/runtime/modules/acc_module.jcod b/hotspot/test/runtime/modules/acc_module.jcod
new file mode 100644
index 0000000..573c7dd
--- /dev/null
+++ b/hotspot/test/runtime/modules/acc_module.jcod
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+/*
+ * This class consists of the following java code, but has an illegal class
+ * access_flags value of 0x8000, that should be ignored by the JVM.
+ *
+ *    public class acc_module {
+ *       public static void main(String[] args) {
+ *            System.out.println("hello");
+ *        }
+ *    }
+ */
+class acc_module {
+  0xCAFEBABE;
+  0; // minor version
+  52; // version
+  [29] { // Constant Pool
+    ; // first element is empty
+    Method #6 #15; // #1     at 0x0A
+    Field #16 #17; // #2     at 0x0F
+    String #18; // #3     at 0x14
+    Method #19 #20; // #4     at 0x17
+    class #21; // #5     at 0x1C
+    class #22; // #6     at 0x1F
+    Utf8 "<init>"; // #7     at 0x22
+    Utf8 "()V"; // #8     at 0x2B
+    Utf8 "Code"; // #9     at 0x31
+    Utf8 "LineNumberTable"; // #10     at 0x38
+    Utf8 "main"; // #11     at 0x4A
+    Utf8 "([Ljava/lang/String;)V"; // #12     at 0x51
+    Utf8 "SourceFile"; // #13     at 0x6A
+    Utf8 "acc_module.java"; // #14     at 0x77
+    NameAndType #7 #8; // #15     at 0x89
+    class #23; // #16     at 0x8E
+    NameAndType #24 #25; // #17     at 0x91
+    Utf8 "hello"; // #18     at 0x96
+    class #26; // #19     at 0x9E
+    NameAndType #27 #28; // #20     at 0xA1
+    Utf8 "acc_module"; // #21     at 0xA6
+    Utf8 "java/lang/Object"; // #22     at 0xB3
+    Utf8 "java/lang/System"; // #23     at 0xC6
+    Utf8 "out"; // #24     at 0xD9
+    Utf8 "Ljava/io/PrintStream;"; // #25     at 0xDF
+    Utf8 "java/io/PrintStream"; // #26     at 0xF7
+    Utf8 "println"; // #27     at 0x010D
+    Utf8 "(Ljava/lang/String;)V"; // #28     at 0x0117
+  } // Constant Pool
+
+  0x8000; // access
+  #5;// this_cpx
+  #6;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [2] { // methods
+    { // Member at 0x013B
+      0x0001; // access
+      #7; // name_cpx
+      #8; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0x0143
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0x015A
+              [1] { // LineNumberTable
+                0  1; //  at 0x0166
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0166
+      0x0009; // access
+      #11; // name_cpx
+      #12; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 37) { // Code at 0x016E
+          2; // max_stack
+          1; // max_locals
+          Bytes[9]{
+            0xB200021203B60004;
+            0xB1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 10) { // LineNumberTable at 0x0189
+              [2] { // LineNumberTable
+                0  3; //  at 0x0195
+                8  4; //  at 0x0199
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#13, 2) { // SourceFile at 0x019B
+      #14;
+    } // end SourceFile
+  } // Attributes
+} // end class acc_module
diff --git a/hotspot/test/runtime/modules/getModuleJNI/GetModule.java b/hotspot/test/runtime/modules/getModuleJNI/GetModule.java
new file mode 100644
index 0000000..bc9883c
--- /dev/null
+++ b/hotspot/test/runtime/modules/getModuleJNI/GetModule.java
@@ -0,0 +1,167 @@
+/*
+ * 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 JNI_GetModule() API
+ * @run main/native GetModule
+ */
+
+import java.lang.reflect.Module;
+import java.lang.management.LockInfo;
+public class GetModule {
+
+    static {
+        System.loadLibrary("GetModule");
+    }
+
+    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;
+
+        // Module for array of primitives, should be "java.base"
+        int[] int_array = {1, 2, 3};
+        Module javaBaseModule;
+        try {
+            javaBaseModule = (Module)callGetModule(int_array.getClass());
+            if (!javaBaseModule.getName().equals("java.base")) {
+                throw new RuntimeException("Unexpected module name for array of primitives: " +
+                                           javaBaseModule.getName());
+            }
+        } catch(Throwable e) {
+            throw new RuntimeException("Unexpected exception for [I: " + e.toString());
+        }
+
+        // Module for java.lang.String
+        java.lang.String str = "abc";
+        try {
+            module = (Module)callGetModule(str.getClass());
+            if (!module.getName().equals("java.base")) {
+                throw new RuntimeException("Unexpected module name for class String: " +
+                                           module.getName());
+            }
+        } catch(Throwable e) {
+            throw new RuntimeException("Unexpected exception for String: " + e.toString());
+        }
+
+        // Module for java.lang.management.LockInfo
+        try {
+            LockInfo li = new LockInfo("java.lang.Class", 57);
+            module = (Module)callGetModule(li.getClass());
+            if (!module.getName().equals("java.management")) {
+                throw new RuntimeException("Unexpected module name for class LockInfo: " +
+                                           module.getName());
+            }
+        } catch(Throwable e) {
+            throw new RuntimeException("Unexpected exception for LockInfo: " + e.toString());
+        }
+
+        // Unnamed module.
+        try {
+            module = (Module)callGetModule(MyClassLoader.class);
+            if (module == null || module.getName() != null) {
+                throw new RuntimeException("Bad module for unnamed module");
+            }
+        } catch(Throwable e) {
+            throw new RuntimeException("Unexpected exception for unnamed module: " + e.toString());
+        }
+
+        try {
+            module = (Module)callGetModule(null);
+            throw new RuntimeException("Failed to get expected NullPointerException");
+        } 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
new file mode 100644
index 0000000..a7b1b6d
--- /dev/null
+++ b/hotspot/test/runtime/modules/getModuleJNI/libGetModule.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 <jni.h>
+
+JNIEXPORT jobject JNICALL
+Java_GetModule_callGetModule(JNIEnv *env, jclass unused, jclass clazz) {
+    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/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java b/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java
new file mode 100644
index 0000000..ca7977ae
--- /dev/null
+++ b/hotspot/test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java
@@ -0,0 +1,69 @@
+/*
+ * 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 java.lang.reflect;
+
+import java.lang.module.ModuleDescriptor;
+
+/**
+ * A helper class intended to be injected into java.lang.reflect using the
+ * java -Xpatch option. The helper class provides access to package private
+ * methods in java.lang.reflect.Module.
+ */
+
+public final class ModuleHelper {
+
+    private ModuleHelper() { }
+
+    /**
+     * Creates a named module but without defining the module to the VM.
+     */
+    public static Module newModule(ClassLoader loader, ModuleDescriptor descriptor) {
+        return new Module(loader, descriptor);
+    }
+
+    /**
+     * Updates module {@code from} to that it reads module {@code to} without
+     * notifying the VM.
+     */
+    public static void addReadsNoSync(Module from, Module to) {
+        from.implAddReadsNoSync(to);
+    }
+
+    /**
+     * Updates module {@code from} so that it exports package {@code pkg}
+     * to module {@code to} but without notifying the VM. If {@code to} is
+     * {@code null} then the package is exported unconditionally.
+     */
+    public static void addExportsNoSync(Module from, String pkg, Module to) {
+        from.implAddExportsNoSync(pkg, to);
+    }
+
+    /**
+     * Adds a package to a module without notifying the VM.
+     */
+    public static void addPackageNoSync(Module m, String pkg) {
+        m.implAddPackageNoSync(pkg);
+    }
+
+}
diff --git a/hotspot/test/runtime/modules/p1/c1.java b/hotspot/test/runtime/modules/p1/c1.java
new file mode 100644
index 0000000..7fbe4f9
--- /dev/null
+++ b/hotspot/test/runtime/modules/p1/c1.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck* tests.
+package p1;
+
+import p2.c2;
+
+public class c1 {
+
+    public c1 () {
+        p2.c2 c2_obj = new p2.c2();
+        c2_obj.method2();
+    }
+}
diff --git a/hotspot/test/runtime/modules/p2/c2.java b/hotspot/test/runtime/modules/p2/c2.java
new file mode 100644
index 0000000..74adc64
--- /dev/null
+++ b/hotspot/test/runtime/modules/p2/c2.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck* tests.
+package p2;
+
+public class c2 {
+    public void method2() { }
+}
diff --git a/hotspot/test/runtime/modules/p3/c3.java b/hotspot/test/runtime/modules/p3/c3.java
new file mode 100644
index 0000000..1e8130c
--- /dev/null
+++ b/hotspot/test/runtime/modules/p3/c3.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck* tests.
+package p3;
+
+public class c3 extends p2.c2 {
+    public void method3() { }
+}
diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
index 33b59c9..4e2abad 100644
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
@@ -95,7 +95,7 @@
             String expectedFormat) throws Exception, IOException,
             InterruptedException, FileNotFoundException {
         ProcessBuilder procBuilder = ProcessTools.createJavaProcessBuilder(
-                vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize));
+                "-XaddExports:java.management/sun.management=ALL-UNNAMED", vmArgs, "JMapHProfLargeHeapProc", String.valueOf(heapSize));
         procBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
         Process largeHeapProc = procBuilder.start();
 
diff --git a/hotspot/test/testlibrary/ClassFileInstaller.java b/hotspot/test/testlibrary/ClassFileInstaller.java
index 4e042da..2c1541d 100644
--- a/hotspot/test/testlibrary/ClassFileInstaller.java
+++ b/hotspot/test/testlibrary/ClassFileInstaller.java
@@ -23,6 +23,7 @@
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.io.ByteArrayInputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -38,22 +39,47 @@
      */
     public static void main(String... args) throws Exception {
         for (String arg : args) {
-            ClassLoader cl = ClassFileInstaller.class.getClassLoader();
-
-            // Convert dotted class name to a path to a class file
-            String pathName = arg.replace('.', '/').concat(".class");
-            InputStream is = cl.getResourceAsStream(pathName);
-            if (is == null) {
-                throw new FileNotFoundException(pathName);
-            }
-
-            // Create the class file's package directory
-            Path p = Paths.get(pathName);
-            if (pathName.contains("/")) {
-                Files.createDirectories(p.getParent());
-            }
-            // Create the class file
-            Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+            writeClassToDisk(arg);
         }
     }
+
+    public static void writeClassToDisk(String className) throws Exception {
+        writeClassToDisk(className, "");
+    }
+
+    public static void writeClassToDisk(String className, String prependPath) throws Exception {
+        ClassLoader cl = ClassFileInstaller.class.getClassLoader();
+
+        // Convert dotted class name to a path to a class file
+        String pathName = className.replace('.', '/').concat(".class");
+        InputStream is = cl.getResourceAsStream(pathName);
+        if (prependPath.length() > 0) {
+            pathName = prependPath + "/" + pathName;
+        }
+        writeToDisk(pathName, is);
+    }
+
+    public static void writeClassToDisk(String className, byte[] bytecode) throws Exception {
+        writeClassToDisk(className, bytecode, "");
+    }
+
+    public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception {
+        // Convert dotted class name to a path to a class file
+        String pathName = className.replace('.', '/').concat(".class");
+        if (prependPath.length() > 0) {
+            pathName = prependPath + "/" + pathName;
+        }
+        writeToDisk(pathName, new ByteArrayInputStream(bytecode));
+    }
+
+
+    private static void writeToDisk(String pathName, InputStream is) throws Exception {
+        // Create the class file's package directory
+        Path p = Paths.get(pathName);
+        if (pathName.contains("/")) {
+            Files.createDirectories(p.getParent());
+        }
+        // Create the class file
+        Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+    }
 }
diff --git a/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java b/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java
index 80439f8..8384b28 100644
--- a/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java
+++ b/hotspot/test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java
@@ -128,12 +128,13 @@
      *
      * @param className The name of the class
      * @param sourceCode The source code for the class with name {@code className}
+     * @param options additional command line options
      * @throws RuntimeException if the compilation did not succeed
      * @return The resulting byte code from the compilation
      */
-    public static byte[] compile(String className, CharSequence sourceCode) {
+    public static byte[] compile(String className, CharSequence sourceCode, String... options) {
         MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode);
-        CompilationTask task = getCompilationTask(file);
+        CompilationTask task = getCompilationTask(file, options);
 
         if(!task.call()) {
             throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode);
@@ -146,7 +147,7 @@
         return ToolProvider.getSystemJavaCompiler();
     }
 
-    private static CompilationTask getCompilationTask(MemoryJavaFileObject file) {
-        return getCompiler().getTask(null, new FileManagerWrapper(file), null, null, null, Arrays.asList(file));
+    private static CompilationTask getCompilationTask(MemoryJavaFileObject file, String... options) {
+        return getCompiler().getTask(null, new FileManagerWrapper(file), null, Arrays.asList(options), null, Arrays.asList(file));
     }
 }
diff --git a/hotspot/test/testlibrary/jdk/test/lib/PerfCounter.java b/hotspot/test/testlibrary/jdk/test/lib/PerfCounter.java
deleted file mode 100644
index fe0bd1d..0000000
--- a/hotspot/test/testlibrary/jdk/test/lib/PerfCounter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2013, 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 jdk.test.lib;
-
-import sun.jvmstat.monitor.Monitor;
-
-/**
- * Represents a performance counter in the JVM.
- *
- * See http://openjdk.java.net/groups/hotspot/docs/Serviceability.html#bjvmstat
- * for more details about performance counters.
- */
-public class PerfCounter {
-    private final Monitor monitor;
-    private final String name;
-
-    PerfCounter(Monitor monitor, String name) {
-        this.monitor = monitor;
-        this.name = name;
-    }
-
-    /**
-     * Returns the value of this performance counter as a long.
-     *
-     * @return The long value of this performance counter
-     * @throws RuntimeException If the value of the performance counter isn't a long
-     */
-    public long longValue() {
-        Object value = monitor.getValue();
-        if (value instanceof Long) {
-            return ((Long) value).longValue();
-        }
-        throw new RuntimeException("Expected " + monitor.getName() + " to have a long value");
-    }
-
-    /**
-     * Returns the name of the performance counter.
-     *
-     * @return The name of the performance counter.
-     */
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-}
diff --git a/hotspot/test/testlibrary/jdk/test/lib/PerfCounters.java b/hotspot/test/testlibrary/jdk/test/lib/PerfCounters.java
deleted file mode 100644
index 5db6a04..0000000
--- a/hotspot/test/testlibrary/jdk/test/lib/PerfCounters.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013, 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 jdk.test.lib;
-
-import sun.jvmstat.monitor.Monitor;
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.VmIdentifier;
-
-/**
- * PerfCounters can be used to get a performance counter from the currently
- * executing VM.
- *
- * Throws a runtime exception if an error occurs while communicating with the
- * currently executing VM.
- */
-public class PerfCounters {
-    private final static MonitoredVm vm;
-
-    static {
-        try {
-            String pid = Integer.toString(ProcessTools.getProcessId());
-            VmIdentifier vmId = new VmIdentifier(pid);
-            MonitoredHost host = MonitoredHost.getMonitoredHost(vmId);
-            vm = host.getMonitoredVm(vmId);
-        } catch (Exception e) {
-            throw new RuntimeException("Could not connect to the VM");
-        }
-    }
-
-    /**
-     * Returns the performance counter with the given name.
-     *
-     * @param name The name of the performance counter.
-     * @throws IllegalArgumentException If no counter with the given name exists.
-     * @throws MonitorException If an error occurs while communicating with the VM.
-     * @return The performance counter with the given name.
-     */
-    public static PerfCounter findByName(String name)
-        throws MonitorException, IllegalArgumentException {
-        Monitor m = vm.findByName(name);
-        if (m == null) {
-            throw new IllegalArgumentException("Did not find a performance counter with name " + name);
-        }
-        return new PerfCounter(m, name);
-    }
-}
diff --git a/hotspot/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java b/hotspot/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java
index e1bb112..5fd3326 100644
--- a/hotspot/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java
+++ b/hotspot/test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java
@@ -101,6 +101,7 @@
                     throws Throwable {
         List<String> finalOptions = new ArrayList<>();
         if (addTestVMOptions) {
+            Collections.addAll(finalOptions, ProcessTools.getVmInputArgs());
             Collections.addAll(finalOptions, Utils.getTestJavaOpts());
         }
         Collections.addAll(finalOptions, options);
diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
new file mode 100644
index 0000000..367e469
--- /dev/null
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ */
+
+package sun.hotspot;
+
+import java.lang.reflect.Executable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.security.BasicPermission;
+
+import sun.hotspot.parser.DiagnosticCommand;
+
+public class WhiteBox {
+
+  @SuppressWarnings("serial")
+  public static class WhiteBoxPermission extends BasicPermission {
+    public WhiteBoxPermission(String s) {
+      super(s);
+    }
+  }
+
+  private WhiteBox() {}
+  private static final WhiteBox instance = new WhiteBox();
+  private static native void registerNatives();
+
+  /**
+   * Returns the singleton WhiteBox instance.
+   *
+   * The returned WhiteBox object should be carefully guarded
+   * by the caller, since it can be used to read and write data
+   * at arbitrary memory addresses. It must never be passed to
+   * untrusted code.
+   */
+  public synchronized static WhiteBox getWhiteBox() {
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null) {
+      sm.checkPermission(new WhiteBoxPermission("getInstance"));
+    }
+    return instance;
+  }
+
+  static {
+    registerNatives();
+  }
+
+  // Get the maximum heap size supporting COOPs
+  public native long getCompressedOopsMaxHeapSize();
+  // Arguments
+  public native void printHeapSizes();
+
+  // Memory
+  public native long getObjectAddress(Object o);
+  public native int  getHeapOopSize();
+  public native int  getVMPageSize();
+  public native boolean isObjectInOldGen(Object o);
+  public native long getObjectSize(Object o);
+
+  // Runtime
+  // Make sure class name is in the correct format
+  public boolean isClassAlive(String name) {
+    return isClassAlive0(name.replace('.', '/'));
+  }
+  private native boolean isClassAlive0(String name);
+
+  // JVMTI
+  public native void addToBootstrapClassLoaderSearch(String segment);
+  public native void addToSystemClassLoaderSearch(String segment);
+
+  // G1
+  public native boolean g1InConcurrentMark();
+  public native boolean g1IsHumongous(Object o);
+  public native long    g1NumFreeRegions();
+  public native int     g1RegionSize();
+  public native Object[]    parseCommandLine(String commandline, char delim, DiagnosticCommand[] args);
+
+  // NMT
+  public native long NMTMalloc(long size);
+  public native void NMTFree(long mem);
+  public native long NMTReserveMemory(long size);
+  public native void NMTCommitMemory(long addr, long size);
+  public native void NMTUncommitMemory(long addr, long size);
+  public native void NMTReleaseMemory(long addr, long size);
+  public native long NMTMallocWithPseudoStack(long size, int index);
+  public native boolean NMTIsDetailSupported();
+  public native boolean NMTChangeTrackingLevel();
+  public native int NMTGetHashSize();
+
+  // Compiler
+  public native void    deoptimizeAll();
+  public        boolean isMethodCompiled(Executable method) {
+    return isMethodCompiled(method, false /*not osr*/);
+  }
+  public native boolean isMethodCompiled(Executable method, boolean isOsr);
+  public        boolean isMethodCompilable(Executable method) {
+    return isMethodCompilable(method, -1 /*any*/);
+  }
+  public        boolean isMethodCompilable(Executable method, int compLevel) {
+    return isMethodCompilable(method, compLevel, false /*not osr*/);
+  }
+  public native boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr);
+  public native boolean isMethodQueuedForCompilation(Executable method);
+  public        int     deoptimizeMethod(Executable method) {
+    return deoptimizeMethod(method, false /*not osr*/);
+  }
+  public native int     deoptimizeMethod(Executable method, boolean isOsr);
+  public        void    makeMethodNotCompilable(Executable method) {
+    makeMethodNotCompilable(method, -1 /*any*/);
+  }
+  public        void    makeMethodNotCompilable(Executable method, int compLevel) {
+    makeMethodNotCompilable(method, compLevel, false /*not osr*/);
+  }
+  public native void    makeMethodNotCompilable(Executable method, int compLevel, boolean isOsr);
+  public        int     getMethodCompilationLevel(Executable method) {
+    return getMethodCompilationLevel(method, false /*not ost*/);
+  }
+  public native int     getMethodCompilationLevel(Executable method, boolean isOsr);
+  public native boolean testSetDontInlineMethod(Executable method, boolean value);
+  public        int     getCompileQueuesSize() {
+    return getCompileQueueSize(-1 /*any*/);
+  }
+  public native int     getCompileQueueSize(int compLevel);
+  public native boolean testSetForceInlineMethod(Executable method, boolean value);
+  public        boolean enqueueMethodForCompilation(Executable method, int compLevel) {
+    return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/);
+  }
+  public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
+  public native void    clearMethodState(Executable method);
+  public native void    lockCompilation();
+  public native void    unlockCompilation();
+  public native int     getMethodEntryBci(Executable method);
+  public native Object[] getNMethod(Executable method, boolean isOsr);
+  public native long    allocateCodeBlob(int size, int type);
+  public        long    allocateCodeBlob(long size, int type) {
+      int intSize = (int) size;
+      if ((long) intSize != size || size < 0) {
+          throw new IllegalArgumentException(
+                "size argument has illegal value " + size);
+      }
+      return allocateCodeBlob( intSize, type);
+  }
+  public native void    freeCodeBlob(long addr);
+  public        void    forceNMethodSweep() {
+    try {
+        forceNMethodSweep0().join();
+    } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+    }
+  }
+  public native Thread  forceNMethodSweep0();
+  public native Object[] getCodeHeapEntries(int type);
+  public native int     getCompilationActivityMode();
+  public native Object[] getCodeBlob(long addr);
+
+  // Intered strings
+  public native boolean isInStringTable(String str);
+
+  // Memory
+  public native void readReservedMemory();
+  public native long allocateMetaspace(ClassLoader classLoader, long size);
+  public native void freeMetaspace(ClassLoader classLoader, long addr, long size);
+  public native long incMetaspaceCapacityUntilGC(long increment);
+  public native long metaspaceCapacityUntilGC();
+
+  // Force Young GC
+  public native void youngGC();
+
+  // Force Full GC
+  public native void fullGC();
+
+  // Method tries to start concurrent mark cycle.
+  // It returns false if CM Thread is always in concurrent cycle.
+  public native boolean g1StartConcMarkCycle();
+
+  // Tests on ReservedSpace/VirtualSpace classes
+  public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations);
+  public native void runMemoryUnitTests();
+  public native void readFromNoaccessArea();
+  public native long getThreadStackSize();
+  public native long getThreadRemainingStackSize();
+
+  // CPU features
+  public native String getCPUFeatures();
+
+  // Native extensions
+  public native long getHeapUsageForContext(int context);
+  public native long getHeapRegionCountForContext(int context);
+  public native int getContextForObject(Object obj);
+  public native void printRegionInfo(int context);
+
+  // VM flags
+  public native boolean isConstantVMFlag(String name);
+  public native boolean isLockedVMFlag(String name);
+  public native void    setBooleanVMFlag(String name, boolean value);
+  public native void    setIntxVMFlag(String name, long value);
+  public native void    setUintxVMFlag(String name, long value);
+  public native void    setUint64VMFlag(String name, long value);
+  public native void    setSizeTVMFlag(String name, long value);
+  public native void    setStringVMFlag(String name, String value);
+  public native void    setDoubleVMFlag(String name, double value);
+  public native Boolean getBooleanVMFlag(String name);
+  public native Long    getIntxVMFlag(String name);
+  public native Long    getUintxVMFlag(String name);
+  public native Long    getUint64VMFlag(String name);
+  public native Long    getSizeTVMFlag(String name);
+  public native String  getStringVMFlag(String name);
+  public native Double  getDoubleVMFlag(String name);
+  private final List<Function<String,Object>> flagsGetters = Arrays.asList(
+    this::getBooleanVMFlag, this::getIntxVMFlag, this::getUintxVMFlag,
+    this::getUint64VMFlag, this::getSizeTVMFlag, this::getStringVMFlag,
+    this::getDoubleVMFlag);
+
+  public Object getVMFlag(String name) {
+    return flagsGetters.stream()
+                       .map(f -> f.apply(name))
+                       .filter(x -> x != null)
+                       .findAny()
+                       .orElse(null);
+  }
+
+  // Jigsaw
+  public native Object DefineModule(String name, Object loader, Object[] packages);
+  public native void AddModuleExports(Object from_module, String pkg, Object to_module);
+  public native void AddReadsModule(Object from_module, Object to_module);
+  public native boolean CanReadModule(Object asking_module, Object target_module);
+  public native boolean IsExportedToModule(Object from_module, String pkg, Object to_module);
+  public native Object GetModule(Class clazz);
+  public native void AddModulePackage(Object module, String pkg);
+
+  // Image File
+  public native boolean readImageFile(String imagefile);
+
+  public native int getOffsetForName0(String name);
+  public int getOffsetForName(String name) throws Exception {
+    int offset = getOffsetForName0(name);
+    if (offset == -1) {
+      throw new RuntimeException(name + " not found");
+    }
+    return offset;
+  }
+
+}
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 9a01ef5..734c653 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -352,3 +352,4 @@
 781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107
 3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108
 24e247ee1fffaa625d480b2a4eef2d3a8a59f5cb jdk-9+109
+1c1bb661d35b846dc04931bd5f687a0348f80345 jdk-9+110
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java
index 6dd5c14..b5d9464 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Constants.java
@@ -505,4 +505,15 @@
         = "com.sun.org.apache.xalan.internal.xsltc.compiler.Fallback";
 
     public static final int RTF_INITIAL_SIZE = 32;
+
+    // the API packages used by generated translet classes
+    public static String[] PKGS_USED_BY_TRANSLET_CLASSES = {
+        "com.sun.org.apache.xalan.internal.lib",
+        "com.sun.org.apache.xalan.internal.xsltc",
+        "com.sun.org.apache.xalan.internal.xsltc.runtime",
+        "com.sun.org.apache.xalan.internal.xsltc.dom",
+        "com.sun.org.apache.xml.internal.serializer",
+        "com.sun.org.apache.xml.internal.dtm",
+        "com.sun.org.apache.xml.internal.dtm.ref",
+    };
 }
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
index efbbe78..9c771af 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
@@ -47,6 +47,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Objects;
 import java.util.Vector;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
@@ -115,7 +116,7 @@
     private boolean _debug = false;      // -x
     private String  _jarFileName = null; // -j <jar-file-name>
     private String  _className = null;   // -o <class-name>
-    private String  _packageName = null; // -p <package-name>
+    private String  _packageName = "die.verwandlung"; // override with -p <package-name>
     private File    _destDir = null;     // -d <directory-name>
     private int     _outputType = FILE_OUTPUT; // by default
 
@@ -724,7 +725,7 @@
      * Set an optional package name for the translet and auxiliary classes
      */
     public void setPackageName(String packageName) {
-        _packageName = packageName;
+        _packageName = Objects.requireNonNull(packageName);
         if (_className != null) setClassName(_className);
     }
 
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 e0ee6fb..bab1609 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
@@ -28,6 +28,7 @@
 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
 import com.sun.org.apache.xalan.internal.xsltc.DOM;
 import com.sun.org.apache.xalan.internal.xsltc.Translet;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 import java.io.IOException;
@@ -36,8 +37,11 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.lang.reflect.Module;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -47,6 +51,8 @@
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.URIResolver;
 
+import jdk.internal.module.Modules;
+
 /**
  * @author Morten Jorgensen
  * @author G. Todd Millerj
@@ -410,6 +416,31 @@
                 _auxClasses = new HashMap<>();
             }
 
+            // create a module for the translet
+            Module xmlModule = TemplatesImpl.class.getModule();
+            String pn = _tfactory.getPackageName();
+            assert pn != null && pn.length() > 0;
+
+            Module m = Modules.defineModule(loader, "jdk.translet",
+                                            Collections.singleton(pn));
+
+            // jdk.translate reads java.base && java.xml
+            Modules.addReads(m, Object.class.getModule());
+            Modules.addReads(m, xmlModule);
+
+            // jdk.translet needs access to runtime classes
+            Arrays.asList(Constants.PKGS_USED_BY_TRANSLET_CLASSES).forEach(p -> {
+                xmlModule.addExports(p, m);
+            });
+
+            // jdk.translate also needs to be loose as the XSL may bind to
+            // java types in an unnamed module
+            Modules.addReads(m, null);
+
+            // java.xml needs to instanitate the translate class
+            xmlModule.addReads(m);
+            Modules.addExports(m, pn, xmlModule);
+
             for (int i = 0; i < classCount; i++) {
                 _class[i] = loader.defineClass(_bytecodes[i]);
                 final Class superClass = _class[i].getSuperclass();
@@ -434,7 +465,7 @@
         }
         catch (LinkageError e) {
             ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);
-            throw new TransformerConfigurationException(err.toString());
+            throw new TransformerConfigurationException(err.toString(), e);
         }
     }
 
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
index 24e07ae..261853c 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
@@ -137,7 +137,8 @@
     /**
      * The package name prefix for all generated translet classes
      */
-    private String _packageName = null;
+    private static final String DEFAULT_TRANSLATE_PACKAGE = "die.verwandlung";
+    private String _packageName = DEFAULT_TRANSLATE_PACKAGE;
 
     /**
      * The jar file name which the translet classes are packaged into
@@ -308,6 +309,13 @@
     }
 
     /**
+     * Returns the package name.
+     */
+    String getPackageName() {
+        return _packageName;
+    }
+
+    /**
      * javax.xml.transform.sax.TransformerFactory implementation.
      * Returns the value set for a TransformerFactory attribute
      *
@@ -884,7 +892,7 @@
             String transletClassName = getTransletBaseName(source);
 
             if (_packageName != null)
-                transletClassName = _packageName + "." + transletClassName;
+               transletClassName = _packageName + "." + transletClassName;
 
             if (_jarFileName != null)
                 bytecodes = getBytecodesFromJar(source, transletClassName);
@@ -1286,7 +1294,7 @@
     private void resetTransientAttributes() {
         _transletName = DEFAULT_TRANSLET_NAME;
         _destinationDirectory = null;
-        _packageName = null;
+        _packageName = DEFAULT_TRANSLATE_PACKAGE;
         _jarFileName = null;
     }
 
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java
index f216fc9..fe37af5 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java
@@ -24,7 +24,6 @@
  */
 package com.sun.org.apache.xpath.internal.compiler;
 
-import com.sun.org.apache.xpath.internal.Expression;
 import com.sun.org.apache.xpath.internal.functions.Function;
 import java.util.HashMap;
 import javax.xml.transform.TransformerException;
@@ -341,11 +340,12 @@
           throws javax.xml.transform.TransformerException
   {
           try{
-              if (which < NUM_BUILT_IN_FUNCS)
+              if (which < NUM_BUILT_IN_FUNCS) {
                   return (Function) m_functions[which].newInstance();
-              else
-                  return (Function) m_functions_customer[
-                      which-NUM_BUILT_IN_FUNCS].newInstance();
+              } else {
+                  Class<?> c =  m_functions_customer[which-NUM_BUILT_IN_FUNCS];
+                  return (Function) c.newInstance();
+              }
           }catch (IllegalAccessException ex){
                   throw new TransformerException(ex.getMessage());
           }catch (InstantiationException ex){
diff --git a/jaxp/src/java.xml/share/classes/module-info.java b/jaxp/src/java.xml/share/classes/module-info.java
new file mode 100644
index 0000000..3bd3fa3
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/module-info.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.xml {
+    exports javax.xml;
+    exports javax.xml.catalog;
+    exports javax.xml.datatype;
+    exports javax.xml.namespace;
+    exports javax.xml.parsers;
+    exports javax.xml.stream;
+    exports javax.xml.stream.events;
+    exports javax.xml.stream.util;
+    exports javax.xml.transform;
+    exports javax.xml.transform.dom;
+    exports javax.xml.transform.sax;
+    exports javax.xml.transform.stax;
+    exports javax.xml.transform.stream;
+    exports javax.xml.validation;
+    exports javax.xml.xpath;
+    exports org.w3c.dom;
+    exports org.w3c.dom.bootstrap;
+    exports org.w3c.dom.events;
+    exports org.w3c.dom.ls;
+    exports org.w3c.dom.ranges;
+    exports org.w3c.dom.traversal;
+    exports org.w3c.dom.views;
+    exports org.xml.sax;
+    exports org.xml.sax.ext;
+    exports org.xml.sax.helpers;
+    exports com.sun.org.apache.xerces.internal.dom to
+        java.xml.ws;
+    exports com.sun.org.apache.xerces.internal.jaxp to
+        java.xml.ws;
+    exports com.sun.org.apache.xerces.internal.util to
+        java.xml.ws;
+    exports com.sun.org.apache.xml.internal.dtm to
+        java.xml.crypto;
+    exports com.sun.org.apache.xml.internal.resolver to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.org.apache.xml.internal.resolver.tools to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.org.apache.xml.internal.utils to
+        java.xml.crypto;
+    exports com.sun.org.apache.xpath.internal to
+        java.xml.crypto;
+    exports com.sun.org.apache.xpath.internal.compiler to
+        java.xml.crypto;
+    exports com.sun.org.apache.xpath.internal.functions to
+        java.xml.crypto;
+    exports com.sun.org.apache.xpath.internal.objects to
+        java.xml.crypto;
+    exports com.sun.org.apache.xpath.internal.res to
+        java.xml.crypto;
+    // reflection access from com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory
+    exports com.sun.xml.internal.stream.writers to java.xml.ws;
+    uses javax.xml.datatype.DatatypeFactory;
+    uses javax.xml.parsers.DocumentBuilderFactory;
+    uses javax.xml.parsers.SAXParserFactory;
+    uses javax.xml.stream.XMLEventFactory;
+    uses javax.xml.stream.XMLInputFactory;
+    uses javax.xml.stream.XMLOutputFactory;
+    uses javax.xml.transform.TransformerFactory;
+    uses javax.xml.validation.SchemaFactory;
+    uses javax.xml.xpath.XPathFactory;
+}
+
diff --git a/jaxp/src/jdk.xml.dom/share/classes/module-info.java b/jaxp/src/jdk.xml.dom/share/classes/module-info.java
new file mode 100644
index 0000000..a75c8f3
--- /dev/null
+++ b/jaxp/src/jdk.xml.dom/share/classes/module-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.xml.dom {
+    requires public java.xml;
+    exports org.w3c.dom.css;
+    exports org.w3c.dom.html;
+    exports org.w3c.dom.stylesheets;
+    exports org.w3c.dom.xpath;
+}
+
diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT
index b78892a..4b6b17d 100644
--- a/jaxp/test/TEST.ROOT
+++ b/jaxp/test/TEST.ROOT
@@ -18,4 +18,4 @@
 groups=TEST.groups 
 
 # Minimum jtreg version
-requiredVersion=4.1 b12
+requiredVersion=4.2 b01
diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
index b39bb20..93da2fd 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
+++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties
@@ -4,5 +4,5 @@
 lib.dirs = /javax/xml/jaxp/libs
 
 # Declare module dependency
-modules=java.xml
-
+modules=java.xml/com.sun.org.apache.xerces.internal.jaxp \
+        java.xml/com.sun.org.apache.xml.internal.serialize
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index d02e1de..93f5e2e 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -355,3 +355,4 @@
 fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107
 513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108
 4b0697e4ce8940b1599af274ff02296d7f59aded jdk-9+109
+0db939c930f332dfa275cedfc7cf223ff1221ea4 jdk-9+110
diff --git a/jaxws/src/java.activation/share/classes/javax/activation/DataContentHandler.java b/jaxws/src/java.activation/share/classes/javax/activation/DataContentHandler.java
index 8148095..8d429ef 100644
--- a/jaxws/src/java.activation/share/classes/javax/activation/DataContentHandler.java
+++ b/jaxws/src/java.activation/share/classes/javax/activation/DataContentHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,18 +33,23 @@
 import javax.activation.DataSource;
 
 /**
- * The DataContentHandler interface is implemented by objects that can
+ * <p>The DataContentHandler interface is implemented by objects that can
  * be used to extend the capabilities of the DataHandler's implementation
  * of the Transferable interface. Through <code>DataContentHandlers</code>
  * the framework can be extended to convert streams in to objects, and
- * to write objects to streams. <p>
+ * to write objects to streams.</p>
  *
- * Applications don't generally call the methods in DataContentHandlers
+ * <p>An implementation of DataContentHandler should be a public class
+ * with a public no-arg constructor. If the implementation class is in
+ * a named module then it should be in an API package that is exported
+ * to the module {@code java.activation}.</p>
+ *
+ * <p>Applications don't generally call the methods in DataContentHandlers
  * directly. Instead, an application calls the equivalent methods in
  * DataHandler. The DataHandler will attempt to find an appropriate
  * DataContentHandler that corresponds to its MIME type using the
  * current DataContentHandlerFactory. The DataHandler then calls
- * through to the methods in the DataContentHandler.
+ * through to the methods in the DataContentHandler.</p>
  *
  * @since 1.6
  */
diff --git a/jaxws/src/java.activation/share/classes/javax/activation/MailcapCommandMap.java b/jaxws/src/java.activation/share/classes/javax/activation/MailcapCommandMap.java
index dd7530c..29bc9ad 100644
--- a/jaxws/src/java.activation/share/classes/javax/activation/MailcapCommandMap.java
+++ b/jaxws/src/java.activation/share/classes/javax/activation/MailcapCommandMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -580,8 +580,7 @@
                 // if anything goes wrong, do it the old way
                 cl = Class.forName(name);
             }
-            if (cl != null)             // XXX - always true?
-                return (DataContentHandler)cl.newInstance();
+            return (DataContentHandler) cl.newInstance();
         } catch (IllegalAccessException e) {
             if (LogSupport.isLoggable())
                 LogSupport.log("Can't load DCH " + name, e);
diff --git a/jaxws/src/java.activation/share/classes/module-info.java b/jaxws/src/java.activation/share/classes/module-info.java
new file mode 100644
index 0000000..d650787
--- /dev/null
+++ b/jaxws/src/java.activation/share/classes/module-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.activation {
+    requires public java.datatransfer;
+    // dependence on java.beans.Beans to be eliminated
+    requires java.desktop;
+    requires java.logging;
+
+    exports javax.activation;
+}
+
diff --git a/jaxws/src/java.annotations.common/share/classes/module-info.java b/jaxws/src/java.annotations.common/share/classes/module-info.java
new file mode 100644
index 0000000..0a3a8dd
--- /dev/null
+++ b/jaxws/src/java.annotations.common/share/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.annotations.common {
+    exports javax.annotation;
+}
+
diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
index ce36be3..da4c5f3 100644
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
@@ -113,7 +113,6 @@
 
             m.put(clazz,new WeakReference<Constructor>(cons));
         }
-
         return cons.newInstance(emptyObject);
     }
 
diff --git a/jaxws/src/java.xml.bind/share/classes/module-info.java b/jaxws/src/java.xml.bind/share/classes/module-info.java
new file mode 100644
index 0000000..7f7cde8
--- /dev/null
+++ b/jaxws/src/java.xml.bind/share/classes/module-info.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.xml.bind {
+    requires public java.activation;
+    requires public java.xml;
+    requires java.compiler;
+    requires java.desktop;
+    requires java.logging;
+
+    uses javax.xml.bind.JAXBContextFactory;
+
+    exports javax.xml.bind;
+    exports javax.xml.bind.annotation;
+    exports javax.xml.bind.annotation.adapters;
+    exports javax.xml.bind.attachment;
+    exports javax.xml.bind.helpers;
+    exports javax.xml.bind.util;
+    exports com.sun.istack.internal to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.istack.internal.localization to
+        java.xml.ws,
+        jdk.xml.ws;
+    exports com.sun.istack.internal.logging to
+        java.xml.ws,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.annotation to
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.api to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.api.impl to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.marshaller to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.unmarshaller to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.util to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.v2 to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.v2.model.annotation to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.bind.v2.model.core to
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.v2.model.impl to
+        jdk.xml.bind;
+    exports 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
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.v2.runtime to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.v2.runtime.unmarshaller to
+        java.xml.ws;
+    exports com.sun.xml.internal.bind.v2.schemagen to
+        java.xml.ws,
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.v2.schemagen.episode to
+        jdk.xml.bind;
+    exports com.sun.xml.internal.bind.v2.schemagen.xmlschema to
+        java.xml.ws;
+    exports com.sun.xml.internal.bind.v2.util to
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.fastinfoset to
+        java.xml.ws;
+    exports com.sun.xml.internal.fastinfoset.stax to
+        java.xml.ws;
+    exports com.sun.xml.internal.fastinfoset.vocab to
+        java.xml.ws;
+    exports com.sun.xml.internal.org.jvnet.fastinfoset to
+        java.xml.ws;
+    exports com.sun.xml.internal.org.jvnet.mimepull to
+        java.xml.ws;
+    exports com.sun.xml.internal.org.jvnet.staxex to
+        java.xml.ws;
+    exports com.sun.xml.internal.org.jvnet.staxex.util to
+        java.xml.ws;
+    exports com.sun.xml.internal.txw2 to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.txw2.annotation to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+    exports com.sun.xml.internal.txw2.output to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
+}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/server/SDDocumentSource.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/server/SDDocumentSource.java
index ccd1b3d..0c774aa 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/server/SDDocumentSource.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/server/SDDocumentSource.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package com.sun.xml.internal.ws.api.server;
 
 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
+import com.sun.xml.internal.ws.server.ServerRtException;
 import com.sun.xml.internal.ws.streaming.TidyXMLStreamReader;
 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
 
@@ -34,6 +35,7 @@
 import javax.xml.stream.XMLStreamReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
 
 /**
@@ -112,6 +114,48 @@
     }
 
     /**
+     * Creates {@link SDDocumentSource} from resource path using resolvingClass to read the resource.
+     * Required for Jigsaw runtime.
+     *
+     * @param resolvingClass class used to read resource
+     * @param path resource path
+     */
+    public static SDDocumentSource create(final Class resolvingClass, final String path) {
+        return new SDDocumentSource() {
+
+            public XMLStreamReader read(XMLInputFactory xif) throws IOException, XMLStreamException {
+                InputStream is = inputStream();
+                return new TidyXMLStreamReader(xif.createXMLStreamReader(path,is), is);
+            }
+
+            public XMLStreamReader read() throws IOException, XMLStreamException {
+                InputStream is = inputStream();
+                return new TidyXMLStreamReader(XMLStreamReaderFactory.create(path,is,false), is);
+            }
+
+            public URL getSystemId() {
+                try {
+                    return new URL("file://" + path);
+                } catch (MalformedURLException e) {
+                    return null;
+                }
+            }
+
+            private InputStream inputStream() throws IOException {
+                java.lang.reflect.Module module = resolvingClass.getModule();
+                if (module != null) {
+                    InputStream stream = module.getResourceAsStream(path);
+                    if (stream != null) {
+                        return stream;
+                    }
+                }
+                throw new ServerRtException("cannot.load.wsdl", path);
+            }
+
+        };
+    }
+
+    /**
      * Creates a {@link SDDocumentSource} from {@link XMLStreamBuffer}.
      */
     public static SDDocumentSource create(final URL systemId, final XMLStreamBuffer xsb) {
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/EndpointImpl.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/EndpointImpl.java
index 82db6e9..9f23f51 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/EndpointImpl.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/EndpointImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -372,7 +372,7 @@
             if (url != null) {
                 return SDDocumentSource.create(url);
             }
-            throw new ServerRtException("cannot.load.wsdl", wsdlLocation);
+            return SDDocumentSource.create(implClass, wsdlLocation);
         }
         return null;
     }
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/HandlerAnnotationProcessor.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/HandlerAnnotationProcessor.java
index 37e7a20..4238523 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/HandlerAnnotationProcessor.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/HandlerAnnotationProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,28 +197,62 @@
         return null;
     }
 
-   static InputStream getFileAsStream(Class clazz, HandlerChain chain) {
-        URL url = clazz.getResource(chain.file());
-        if (url == null) {
-            url = Thread.currentThread().getContextClassLoader().
-                getResource(chain.file());
-        }
-        if (url == null) {
-            String tmp = clazz.getPackage().getName();
-            tmp = tmp.replace('.', '/');
-            tmp += "/" + chain.file();
-            url =
-                Thread.currentThread().getContextClassLoader().getResource(tmp);
-        }
+    static InputStream getFileAsStream(Class clazz, HandlerChain chain) {
+        Package pkg = clazz.getPackage();
+        String filename = chain.file();
+        String fullpath = addPackagePath(filename, pkg);
+        InputStream is;
+
+        is = moduleResource(clazz, filename);
+        if (is != null) return is;
+
+        is = moduleResource(clazz, fullpath);
+        if (is != null) return is;
+
+        URL url = cpResource(clazz, filename);
+        if (url == null) url = cpResource(clazz, fullpath);
+
         if (url == null) {
             throw new UtilException("util.failed.to.find.handlerchain.file",
-                clazz.getName(), chain.file());
+                    clazz.getName(), filename);
         }
         try {
             return url.openStream();
         } catch (IOException e) {
             throw new UtilException("util.failed.to.parse.handlerchain.file",
-                clazz.getName(), chain.file());
+                    clazz.getName(), filename);
         }
     }
+
+    private static URL cpResource(Class clazz, String name) {
+        URL url = clazz.getResource(name);
+        if (url == null) {
+            ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+            url = tccl.getResource(name);
+        }
+        return url;
+    }
+
+    private static InputStream moduleResource(Class resolvingClass, String name) {
+        java.lang.reflect.Module module = resolvingClass.getModule();
+        if (module != null) {
+            try {
+                InputStream stream = module.getResourceAsStream(name);
+                if (stream != null) {
+                    return stream;
+                }
+            } catch(IOException e) {
+                throw new UtilException("util.failed.to.find.handlerchain.file",
+                        resolvingClass.getName(), name);
+            }
+        }
+        return null;
+    }
+
+    private static String addPackagePath(String file, Package pkg) {
+        String tmp = pkg.getName();
+        tmp = tmp.replace('.', '/');
+        tmp += "/" + file;
+        return tmp;
+    }
 }
diff --git a/jaxws/src/java.xml.ws/share/classes/module-info.java b/jaxws/src/java.xml.ws/share/classes/module-info.java
new file mode 100644
index 0000000..799e0f2
--- /dev/null
+++ b/jaxws/src/java.xml.ws/share/classes/module-info.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.xml.ws {
+    requires public java.activation;
+    requires public java.xml;
+    requires public java.xml.bind;
+    requires java.annotations.common;
+    requires java.desktop;
+    requires java.logging;
+    requires java.management;
+    requires java.rmi;
+    requires jdk.httpserver;
+
+    uses javax.xml.ws.spi.Provider;
+    uses javax.xml.soap.MessageFactory;
+    uses javax.xml.soap.SAAJMetaFactory;
+    uses javax.xml.soap.SOAPConnectionFactory;
+    uses javax.xml.soap.SOAPFactory;
+
+    exports javax.jws;
+    exports javax.jws.soap;
+    exports javax.xml.soap;
+    exports javax.xml.ws;
+    exports javax.xml.ws.handler;
+    exports javax.xml.ws.handler.soap;
+    exports javax.xml.ws.http;
+    exports javax.xml.ws.soap;
+    exports javax.xml.ws.spi;
+    exports javax.xml.ws.spi.http;
+    exports javax.xml.ws.wsaddressing;
+
+    exports com.oracle.webservices.internal.api.databinding to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.addressing to
+        jdk.xml.ws,
+        java.xml.bind;
+    exports com.sun.xml.internal.ws.addressing.v200408 to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.addressing to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.databinding to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.model to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.server to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.streaming to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.wsdl.parser to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.api.wsdl.writer to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.binding to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.db to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.model to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.policy.sourcemodel.wspolicy to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.spi.db to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.streaming to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.util to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.util.exception to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.util.xml to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.wsdl.parser to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.ws.wsdl.writer to
+        jdk.xml.ws;
+
+    // XML document content needs to be exported
+    exports 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;
+
+    // JAF data handlers
+    exports com.sun.xml.internal.messaging.saaj.soap to
+        java.activation;
+    exports com.sun.xml.internal.ws.encoding to
+        java.activation;
+}
+
diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java
index 9e52348..e661b81 100644
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.net.URL;
 import java.text.ParseException;
 import java.util.Iterator;
 import java.util.List;
@@ -69,22 +68,17 @@
 
     private final JPackage pkg;
     private final String className;
-    private final URL source;
+    private final ResourceLoader source;
     private final JStaticClass clazz;
     private final LineFilter filter;
 
-    public JStaticJavaFile(JPackage _pkg, String className, String _resourceName) {
-        this( _pkg, className,
-            SecureLoader.getClassClassLoader(JStaticJavaFile.class).getResource(_resourceName), null );
-    }
-
-    public JStaticJavaFile(JPackage _pkg, String _className, URL _source, LineFilter _filter ) {
-        super(_className+".java");
-        if(_source==null)   throw new NullPointerException();
+    public JStaticJavaFile(JPackage _pkg, String _className, Class<?> loadingClass, LineFilter _filter) {
+        super(_className + ".java");
+        if (loadingClass == null) throw new NullPointerException();
         this.pkg = _pkg;
         this.clazz = new JStaticClass();
         this.className = _className;
-        this.source = _source;
+        this.source = new ResourceLoader(_className, loadingClass);
         this.filter = _filter;
     }
 
@@ -100,14 +94,13 @@
     }
 
     protected  void build(OutputStream os) throws IOException {
-        InputStream is = source.openStream();
-
-        BufferedReader r = new BufferedReader(new InputStreamReader(is));
-        PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os)));
-        LineFilter filter = createLineFilter();
         int lineNumber=1;
-
-        try {
+        try (
+                InputStream is = source.getResourceAsStream();
+                BufferedReader r = new BufferedReader(new InputStreamReader(is));
+                PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os)));
+        ) {
+            LineFilter filter = createLineFilter();
             String line;
             while((line=r.readLine())!=null) {
                 line = filter.process(line);
@@ -118,9 +111,6 @@
         } catch( ParseException e ) {
             throw new IOException("unable to process "+source+" line:"+lineNumber+"\n"+e.getMessage());
         }
-
-        w.close();
-        r.close();
     }
 
     /**
@@ -235,5 +225,32 @@
         protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
             return this;
         }
-    };
+    }
+
+    static class ResourceLoader {
+        Class<?> loadingClass;
+        String shortName;
+
+        ResourceLoader(String shortName, Class<?> loadingClass) {
+            this.loadingClass = loadingClass;
+            this.shortName = shortName;
+        }
+
+        InputStream getResourceAsStream() {
+            // some people didn't like our jars to contain files with .java extension,
+            // so when we build jars, we'' use ".java_". But when we run from the workspace,
+            // we want the original source code to be used, so we check both here.
+            // see bug 6211503.
+            InputStream stream = loadingClass.getResourceAsStream(shortName + ".java");
+            if (stream == null) {
+                stream = loadingClass.getResourceAsStream(shortName + ".java_");
+            }
+            if (stream == null) {
+                throw new InternalError("Unable to load source code of " + loadingClass.getName() + " as a resource");
+            }
+            return stream;
+        }
+
+    }
+
 }
diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/generator/bean/BeanGenerator.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/generator/bean/BeanGenerator.java
index 6b38381..01cf43a 100644
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/generator/bean/BeanGenerator.java
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/generator/bean/BeanGenerator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 import static com.sun.tools.internal.xjc.outline.Aspect.EXPOSED;
 
 import java.io.Serializable;
-import java.net.URL;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -809,26 +808,14 @@
     }
 
     public JClass generateStaticClass(Class src, JPackage out) {
-        String shortName = getShortName(src.getName());
-
-        // some people didn't like our jars to contain files with .java extension,
-        // so when we build jars, we'' use ".java_". But when we run from the workspace,
-        // we want the original source code to be used, so we check both here.
-        // see bug 6211503.
-        URL res = src.getResource(shortName + ".java");
-        if (res == null) {
-            res = src.getResource(shortName + ".java_");
-        }
-        if (res == null) {
-            throw new InternalError("Unable to load source code of " + src.getName() + " as a resource");
-        }
-
-        JStaticJavaFile sjf = new JStaticJavaFile(out, shortName, res, null);
+        JStaticJavaFile sjf = new JStaticJavaFile(out, getShortName(src), src, null);
         out.addResourceFile(sjf);
         return sjf.getJClass();
     }
 
-    private String getShortName(String name) {
+    private String getShortName(Class src) {
+        String name = src.getName();
         return name.substring(name.lastIndexOf('.') + 1);
     }
+
 }
diff --git a/jaxws/src/jdk.xml.bind/share/classes/module-info.java b/jaxws/src/jdk.xml.bind/share/classes/module-info.java
new file mode 100644
index 0000000..06faf9d
--- /dev/null
+++ b/jaxws/src/jdk.xml.bind/share/classes/module-info.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.xml.bind {
+    requires java.activation;
+    requires java.compiler;
+    requires java.desktop;
+    requires java.logging;
+    requires java.xml;
+    requires java.xml.bind;
+    requires jdk.compiler;
+
+    exports com.sun.codemodel.internal to
+        jdk.xml.ws;
+    exports com.sun.codemodel.internal.writer to
+        jdk.xml.ws;
+    exports com.sun.istack.internal.tools to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.jxc.ap to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.jxc.model.nav to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.xjc to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.xjc.api to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.xjc.reader to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.xjc.reader.internalizer to
+        jdk.xml.ws;
+    exports com.sun.tools.internal.xjc.util to
+        jdk.xml.ws;
+    exports com.sun.xml.internal.xsom.parser to
+        jdk.xml.ws;
+
+    // XML document content needs to be exported
+    exports 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;
+}
+
diff --git a/jaxws/src/jdk.xml.ws/share/classes/module-info.java b/jaxws/src/jdk.xml.ws/share/classes/module-info.java
new file mode 100644
index 0000000..9e5d44d
--- /dev/null
+++ b/jaxws/src/jdk.xml.ws/share/classes/module-info.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.xml.ws {
+    requires java.compiler;
+    requires java.logging;
+    requires java.rmi;
+    requires java.xml;
+    requires java.xml.bind;
+    requires java.xml.ws;
+    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;
+}
+
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 8d4f94f..49cf4dd 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -352,3 +352,4 @@
 8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107
 42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108
 1c7bad0798900fe58f4db01ae7ffdc84f5baee8c jdk-9+109
+9417e1bcded6af5532c3b26235437ab227758877 jdk-9+110
diff --git a/jdk/make/CompileInterimRmic.gmk b/jdk/make/CompileInterimRmic.gmk
index f31db8d..ce60127 100644
--- a/jdk/make/CompileInterimRmic.gmk
+++ b/jdk/make/CompileInterimRmic.gmk
@@ -44,8 +44,9 @@
 $(eval $(call SetupJavaCompilation,BUILD_INTERIM_RMIC, \
     SETUP := GENERATE_OLDBYTECODE, \
     SRC := $(JDK_TOPDIR)/src/jdk.rmic/share/classes, \
+    EXCLUDE_FILES := module-info.java, \
     INCLUDES := $(RMIC_PKGS), \
-    BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_rmic_classes, \
+    BIN := $(BUILDTOOLS_OUTPUTDIR)/override_modules/jdk.rmic, \
     COPY := .properties))
 
 ##########################################################################################
diff --git a/jdk/make/CompileTools.gmk b/jdk/make/CompileTools.gmk
index 27aaffa..46dab28 100644
--- a/jdk/make/CompileTools.gmk
+++ b/jdk/make/CompileTools.gmk
@@ -32,42 +32,12 @@
 
 ################################################################################
 
-JIMAGE_PKGS := \
-    jdk/internal/jimage \
-    jdk/internal/jrtfs \
-    #
-
-$(eval $(call SetupJavaCompilation,BUILD_INTERIM_JIMAGE, \
-    SETUP := GENERATE_OLDBYTECODE, \
-    SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
-    INCLUDES := $(JIMAGE_PKGS), \
-    BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes))
-
-TARGETS += $(BUILD_INTERIM_JIMAGE)
-
-# Because of the explicit INCLUDES in the compilation setup above, the service provider
-# file will not be copied unless META-INF/services would also be added to the INCLUDES.
-# Adding META-INF/services would include all files in that directory when only the one
-# is needed, which is why this explicit copy is defined instead.
-$(eval $(call SetupCopyFiles,COPY_JIMAGE_SERVICE_PROVIDER, \
-    SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
-    DEST := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \
-    FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
-
-TARGETS += $(COPY_JIMAGE_SERVICE_PROVIDER)
-
-################################################################################
-
 $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
     SETUP := GENERATE_OLDBYTECODE, \
-    ADD_JAVAC_FLAGS := -Xbootclasspath/p:$(call PathList, \
-        $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes \
-        $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes), \
     SRC := $(JDK_TOPDIR)/make/src/classes $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes, \
-    BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
-    COPY := boot.modules ext.modules))
-
-$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE) $(COPY_JIMAGE_SERVICE_PROVIDER)
+    EXCLUDES := build/tools/deps \
+                build/tools/jigsaw, \
+    BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes))
 
 TARGETS += $(BUILD_TOOLS_JDK)
 
diff --git a/jdk/make/GenerateModuleSummary.gmk b/jdk/make/GenerateModuleSummary.gmk
new file mode 100644
index 0000000..285de73
--- /dev/null
+++ b/jdk/make/GenerateModuleSummary.gmk
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Default target declared first
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include ModuleTools.gmk
+
+GENGRAPHS_DIR := $(IMAGES_OUTPUTDIR)/gengraphs
+TOOLS_MODULE_SRCDIR := $(JDK_TOPDIR)/make/src/classes/build/tools/jigsaw
+
+$(GENGRAPHS_DIR)/jdk.dot: $(BUILD_JIGSAW_TOOLS)
+	$(MKDIR) -p $(@D)
+	$(TOOL_GENGRAPHS) $(GENGRAPHS_DIR)
+
+$(GENGRAPHS_DIR)/technology-summary.html: $(TOOLS_MODULE_SRCDIR)/technology-summary.html
+	$(install-file)
+
+$(GENGRAPHS_DIR)/module-summary.html: $(BUILD_JIGSAW_TOOLS) $(GENGRAPHS_DIR)/technology-summary.html
+	$(MKDIR) -p $(@D)
+	$(TOOL_MODULESUMMARY) -o $@ -mp $(IMAGES_OUTPUTDIR)/jmods
+
+all: $(GENGRAPHS_DIR)/jdk.dot $(GENGRAPHS_DIR)/module-summary.html
diff --git a/jdk/make/ModuleTools.gmk b/jdk/make/ModuleTools.gmk
new file mode 100644
index 0000000..2943b9c
--- /dev/null
+++ b/jdk/make/ModuleTools.gmk
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include $(SPEC)
+include MakeBase.gmk
+include JavaCompilation.gmk
+include SetupJavaCompilers.gmk
+
+TOOLS_CLASSES_DIR := $(BUILDTOOLS_OUTPUTDIR)/tools_jigsaw_classes
+
+$(eval $(call SetupJavaCompilation,BUILD_JIGSAW_TOOLS, \
+    SETUP := GENERATE_USINGJDKBYTECODE, \
+    SRC := $(JDK_TOPDIR)/make/src/classes, \
+    INCLUDES := build/tools/deps \
+                build/tools/jigsaw, \
+    BIN := $(TOOLS_CLASSES_DIR), \
+    ADD_JAVAC_FLAGS := -XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED ))
+
+
+TOOL_GENGRAPHS := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
+    build.tools.jigsaw.GenGraphs
+
+TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
+    -XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
+    build.tools.jigsaw.ModuleSummary
diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk
index a087e3c..1ae471d 100644
--- a/jdk/make/Tools.gmk
+++ b/jdk/make/Tools.gmk
@@ -41,7 +41,12 @@
 TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
     build.tools.addjsum.AddJsum
 
+ifeq ($(BOOT_JDK_MODULAR), true)
+  COMPILEFONTCONFIG_ADD_EXPORTS := -XaddExports:java.desktop/sun.awt=ALL-UNNAMED
+endif
+
 TOOL_COMPILEFONTCONFIG = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
+    $(COMPILEFONTCONFIG_ADD_EXPORTS) \
     build.tools.compilefontconfig.CompileFontConfig
 
 TOOL_COMPILEPROPERTIES = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
@@ -106,12 +111,18 @@
 TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
     build.tools.cldrconverter.CLDRConverter
 
-TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
-    -cp $(call PathList, $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes $(JDK_OUTPUTDIR)) \
+TOOL_GENMODULESXML = $(JAVA_SMALL) $(INTERIM_LANGTOOLS_BOOTCLASSPATH) \
+    -cp $(call PathList, $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes) \
     build.tools.module.GenJdepsModulesXml
 
-TOOL_IMAGEBUILDER = $(JAVA_SMALL) -Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes \
-    -cp $(call PathList, $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes $(JDK_OUTPUTDIR)) \
-    build.tools.module.ImageBuilder
+TOOL_GENMODULEINFOSOURCE = $(JAVA_SMALL) $(INTERIM_LANGTOOLS_BOOTCLASSPATH) \
+    -cp $(call PathList, $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes) \
+    build.tools.module.GenModuleInfoSource
+
+TOOL_GENCLASSLOADERMAP = $(JAVA_SMALL) $(INTERIM_LANGTOOLS_BOOTCLASSPATH) \
+    -cp $(call PathList, $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes) \
+    build.tools.module.GenModuleLoaderMap
+
+##########################################################################################
 
 endif # _TOOLS_GMK
diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk
index ed8e42a..04988de 100644
--- a/jdk/make/copy/Copy-java.base.gmk
+++ b/jdk/make/copy/Copy-java.base.gmk
@@ -172,6 +172,11 @@
   POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
 endif
 
+# Allow imported modules to modify the java.policy
+ifneq ($(IMPORT_MODULES_CONF), )
+  POLICY_SRC_LIST += $(wildcard $(IMPORT_MODULES_CONF)/java.base/security/java.policy.extra)
+endif
+
 POLICY_SRC_LIST += $(POLICY_SRC)
 
 $(POLICY_DST): $(POLICY_SRC_LIST)
diff --git a/jdk/make/data/jdwp/jdwp.spec b/jdk/make/data/jdwp/jdwp.spec
index 8d05beb..a144c89 100644
--- a/jdk/make/data/jdwp/jdwp.spec
+++ b/jdk/make/data/jdwp/jdwp.spec
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -569,6 +569,21 @@
             (Error VM_DEAD)
         )
     )
+    (Command AllModules=22
+        "Returns all modules in the target VM."
+        "<p>Since JDWP version 9."
+        (Out
+        )
+        (Reply
+            (Repeat modules "The number of the modules that follow."
+                (moduleID module "One of the modules.")
+            )
+        )
+        (ErrorSet
+            (Error NOT_IMPLEMENTED)
+            (Error VM_DEAD)
+        )
+    )
 )
 
 (CommandSet ReferenceType=2
@@ -1029,6 +1044,22 @@
             (Error VM_DEAD)
         )
     )
+    (Command Module=19
+        "Returns the module that this reference type belongs to."
+        "<p>Since JDWP version 9."
+        (Out
+            (referenceType refType "The reference type.")
+        )
+        (Reply
+            (moduleID module "The module this reference type belongs to.")
+        )
+        (ErrorSet
+            (Error INVALID_CLASS   "refType is not the ID of a reference type.")
+            (Error INVALID_OBJECT  "refType is not a known ID.")
+            (Error NOT_IMPLEMENTED)
+            (Error VM_DEAD)
+        )
+    )
 )
 (CommandSet ClassType=3
     (Command Superclass=1
@@ -2647,6 +2678,54 @@
         )
     )
 )
+(CommandSet ModuleReference=18
+    (Command Name=1
+        "Returns the name of this module."
+        "<p>Since JDWP version 9."
+        (Out
+            (moduleID module "This module.")
+        )
+        (Reply
+            (string name  "The module's name.")
+        )
+        (ErrorSet
+            (Error INVALID_MODULE)
+            (Error NOT_IMPLEMENTED)
+            (Error VM_DEAD)
+        )
+    )
+    (Command ClassLoader=2
+        "Returns the class loader of this module."
+        "<p>Since JDWP version 9."
+        (Out
+            (moduleID module "This module.")
+        )
+        (Reply
+            (classLoaderObject classLoader  "The module's class loader.")
+        )
+        (ErrorSet
+            (Error INVALID_MODULE)
+            (Error NOT_IMPLEMENTED)
+            (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
         "Several events may occur at a given time in the target VM. "
@@ -3054,6 +3133,7 @@
     (Constant INVALID_SLOT           =35  "Invalid slot.")
     (Constant DUPLICATE              =40  "Item already set.")
     (Constant NOT_FOUND              =41  "Desired element not found.")
+    (Constant INVALID_MODULE         =42  "Invalid module.")
     (Constant INVALID_MONITOR        =50  "Invalid monitor.")
     (Constant NOT_MONITOR_OWNER      =51  "This thread doesn't own the monitor.")
     (Constant INTERRUPT              =52  "The call has been interrupted before completion.")
diff --git a/jdk/make/gendata/Gendata-jdk.jdeps.gmk b/jdk/make/gendata/Gendata-jdk.jdeps.gmk
deleted file mode 100644
index 3616796..0000000
--- a/jdk/make/gendata/Gendata-jdk.jdeps.gmk
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include GendataCommon.gmk
-
-$(eval $(call IncludeCustomExtension, jdk, gendata/Gendata-jdk.jdeps.gmk))
-
-JDEPS_MODULES_XML := $(JDK_OUTPUTDIR)/modules/jdk.jdeps/com/sun/tools/jdeps/resources/jdeps-modules.xml
-MODULES_XML += $(TOPDIR)/modules.xml
-
-#
-# Generate modules.xml for jdeps to use
-# It augments $(TOPDIR)/modules.xml to include module membership
-#
-$(JDEPS_MODULES_XML): $(BUILD_TOOLS_JDK) $(MODULES_XML)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(TOOL_GENMODULESXML) -o $@ -mp $(JDK_OUTPUTDIR)/modules $(MODULES_XML)
-
-TARGETS += $(JDEPS_MODULES_XML)
diff --git a/jdk/make/gendata/GendataBreakIterator.gmk b/jdk/make/gendata/GendataBreakIterator.gmk
index 2ca835c..1aa4bec 100644
--- a/jdk/make/gendata/GendataBreakIterator.gmk
+++ b/jdk/make/gendata/GendataBreakIterator.gmk
@@ -33,8 +33,6 @@
 # They are used at JDK build phase in order to create $(BIFILES) which
 # are used on runtime instead.
 #
-TEXT_SRCDIR := $(JDK_TOPDIR)/src/java.base/share/classes \
-    $(JDK_TOPDIR)/src/jdk.localedata/share/classes
 TEXT_PKG := sun/text/resources
 TEXT_PKG_LD := $(TEXT_PKG)/ext
 TEXT_SOURCES := $(TEXT_PKG)/BreakIteratorRules.java \
@@ -46,11 +44,35 @@
 BREAK_ITERATOR_CLASSES := $(BUILDTOOLS_OUTPUTDIR)/break_iterator_classes
 
 # These two files should be moved out to a build tool!
-$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR, \
+$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_BASE, \
     SETUP := GENERATE_OLDBYTECODE, \
-    SRC := $(TEXT_SRCDIR), \
-    INCLUDE_FILES := $(TEXT_SOURCES), \
-    BIN := $(BREAK_ITERATOR_CLASSES)))
+    SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
+    INCLUDE_FILES := \
+        $(TEXT_PKG)/BreakIteratorRules.java \
+        $(TEXT_PKG)/BreakIteratorInfo.java, \
+    BIN := $(BREAK_ITERATOR_CLASSES)/java.base))
+
+$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
+    SETUP := GENERATE_OLDBYTECODE, \
+    SRC := $(JDK_TOPDIR)/src/jdk.localedata/share/classes, \
+    INCLUDES := $(TEXT_PKG_LD), \
+    INCLUDE_FILES := \
+        $(TEXT_PKG_LD)/BreakIteratorRules_th.java \
+        $(TEXT_PKG_LD)/BreakIteratorInfo_th.java, \
+    BIN := $(BREAK_ITERATOR_CLASSES)/jdk.localedata))
+
+ifeq ($(BOOT_JDK_MODULAR), true)
+  BREAK_ITERATOR_BOOTCLASSPATH := -Xpatch:$(BREAK_ITERATOR_CLASSES) \
+      -XaddExports:$(subst $(SPACE),$(COMMA),$(strip \
+          java.base/sun.text=ALL-UNNAMED \
+          java.base/sun.text.resources=ALL-UNNAMED \
+          jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \
+      ))
+else
+  BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \
+      $(BREAK_ITERATOR_CLASSES)/java.base \
+      $(BREAK_ITERATOR_CLASSES)/jdk.localedata)
+endif
 
 # Generate data resource files.
 # input
@@ -67,8 +89,9 @@
     $(LD_DATA_PKG_DIR)/LineBreakIteratorData_th
 
 $(BIFILES): $(BASE_DATA_PKG_DIR)/_the.bifiles
-$(BASE_DATA_PKG_DIR)/_the.bifiles: JAVA_FLAGS += -Xbootclasspath/p:$(BREAK_ITERATOR_CLASSES)
-$(BASE_DATA_PKG_DIR)/_the.bifiles: $(BUILD_TOOLS) $(UNICODEDATA) $(BUILD_BREAKITERATOR)
+$(BASE_DATA_PKG_DIR)/_the.bifiles: JAVA_FLAGS += $(BREAK_ITERATOR_BOOTCLASSPATH)
+$(BASE_DATA_PKG_DIR)/_the.bifiles: $(BUILD_TOOLS) $(UNICODEDATA) \
+    $(BUILD_BREAKITERATOR_BASE) $(BUILD_BREAKITERATOR_LD)
 	$(call LogInfo, Generating BreakIteratorData)
 	$(call MakeDir, $(@D))
 	$(RM) $(BIFILES)
@@ -78,8 +101,9 @@
 	$(TOUCH) $@
 
 $(BIFILES_TH): $(LD_DATA_PKG_DIR)/_the.bifiles_th
-$(LD_DATA_PKG_DIR)/_the.bifiles_th: JAVA_FLAGS += -Xbootclasspath/p:$(BREAK_ITERATOR_CLASSES)
-$(LD_DATA_PKG_DIR)/_the.bifiles_th: $(BUILD_TOOLS) $(UNICODEDATA) $(BUILD_BREAKITERATOR)
+$(LD_DATA_PKG_DIR)/_the.bifiles_th: JAVA_FLAGS += $(BREAK_ITERATOR_BOOTCLASSPATH)
+$(LD_DATA_PKG_DIR)/_the.bifiles_th: $(BUILD_TOOLS) $(UNICODEDATA) \
+    $(BUILD_BREAKITERATOR_BASE) $(BUILD_BREAKITERATOR_LD)
 	$(call LogInfo, Generating BreakIteratorData_th)
 	$(RM) $(BIFILES_TH)
 	$(TOOL_GENERATEBREAKITERATORDATA) \
diff --git a/jdk/make/gensrc/Gensrc-java.base.gmk b/jdk/make/gensrc/Gensrc-java.base.gmk
index e176d88..1a188a9 100644
--- a/jdk/make/gensrc/Gensrc-java.base.gmk
+++ b/jdk/make/gensrc/Gensrc-java.base.gmk
@@ -33,6 +33,7 @@
 include GensrcCharsetCoder.gmk
 include GensrcBuffer.gmk
 include GensrcExceptions.gmk
+include GensrcModuleLoaderMap.gmk
 
 ################################################################################
 
diff --git a/jdk/make/gensrc/Gensrc-jdk.dev.gmk b/jdk/make/gensrc/Gensrc-jdk.dev.gmk
deleted file mode 100644
index 4316c48..0000000
--- a/jdk/make/gensrc/Gensrc-jdk.dev.gmk
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include GensrcCommon.gmk
-
-################################################################################
-
-include GensrcProperties.gmk
-
-$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
-    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources, \
-    CLASS := ListResourceBundle, \
-))
-
-TARGETS += $(COMPILE_PROPERTIES)
-
-################################################################################
-
-all: $(TARGETS)
-
-.PHONY: all
diff --git a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk
index e634c12..720b685 100644
--- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk
+++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk
@@ -61,30 +61,6 @@
 
 ################################################################################
 
-define process-provider
-	$(call MakeDir, $(@D))
-	$(CAT) $^ | $(SED) -e "s/^#\[$(OPENJDK_TARGET_OS)\]//" > $@
-endef
-
-# Filter com.sun.jdi.connect.Connector
-$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \
-    $(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector \
-    $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/META-INF/services/com.sun.jdi.connect.Connector
-	$(process-provider)
-
-# Copy the same service file into jdk.hotspot.agent so that they are kept the same.
-$(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/META-INF/services/com.sun.jdi.connect.Connector: \
-    $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector
-	$(install-file)
-
-# Some platforms don't have the serviceability agent
-ifeq ($(INCLUDE_SA), true)
-  GENSRC_JDK_JDI += $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector \
-      $(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/META-INF/services/com.sun.jdi.connect.Connector
-endif
-
-################################################################################
-
 include GensrcProperties.gmk
 
 $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
diff --git a/jdk/make/gensrc/Gensrc-jdk.jlink.gmk b/jdk/make/gensrc/Gensrc-jdk.jlink.gmk
new file mode 100644
index 0000000..c841345
--- /dev/null
+++ b/jdk/make/gensrc/Gensrc-jdk.jlink.gmk
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include GensrcCommon.gmk
+
+################################################################################
+
+include GensrcProperties.gmk
+
+$(eval $(call SetupCompileProperties, JLINK_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jlink/share/classes/jdk/tools/jlink/resources, \
+    CLASS := ListResourceBundle, \
+))
+
+$(eval $(call SetupCompileProperties, JMOD_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jlink/share/classes/jdk/tools/jmod/resources, \
+    CLASS := ListResourceBundle, \
+))
+
+$(eval $(call SetupCompileProperties, JIMAGE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jlink/share/classes/jdk/tools/jimage/resources, \
+    CLASS := ListResourceBundle, \
+))
+
+
+TARGETS += $(JLINK_PROPERTIES) $(JMOD_PROPERTIES) $(JIMAGE_PROPERTIES)
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: all
diff --git a/jdk/make/gensrc/Gensrc-jdk.jvmstat.gmk b/jdk/make/gensrc/Gensrc-jdk.jvmstat.gmk
deleted file mode 100644
index 11e54a6..0000000
--- a/jdk/make/gensrc/Gensrc-jdk.jvmstat.gmk
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include GensrcCommon.gmk
-
-################################################################################
-
-define merge-providers
-	$(MKDIR) -p $(@D)
-	$(CAT) $^ > $@
-endef
-
-PROVIDER_FILE := META-INF/services/sun.jvmstat.monitor.MonitoredHostService
-
-# Merge the local and remote sevice providers into jdk.jvmstat/META-INF/services
-$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE): \
-    $(JDK_TOPDIR)/src/jdk.jvmstat/share/classes/$(PROVIDER_FILE) \
-    $(JDK_TOPDIR)/src/jdk.jvmstat.rmi/share/classes/$(PROVIDER_FILE)
-	$(merge-providers)
-
-# Copy the same service file into jdk.jvmstat.rmi so that they are kept the same.
-$(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat.rmi/$(PROVIDER_FILE): \
-    $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE)
-	$(install-file)
-
-################################################################################
-
-jdk.jvmstat: $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat/$(PROVIDER_FILE) \
-    $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jvmstat.rmi/$(PROVIDER_FILE)
-
-all: jdk.jvmstat
-
-.PHONY: all
\ No newline at end of file
diff --git a/jdk/make/gensrc/GensrcLocaleData.gmk b/jdk/make/gensrc/GensrcLocaleData.gmk
index 602a4f4..0acc8f9 100644
--- a/jdk/make/gensrc/GensrcLocaleData.gmk
+++ b/jdk/make/gensrc/GensrcLocaleData.gmk
@@ -143,19 +143,6 @@
 GENSRC_BASELOCALEDATA := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/BaseLocaleDataMetaInfo.java
 GENSRC_LOCALEDATA := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonBaseLocaleDataMetaInfo.java
 
-################################################################################
-
-GENSRC_CRBC_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/CoreResourceBundleControl.java
-GENSRC_CRBC_CMD := $(JDK_TOPDIR)/make/scripts/localelist.sh
-
-JRE_NONEXIST_LOCALES := en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh
-
-$(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template \
-    $(GENSRC_CRBC_CMD)
-	$(MKDIR) -p $(@D)
-	NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@
-
-GENSRC_BASELOCALEDATA += $(GENSRC_CRBC_DST)
 GENSRC_JAVA_BASE += $(GENSRC_BASELOCALEDATA)
 GENSRC_JDK_LOCALEDATA += $(GENSRC_LOCALEDATA)
 
diff --git a/jdk/make/gensrc/GensrcModuleLoaderMap.gmk b/jdk/make/gensrc/GensrcModuleLoaderMap.gmk
new file mode 100644
index 0000000..7e8fb33
--- /dev/null
+++ b/jdk/make/gensrc/GensrcModuleLoaderMap.gmk
@@ -0,0 +1,164 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include Modules.gmk
+
+BOOT_MODULES :=
+UPGRADEABLE_MDOULES :=
+AGGREGATOR_MDOULES :=
+OTHER_PLATFORM_MODULES :=
+
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, gensrc/GensrcModuleLoaderMap.gmk))
+
+BOOT_MODULES += \
+    java.base \
+    java.datatransfer \
+    java.desktop \
+    java.httpclient \
+    java.instrument \
+    java.logging \
+    java.management \
+    java.naming \
+    java.prefs \
+    java.rmi \
+    java.security.jgss \
+    java.security.sasl \
+    java.sql \
+    java.xml \
+    java.xml.crypto \
+    jdk.httpserver \
+    jdk.management \
+    jdk.sctp \
+    jdk.security.auth \
+    jdk.security.jgss \
+    #
+
+# to be deprivileged
+BOOT_MODULES += \
+    java.compiler \
+    java.scripting \
+    java.sql.rowset \
+    java.smartcardio \
+    jdk.charsets \
+    jdk.naming.rmi \
+    #
+
+UPGRADEABLE_MODULES += \
+    java.activation \
+    java.annotations.common \
+    java.corba \
+    java.transaction \
+    java.xml.bind \
+    java.xml.ws \
+    #
+
+AGGREGATOR_MODULES += \
+    java.compact1 \
+    java.compact2 \
+    java.compact3 \
+    java.se \
+    java.se.ee \
+    #
+
+OTHER_PLATFORM_MODULES += \
+    jdk.accessibility \
+    jdk.crypto.ec \
+    jdk.crypto.pkcs11 \
+    jdk.dynalink \
+    jdk.jsobject \
+    jdk.xml.dom \
+    jdk.localedata \
+    jdk.naming.dns \
+    jdk.scripting.nashorn \
+    jdk.zipfs \
+    #
+
+ifeq ($(OPENJDK_TARGET_OS), macsox)
+  BOOT_MODULES += jdk.deploy.osx
+endif
+ifeq ($(OPENJDK_TARGET_OS), windows)
+  OTHER_PLATFORM_MODULES += jdk.crypto.mscapi
+endif
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+  OTHER_PLATFORM_MODULES += jdk.crypto.ucrypto
+endif
+
+# Param 1 - Name of module
+define ReadImportMetaData
+  ifneq ($$(wildcard $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties), )
+    classloader :=
+    include $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties
+    ifeq ($$(classloader), boot)
+      BOOT_MODULES += $1
+    else ifeq ($$(classloader), ext)
+      OTHER_PLATFORM_MODULES += $1
+    endif
+  endif
+endef
+
+IMPORTED_MODULES := $(call FindImportedModules)
+$(foreach m, $(IMPORTED_MODULES), $(eval $(call ReadImportMetaData, $m)))
+
+
+# Replacing double-comma with a single comma is to workaround the issue
+# with some version of make on windows that doesn't substitute spaces
+# with one comma properly as with make 4.0
+define SubstComma
+$(strip \
+  $(subst $(COMMA)$(COMMA),$(COMMA),$(subst $(SPACE),$(COMMA),$(strip $1))) \
+)
+endef
+BOOT_MODULES_LIST := $(call SubstComma, $(BOOT_MODULES))
+PLATFORM_MODULES_LIST := $(call SubstComma, $(UPGRADEABLE_MODULES) $(AGGREGATOR_MODULES) $(OTHER_PLATFORM_MODULES))
+
+VARDEPS_VALUE := $(BOOT_MODULES_LIST) $(PLATFORM_MODULES_LIST)
+VARDEPS_FILE := $(call DependOnVariable, VARDEPS_VALUE)
+
+############################################################################
+
+$(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/module/ModuleLoaderMap.java: \
+    $(JDK_TOPDIR)/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java \
+    $(VARDEPS_FILE) $(BUILD_TOOLS_JDK)
+	$(MKDIR) -p $(@D)
+	$(RM) $@ $@.tmp
+	$(TOOL_GENCLASSLOADERMAP) -boot $(BOOT_MODULES_LIST) \
+	     -platform $(PLATFORM_MODULES_LIST) -o $@.tmp $<
+	$(MV) $@.tmp $@
+
+GENSRC_JAVA_BASE += $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/module/ModuleLoaderMap.java
+
+$(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat: \
+    $(JDK_TOPDIR)/src/java.base/share/classes/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat \
+    $(VARDEPS_FILE) $(BUILD_TOOLS_JDK)
+	$(MKDIR) -p $(@D)
+	$(RM) $@ $@.tmp
+	$(TOOL_GENCLASSLOADERMAP) -boot $(BOOT_MODULES_LIST) \
+	    -platform $(PLATFORM_MODULES_LIST) -o $@.tmp $<
+	$(MV) $@.tmp $@
+
+GENSRC_JAVA_BASE += $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat
+
+################################################################################
diff --git a/jdk/make/launcher/Launcher-java.desktop.gmk b/jdk/make/launcher/Launcher-java.desktop.gmk
index 2bb3c49..c9f730f 100644
--- a/jdk/make/launcher/Launcher-java.desktop.gmk
+++ b/jdk/make/launcher/Launcher-java.desktop.gmk
@@ -31,6 +31,7 @@
 ifndef BUILD_HEADLESS_ONLY
   $(eval $(call SetupBuildLauncher, appletviewer, \
       MAIN_CLASS := sun.applet.Main, \
+      JAVA_ARGS := -addmods ALL-SYSTEM, \
       LIBS_unix := $(X_LIBS), \
   ))
 endif
diff --git a/jdk/make/launcher/Launcher-jdk.dev.gmk b/jdk/make/launcher/Launcher-jdk.dev.gmk
deleted file mode 100644
index d874ae9..0000000
--- a/jdk/make/launcher/Launcher-jdk.dev.gmk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include LauncherCommon.gmk
-
-$(eval $(call SetupBuildLauncher, jimage,\
-    MAIN_CLASS := jdk.tools.jimage.Main, \
-))
diff --git a/jdk/make/launcher/Launcher-jdk.jlink.gmk b/jdk/make/launcher/Launcher-jdk.jlink.gmk
new file mode 100644
index 0000000..acf8228
--- /dev/null
+++ b/jdk/make/launcher/Launcher-jdk.jlink.gmk
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupBuildLauncher, jimage,\
+    MAIN_CLASS := jdk.tools.jimage.Main, \
+    CFLAGS := -DENABLE_ARG_FILES, \
+))
+
+$(eval $(call SetupBuildLauncher, jlink,\
+    MAIN_CLASS := jdk.tools.jlink.internal.Main, \
+    CFLAGS := -DENABLE_ARG_FILES \
+        -DEXPAND_CLASSPATH_WILDCARDS \
+        -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
+
+$(eval $(call SetupBuildLauncher, jmod,\
+    MAIN_CLASS := jdk.tools.jmod.Main, \
+    CFLAGS := -DENABLE_ARG_FILES \
+        -DEXPAND_CLASSPATH_WILDCARDS \
+        -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
diff --git a/jdk/make/launcher/Launcher-jdk.pack200.gmk b/jdk/make/launcher/Launcher-jdk.pack200.gmk
index 818828a..af05055 100644
--- a/jdk/make/launcher/Launcher-jdk.pack200.gmk
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk
@@ -26,6 +26,7 @@
 include LauncherCommon.gmk
 
 $(eval $(call SetupBuildLauncher, pack200, \
+    MAIN_MODULE := java.base, \
     MAIN_CLASS := com.sun.java.util.jar.pack.Driver, \
 ))
 
diff --git a/jdk/make/launcher/Launcher-jdk.rmic.gmk b/jdk/make/launcher/Launcher-jdk.rmic.gmk
index d60c3d9..b0a8b6d 100644
--- a/jdk/make/launcher/Launcher-jdk.rmic.gmk
+++ b/jdk/make/launcher/Launcher-jdk.rmic.gmk
@@ -26,6 +26,6 @@
 include LauncherCommon.gmk
 
 $(eval $(call SetupBuildLauncher, rmic, \
-    MAIN_CLASS := sun.rmi.rmic.Main, \
+    MAIN_CLASS := jdk.rmi.rmic.Main, \
     CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
 ))
diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk
index d35b8b7..1bef88f 100644
--- a/jdk/make/launcher/LauncherCommon.gmk
+++ b/jdk/make/launcher/LauncherCommon.gmk
@@ -63,6 +63,8 @@
 # used as the name of the executable.
 #
 # Remaining parameters are named arguments. These include:
+# MAIN_MODULE  The module of the main class to launch if different from the
+#     current module
 # MAIN_CLASS   The Java main class to launch
 # JAVA_ARGS   Processed into a -DJAVA_ARGS C flag
 # CFLAGS   Additional CFLAGS
@@ -97,9 +99,13 @@
     $1_JAVA_ARGS += -ms8m
   endif
 
+  ifeq ($$($1_MAIN_MODULE), )
+    $1_MAIN_MODULE := $(MODULE)
+  endif
+
   ifneq ($$($1_JAVA_ARGS), )
     $1_JAVA_ARGS_STR := '{ $$(strip $$(foreach a, \
-        $$(addprefix -J, $$($1_JAVA_ARGS)) $$($1_MAIN_CLASS), "$$a"$(COMMA) )) }'
+        $$(addprefix -J, $$($1_JAVA_ARGS)) -m $$($1_MAIN_MODULE)/$$($1_MAIN_CLASS), "$$a"$(COMMA) )) }'
     $1_CFLAGS += -DJAVA_ARGS=$$($1_JAVA_ARGS_STR)
   endif
 
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 9dcf06b..f114c9b 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -146,6 +146,7 @@
         $(LIBJAVA_CFLAGS), \
     System.c_CFLAGS := $(VERSION_CFLAGS), \
     jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \
+    DISABLED_WARNINGS_gcc := unused-result, \
     DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
     MAPFILE := $(LIBJAVA_MAPFILE), \
     LDFLAGS := $(LDFLAGS_JDKLIB) \
diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk
index 44ba88d..64f25d0 100644
--- a/jdk/make/lib/Lib-java.instrument.gmk
+++ b/jdk/make/lib/Lib-java.instrument.gmk
@@ -68,14 +68,14 @@
     LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
     LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
     LIBS := $(JDKLIB_LIBS), \
-    LIBS_unix := -ljava $(LIBZ), \
+    LIBS_unix := -ljava -ljvm $(LIBZ), \
     LIBS_linux := -ljli $(LIBDL), \
     LIBS_solaris := -ljli $(LIBDL), \
     LIBS_aix := -liconv -ljli_static $(LIBDL), \
     LIBS_macosx := -liconv -framework Cocoa -framework Security \
         -framework ApplicationServices \
         $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
-    LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \
+    LIBS_windows := jvm.lib $(WIN_JAVA_LIB) advapi32.lib \
         $(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib, \
     VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
     RC_FLAGS := $(RC_FLAGS) \
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index ac21dd2..82fd583 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -137,7 +137,6 @@
 		Java_java_lang_ClassLoader_registerNatives;
 		Java_java_lang_Double_longBitsToDouble;
 		Java_java_lang_Double_doubleToRawLongBits;
-		Java_java_lang_reflect_Proxy_defineClass0;
 		Java_java_lang_Float_intBitsToFloat;
 		Java_java_lang_Float_floatToRawIntBits;
                 Java_java_lang_StackFrameInfo_fillInStackFrames;
@@ -165,8 +164,6 @@
 		Java_java_lang_StrictMath_expm1;
 		Java_java_lang_Object_getClass;
 		Java_java_lang_Object_registerNatives;
-		Java_java_lang_Package_getSystemPackage0;
-		Java_java_lang_Package_getSystemPackages0;
 		Java_java_lang_ProcessEnvironment_environ;
 		Java_java_lang_ProcessHandleImpl_destroy0;
 		Java_java_lang_ProcessHandleImpl_getCurrentPid0;
@@ -204,11 +201,11 @@
 		Java_java_lang_reflect_Executable_getTypeAnnotationBytes0;
 		Java_java_lang_reflect_Field_getTypeAnnotationBytes0;
 		Java_java_lang_Runtime_freeMemory;
-                Java_java_lang_Runtime_maxMemory;
+		Java_java_lang_Runtime_maxMemory;
 		Java_java_lang_Runtime_gc;
 		Java_java_lang_Runtime_runFinalization0;
 		Java_java_lang_Runtime_totalMemory;
-                Java_java_lang_Runtime_availableProcessors;
+		Java_java_lang_Runtime_availableProcessors;
 		Java_java_lang_SecurityManager_classDepth;
 		Java_java_lang_SecurityManager_classLoaderDepth0;
 		Java_java_lang_SecurityManager_currentClassLoader0;
@@ -274,6 +271,18 @@
                 Java_jdk_internal_misc_VM_getgid;
                 Java_jdk_internal_misc_VM_getegid;
                 Java_jdk_internal_misc_VM_initialize;
+
+                Java_java_lang_reflect_Module_defineModule0;
+                Java_java_lang_reflect_Module_addReads0;
+                Java_java_lang_reflect_Module_addExports0;
+                Java_java_lang_reflect_Module_addExportsToAll0;
+                Java_java_lang_reflect_Module_addExportsToAllUnnamed0;
+                Java_java_lang_reflect_Module_addPackage0;
+
+		Java_jdk_internal_loader_BootLoader_getSystemPackageLocation;
+		Java_jdk_internal_loader_BootLoader_getSystemPackageNames;
+                Java_jdk_internal_loader_BootLoader_setBootLoaderUnnamedModule0;
+
 		Java_sun_misc_VMSupport_initAgentProperties;
 		Java_sun_misc_VMSupport_getVMTemporaryDirectory;
 
diff --git a/jdk/make/mapfiles/libjimage/mapfile-vers b/jdk/make/mapfiles/libjimage/mapfile-vers
index 68e01c6..48eac21 100644
--- a/jdk/make/mapfiles/libjimage/mapfile-vers
+++ b/jdk/make/mapfiles/libjimage/mapfile-vers
@@ -27,23 +27,7 @@
 
 SUNWprivate_1.1 {
     global:
-        JNI_OnLoad;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_openImage;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_read;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule;
-        Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources;
+        Java_jdk_internal_jimage_NativeImageBuffer_getNativeMap;
         JIMAGE_Open;
         JIMAGE_Close;
         JIMAGE_PackageToModule;
diff --git a/jdk/make/rmic/Rmic-java.management.gmk b/jdk/make/rmic/Rmic-java.management.gmk
index 9eca430..0452d5c 100644
--- a/jdk/make/rmic/Rmic-java.management.gmk
+++ b/jdk/make/rmic/Rmic-java.management.gmk
@@ -40,7 +40,7 @@
 $(eval $(call SetupRMICompilation,RMI_GEN, \
     CLASSES := $(JMX_RMI_CLASSES), \
     CLASSES_DIR := $(CLASSES_DIR)/java.management, \
-    STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR), \
+    STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management, \
     RUN_V12 := true, \
     KEEP_GENERATED := true, \
 ))
@@ -50,7 +50,7 @@
 	$(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class"))
 	$(foreach src, $(classfiles), \
 	    $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \
-	        $(STUB_CLASSES_DIR)/java.management/%, $(src))) \
+	        $(STUB_CLASSES_DIR)/%, $(src))) \
 	    $(MKDIR) -p $(dir $(target)) ; \
 	    $(MV) $(src) $(target) $(NEWLINE))
 	$(TOUCH) $@
diff --git a/jdk/make/rmic/RmicCommon.gmk b/jdk/make/rmic/RmicCommon.gmk
index 8c6affb..45fd1de 100644
--- a/jdk/make/rmic/RmicCommon.gmk
+++ b/jdk/make/rmic/RmicCommon.gmk
@@ -31,10 +31,7 @@
 
 ##########################################################################################
 
-BTRMIC_CP := $(call PathList, \
-    $(BUILDTOOLS_OUTPUTDIR)/interim_rmic_classes $(INTERIM_LANGTOOLS_JAR))
-BTRMIC_ARGS := -cp $(BTRMIC_CP)
-RMIC := $(JAVA) $(BTRMIC_ARGS) sun.rmi.rmic.Main
+RMIC := $(JAVA) $(INTERIM_OVERRIDE_MODULES_ARGS) sun.rmi.rmic.Main
 
 CLASSES_DIR := $(JDK_OUTPUTDIR)/modules
 # NOTE: If the smart javac dependency management is reintroduced, these classes risk
diff --git a/jdk/make/scripts/localelist.sh b/jdk/make/scripts/localelist.sh
deleted file mode 100644
index 96fa02b..0000000
--- a/jdk/make/scripts/localelist.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-#
-# This script is to generate the supported locale list string and replace the
-# #LOCALE_LIST# in <ws>/src/share/classes/sun/util/CoreResourceBundleControl.java.
-#
-# NAWK & SED is passed in as environment variables.
-#
-LOCALE_LIST=$1
-INUT_FILE=$2
-OUTPUT_FILE=$3
-
-LOCALES=`(for I in $LOCALE_LIST; do echo $I;done) | sort | uniq`
-JAVA_LOCALES=
-
-toJavaLocale()
-{
-  NewLocale=`echo $1 | $NAWK '
-      BEGIN {
-        # The following values have to be consistent with java.util.Locale.
-        javalocales["en"] = "ENGLISH";
-        javalocales["fr"] = "FRENCH";
-        javalocales["de"] = "GERMAN";
-        javalocales["it"] = "ITALIAN";
-        javalocales["ja"] = "JAPANESE";
-        javalocales["ko"] = "KOREAN";
-        javalocales["zh"] = "CHINESE";
-        javalocales["zh_CN"] = "SIMPLIFIED_CHINESE";
-        javalocales["zh_TW"] = "TRADITIONAL_CHINESE";
-        javalocales["fr_FR"] = "FRANCE";
-        javalocales["de_DE"] = "GERMANY";
-        javalocales["it_IT"] = "ITALY";
-        javalocales["ja_JP"] = "JAPAN";
-        javalocales["ko_KR"] = "KOREA";
-        javalocales["en_GB"] = "UK";
-        javalocales["en_US"] = "US";
-        javalocales["en_CA"] = "CANADA";
-        javalocales["fr_CA"] = "CANADA_FRENCH";
-      }
-      {
-        if ($0 in javalocales) {
-          print "        Locale." javalocales[$0];
-        } else {
-          split($0, a, "_");
-          if (a[3] != "") {
-            print " new Locale(\"" a[1] "\", \"" a[2] "\", \"" a[3] "\")";
-          } else if (a[2] != "") {
-            print " new Locale(\"" a[1] "\", \"" a[2] "\")";
-          } else {
-            print " new Locale(\"" a[1] "\")";
-          }
-        }
-      }'`
-
-  JAVA_LOCALES=$JAVA_LOCALES$NewLocale
-}
-
-# count the number of locales
-counter=0
-for i in $LOCALES
-do
-  counter=`expr $counter + 1`
-done
-
-index=0
-for locale in $LOCALES
-do
-  index=`expr $index + 1`;
-  if [ $index != $counter ]
-  then
-    toJavaLocale $locale
-    JAVA_LOCALES=$JAVA_LOCALES","
-  else
-    toJavaLocale $locale
-  fi
-done
-
-# replace the #LOCALE_LIST# in the precompiled CoreResourceBundleControl.java file.
-
-$SED -e "s@^#warn .*@// -- This file was mechanically generated: Do not edit! -- //@" \
-    -e "s/#LOCALE_LIST#/$JAVA_LOCALES/g" $2 > $3
diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
index 500cf2b..b291758 100644
--- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
+++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
@@ -343,9 +343,7 @@
                 if (!all && CLDRConverter.isBaseModule ^ isBaseLocale(id)) {
                     continue;
                 }
-                if (sb.length() > 0) {
-                    sb.append(' ');
-                }
+                sb.append(' ');
                 sb.append(id);
             }
         }
diff --git a/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java b/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java
index c22fa68..f0821e8 100644
--- a/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java
+++ b/jdk/make/src/classes/build/tools/generatebreakiteratordata/GenerateBreakIteratorData.java
@@ -62,25 +62,37 @@
         CharacterCategory.makeCategoryMap(unicodeData);
 
         /* Generate files */
-        generateFiles();
+        try {
+            generateFiles();
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    private static String localizedBundleName(String pkg, String clazz) {
+        if (language.length() > 0) {
+            return pkg + ".ext." + clazz + '_' + language;
+        } else {
+            return pkg + '.' + clazz;
+        }
     }
 
     /**
      * Generate data files whose names are included in
      * sun.text.resources.BreakIteratorInfo+<localeName>
      */
-    private static void generateFiles() {
+    private static void generateFiles() throws Exception {
         String[] classNames;
         ResourceBundle rules, info;
 
-        String pkgName = "sun.text.resources" + (language.length() > 0 ? ".ext" : "");
+        info = (ResourceBundle) Class.forName(
+            localizedBundleName("sun.text.resources", "BreakIteratorInfo")).newInstance();
 
-        info =  ResourceBundle.getBundle(pkgName + ".BreakIteratorInfo",
-                                         new Locale(language, country, valiant));
         classNames = info.getStringArray("BreakIteratorClasses");
 
-        rules = ResourceBundle.getBundle(pkgName + ".BreakIteratorRules",
-                                         new Locale(language, country, valiant));
+        rules = (ResourceBundle) Class.forName(
+            localizedBundleName("sun.text.resources", "BreakIteratorRules")).newInstance();
 
         if (info.containsKey("CharacterData")) {
             generateDataFile(info.getString("CharacterData"),
diff --git a/jdk/make/src/classes/build/tools/jdwpgen/ModuleTypeNode.java b/jdk/make/src/classes/build/tools/jdwpgen/ModuleTypeNode.java
new file mode 100644
index 0000000..af12852
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/jdwpgen/ModuleTypeNode.java
@@ -0,0 +1,56 @@
+/*
+ * 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.jdwpgen;
+
+import java.util.*;
+import java.io.*;
+
+class ModuleTypeNode extends AbstractSimpleTypeNode {
+
+    String docType() {
+        return "moduleID";
+    }
+
+    String javaType() {
+        return "ModuleReferenceImpl";
+    }
+
+    String debugValue(String label) {
+        return "(" + label + "==null?\"NULL\":\"ref=\"+" + label + ".ref())";
+    }
+
+    public void genJavaWrite(PrintWriter writer, int depth,
+                             String writeLabel) {
+        genJavaDebugWrite(writer, depth, writeLabel,
+                          debugValue(writeLabel));
+        indent(writer, depth);
+        writer.println("ps.writeModuleRef(" + writeLabel + ".ref());");
+    }
+
+    String javaRead() {
+        return "ps.readModule()";
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/jdwpgen/Parse.java b/jdk/make/src/classes/build/tools/jdwpgen/Parse.java
index 5b172e5..4ac854b 100644
--- a/jdk/make/src/classes/build/tools/jdwpgen/Parse.java
+++ b/jdk/make/src/classes/build/tools/jdwpgen/Parse.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -80,6 +80,7 @@
         kindMap.put("field", new FieldTypeNode());
         kindMap.put("frame", new FrameTypeNode());
         kindMap.put("string", new StringTypeNode());
+        kindMap.put("moduleID", new ModuleTypeNode());
         kindMap.put("value", new ValueTypeNode());
         kindMap.put("byte", new ByteTypeNode());
         kindMap.put("location", new LocationTypeNode());
diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
new file mode 100644
index 0000000..da77475
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
@@ -0,0 +1,231 @@
+/*
+ * 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
+ * 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.jigsaw;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.PUBLIC;
+
+/**
+ * Generate the DOT file for a module graph for each module in the JDK
+ * after transitive reduction.
+ */
+public class GenGraphs {
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length != 1) {
+            System.err.println("ERROR: specify the output directory");
+            System.exit(1);
+        }
+        Path dir = Paths.get(args[0]);
+        Files.createDirectories(dir);
+
+        ModuleFinder finder = ModuleFinder.ofSystem();
+
+        Set<ModuleDescriptor> javaSEModules
+            = new TreeSet<>(finder.findAll().stream()
+                                  .map(ModuleReference::descriptor)
+                                  .filter(m -> (m.name().startsWith("java.") &&
+                                               !m.name().equals("java.smartcardio")))
+                                  .collect(Collectors.toSet()));
+        Set<ModuleDescriptor> jdkModules
+            = new TreeSet<>(finder.findAll().stream()
+                                  .map(ModuleReference::descriptor)
+                                  .filter(m -> !javaSEModules.contains(m))
+                                  .collect(Collectors.toSet()));
+
+        GenGraphs genGraphs = new GenGraphs(javaSEModules, jdkModules);
+        Set<String> mods = new HashSet<>();
+        for (ModuleReference mref: finder.findAll()) {
+            ModuleDescriptor descriptor = mref.descriptor();
+            String name = descriptor.name();
+            mods.add(name);
+            Configuration cf = Configuration.empty()
+                    .resolveRequires(finder,
+                                     ModuleFinder.empty(),
+                                     Set.of(name));
+            genGraphs.genDotFile(dir, name, cf);
+        }
+
+        Configuration cf = Configuration.empty()
+                .resolveRequires(finder,
+                                 ModuleFinder.empty(),
+                                 mods);
+        genGraphs.genDotFile(dir, "jdk", cf);
+
+    }
+
+    private final Set<ModuleDescriptor> javaGroup;
+    private final Set<ModuleDescriptor> jdkGroup;
+
+    GenGraphs(Set<ModuleDescriptor> javaGroup, Set<ModuleDescriptor> jdkGroup) {
+        this.javaGroup = Collections.unmodifiableSet(javaGroup);
+        this.jdkGroup = Collections.unmodifiableSet(jdkGroup);
+    }
+
+    private static final String ORANGE = "#e76f00";
+    private static final String BLUE = "#437291";
+    private static final String GRAY = "#dddddd";
+
+    private static final String REEXPORTS = "";
+    private static final String REQUIRES = "style=\"dashed\"";
+    private static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
+
+    private static final Map<String,Integer> weights = new HashMap<>();
+
+    private static void weight(String s, String t, int w) {
+        weights.put(s + ":" + t, w);
+    }
+
+    private static int weightOf(String s, String t) {
+        int w = weights.getOrDefault(s + ":" + t, 1);
+        if (w != 1)
+            return w;
+        if (s.startsWith("java.") && t.startsWith("java."))
+            return 10;
+        return 1;
+    }
+
+    static {
+        int h = 1000;
+        weight("java.se", "java.compact3", h * 10);
+        weight("jdk.compact3", "java.compact3", h * 10);
+        weight("java.compact3", "java.compact2", h * 10);
+        weight("java.compact2", "java.compact1", h * 10);
+        weight("java.compact1", "java.logging", h * 10);
+        weight("java.logging", "java.base", h * 10);
+    }
+
+    private void genDotFile(Path dir, String name, Configuration cf) throws IOException {
+        try (PrintStream out
+                 = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
+
+            Map<String, ModuleDescriptor> nameToModule = cf.modules().stream()
+                    .map(ResolvedModule::reference)
+                    .map(ModuleReference::descriptor)
+                    .collect(Collectors.toMap(ModuleDescriptor::name, Function.identity()));
+
+            Set<ModuleDescriptor> descriptors = new TreeSet<>(nameToModule.values());
+
+            out.format("digraph \"%s\" {%n", name);
+            out.format("size=\"25,25\";");
+            out.format("nodesep=.5;%n");
+            out.format("ranksep=1.5;%n");
+            out.format("pencolor=transparent;%n");
+            out.format("node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n");
+            out.format("edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n");
+
+            out.format("subgraph %sse {%n", name.equals("jdk") ? "cluster_" : "");
+            descriptors.stream()
+                .filter(javaGroup::contains)
+                .map(ModuleDescriptor::name)
+                .forEach(mn -> out.format("  \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                          mn, ORANGE, "java"));
+            out.format("}%n");
+            descriptors.stream()
+                .filter(jdkGroup::contains)
+                .map(ModuleDescriptor::name)
+                .forEach(mn -> out.format("  \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                          mn, BLUE, "jdk"));
+
+            // transitive reduction
+            Graph<String> graph = gengraph(cf);
+            descriptors.forEach(md -> {
+                String mn = md.name();
+                Set<String> requiresPublic = md.requires().stream()
+                        .filter(d -> d.modifiers().contains(PUBLIC))
+                        .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);
+                    int w = weightOf(mn, dn);
+                    if (w > 1)
+                        attr += "weight=" + w;
+                    out.format("  \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
+                });
+            });
+
+            out.println("}");
+        }
+    }
+
+    /**
+     * 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
+     * (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(Configuration cf) {
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            String mn = resolvedModule.reference().descriptor().name();
+            builder.addNode(mn);
+            resolvedModule.reads().stream()
+                    .map(ResolvedModule::name)
+                    .forEach(target -> builder.addEdge(mn, target));
+        }
+        Graph<String> rpg = requiresPublicGraph(cf);
+        return builder.build().reduce(rpg);
+    }
+
+    /**
+     * Returns a Graph containing only requires public edges
+     * with transitive reduction.
+     */
+    private Graph<String> requiresPublicGraph(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))
+                    .map(d -> d.name())
+                    .forEach(d -> builder.addEdge(mn, d));
+        }
+        return builder.build().reduce();
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/jigsaw/Graph.java b/jdk/make/src/classes/build/tools/jigsaw/Graph.java
new file mode 100644
index 0000000..a835da1
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/jigsaw/Graph.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.jigsaw;
+
+import java.io.PrintStream;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+public class Graph<T> {
+    private static boolean traceOn = Boolean.getBoolean("build.tools.module.trace");
+    private final Set<T> nodes;
+    private final Map<T, Set<T>> edges;
+    private Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+        this.nodes = nodes;
+        this.edges = edges;
+    }
+
+    public Set<T> nodes() {
+        return nodes;
+    }
+
+    public Map<T, Set<T>> edges() {
+        return edges;
+    }
+
+    public Set<T> adjacentNodes(T u) {
+        return edges.get(u);
+    }
+
+    /**
+     * Returns a new Graph after transitive reduction
+     */
+    public Graph<T> reduce() {
+        Graph.Builder<T> builder = new Builder<>();
+        nodes.stream()
+             .forEach(u -> {
+                 builder.addNode(u);
+                 edges.get(u).stream()
+                         .filter(v -> !pathExists(u, v, false))
+                         .forEach(v -> builder.addEdge(u, v));
+             });
+        return builder.build();
+    }
+
+    /**
+     * Returns a new Graph after transitive reduction.  All edges in
+     * the given g takes precedence over this graph.
+     *
+     * @throw IllegalArgumentException g must be a subgraph this graph
+     */
+    public Graph<T> reduce(Graph<T> g) {
+        boolean subgraph = nodes.containsAll(g.nodes) && g.edges.keySet().stream()
+               .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u)));
+        if (!subgraph) {
+            throw new IllegalArgumentException("the given argument is not a subgraph of this graph");
+        }
+
+        Graph.Builder<T> builder = new Builder<>();
+        nodes.stream()
+             .forEach(u -> {
+                 builder.addNode(u);
+                 // filter the edge if there exists a path from u to v in the given g
+                 // or there exists another path from u to v in this graph
+                 edges.get(u).stream()
+                      .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false))
+                      .forEach(v -> builder.addEdge(u, v));
+             });
+
+        // add the overlapped edges from this graph and the given g
+        g.edges().keySet().stream()
+                 .forEach(u -> g.adjacentNodes(u).stream()
+                         .filter(v -> isAdjacent(u, v))
+                         .forEach(v -> builder.addEdge(u, v)));
+        return builder.build();
+    }
+
+    private boolean isAdjacent(T u, T v) {
+        return edges.containsKey(u) && edges.get(u).contains(v);
+    }
+
+    private boolean pathExists(T u, T v) {
+        return pathExists(u, v, true);
+    }
+
+    /**
+     * Returns true if there exists a path from u to v in this graph.
+     * If includeAdjacent is false, it returns true if there exists
+     * another path from u to v of distance > 1
+     */
+    private boolean pathExists(T u, T v, boolean includeAdjacent) {
+        if (!nodes.contains(u) || !nodes.contains(v)) {
+            return false;
+        }
+        if (includeAdjacent && isAdjacent(u, v)) {
+            return true;
+        }
+        Deque<T> stack = new LinkedList<>();
+        Set<T> visited = new HashSet<>();
+        stack.push(u);
+        while (!stack.isEmpty()) {
+            T node = stack.pop();
+            if (node.equals(v)) {
+                if (traceOn) {
+                    System.out.format("Edge %s -> %s removed%n", u, v);
+                }
+                return true;
+            }
+            if (!visited.contains(node)) {
+                visited.add(node);
+                edges.get(node).stream()
+                     .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v))
+                     .forEach(e -> stack.push(e));
+            }
+        }
+        assert !visited.contains(v);
+        return false;
+    }
+
+    void printGraph(PrintStream out) {
+        nodes.stream()
+             .forEach(u -> adjacentNodes(u).stream()
+                     .forEach(v -> out.format("%s -> %s%n", u, v)));
+    }
+
+    public static class Builder<T> {
+        final Set<T> nodes = new HashSet<>();
+        final Map<T, Set<T>> edges = new HashMap<>();
+        public void addNode(T node) {
+            if (nodes.contains(node)) {
+                return;
+            }
+            nodes.add(node);
+            edges.computeIfAbsent(node, _e -> new HashSet<>());
+        }
+        public void addEdge(T u, T v) {
+            addNode(u);
+            addNode(v);
+            edges.get(u).add(v);
+        }
+        public Graph<T> build() {
+            return new Graph<>(nodes, edges);
+        }
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java
new file mode 100644
index 0000000..c1b15d3
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java
@@ -0,0 +1,766 @@
+/*
+ * 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
+ * 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.jigsaw;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import static java.lang.module.ModuleDescriptor.*;
+import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Selector.*;
+import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Division.*;
+
+public class ModuleSummary {
+    private static final String USAGE = "Usage: ModuleSummary -mp <dir> -o <outfile> [-root mn]*";
+
+    public static void main(String[] args) throws Exception {
+        int i=0;
+        Path modpath = null;
+        Path outfile = null;
+        Set<String> roots = new HashSet<>();
+        while (i < args.length && args[i].startsWith("-")) {
+            String arg = args[i++];
+            switch (arg) {
+                case "-mp":
+                    modpath = Paths.get(args[i++]);
+                    break;
+                case "-o":
+                    outfile = Paths.get(args[i++]);
+                    break;
+                case "-root":
+                    roots.add(args[i++]);
+                default:
+                    System.err.println(USAGE);
+                    System.exit(-1);
+            }
+        }
+        if (outfile == null || modpath == null) {
+            System.err.println(USAGE);
+            System.exit(1);
+        }
+        Path dir = outfile.getParent() != null ? outfile.getParent() : Paths.get(".");
+        Files.createDirectories(dir);
+
+        Map<String, ModuleSummary> modules = new HashMap<>();
+        Set<ModuleReference> mrefs = ModuleFinder.ofSystem().findAll();
+        for (ModuleReference mref : mrefs) {
+            String mn = mref.descriptor().name();
+            Path jmod = modpath.resolve(mn + ".jmod");
+            modules.put(mn, new ModuleSummary(mref, jmod));
+        }
+
+        if (roots.isEmpty()) {
+            roots.addAll(modules.keySet());
+        }
+        genReport(outfile, modules, roots, "JDK Module Summary");
+    }
+
+    static void genReport(Path outfile, Map<String, ModuleSummary> modules, Set<String> roots, String title)
+        throws IOException
+    {
+        Configuration cf = resolve(roots);
+        try (PrintStream out = new PrintStream(Files.newOutputStream(outfile))) {
+            HtmlDocument doc = new HtmlDocument(title, modules);
+            Set<ModuleDescriptor> descriptors = cf.modules().stream()
+                    .map(ResolvedModule::reference)
+                    .map(ModuleReference::descriptor)
+                    .collect(Collectors.toSet());
+            doc.writeTo(out, descriptors);
+        }
+    }
+
+    private final String name;
+    private final ModuleDescriptor descriptor;
+    private final JmodInfo jmodInfo;
+    ModuleSummary(ModuleReference mref, Path jmod) throws IOException {
+        this.name = mref.descriptor().name();
+        this.descriptor = mref.descriptor();
+        this.jmodInfo = new JmodInfo(jmod);
+    }
+
+    String name() {
+        return name;
+    }
+
+    long uncompressedSize() {
+        return jmodInfo.size;
+    }
+
+    long jmodFileSize() {
+        return jmodInfo.filesize; // estimated compressed size
+    }
+
+    ModuleDescriptor descriptor() {
+        return descriptor;
+    }
+
+    int numClasses() {
+        return jmodInfo.classCount;
+    }
+
+    long classBytes() {
+        return jmodInfo.classBytes;
+    }
+
+    int numResources() {
+        return jmodInfo.resourceCount;
+    }
+
+    long resourceBytes() {
+        return jmodInfo.resourceBytes;
+    }
+
+    int numConfigs() {
+        return jmodInfo.configCount;
+    }
+    long configBytes() {
+        return jmodInfo.configBytes;
+    }
+    int numCommands() {
+        return jmodInfo.nativeCmds.size();
+    }
+
+    long commandBytes() {
+        return jmodInfo.nativeCmds.values().stream()
+                .mapToLong(l -> l.longValue()).sum() - jmodInfo.debugInfoCmdBytes;
+    }
+    int numCommandsDebug() {
+        return jmodInfo.debugInfoCmdCount;
+    }
+    long commandDebugBytes() {
+        return jmodInfo.debugInfoCmdBytes;
+    }
+    int numNativeLibraries() {
+        return jmodInfo.nativeLibs.size();
+    }
+
+    long nativeLibrariesBytes() {
+        return jmodInfo.nativeLibs.values().stream()
+                .mapToLong(l -> l.longValue()).sum() - jmodInfo.debugInfoLibBytes;
+    }
+    int numNativeLibrariesDebug() {
+        return jmodInfo.debugInfoLibCount;
+    }
+
+    long nativeLibrariesDebugBytes() {
+        return jmodInfo.debugInfoLibBytes;
+    }
+
+    Map<String,Long> commands() {
+        return jmodInfo.nativeCmds;
+    }
+
+    Map<String,Long> nativeLibs() {
+        return jmodInfo.nativeLibs;
+    }
+
+    Map<String,Long> configFiles() {
+        return jmodInfo.configFiles;
+    }
+
+
+    static class JmodInfo {
+        final long size;
+        final long filesize;
+        final int  classCount;
+        final long classBytes;
+        final int  resourceCount;
+        final long resourceBytes;
+        final int  configCount;
+        final long configBytes;
+        final int  debugInfoLibCount;
+        final long debugInfoLibBytes;
+        final int  debugInfoCmdCount;
+        final long debugInfoCmdBytes;
+        final Map<String,Long> configFiles = new HashMap<>();
+        final Map<String,Long> nativeCmds = new HashMap<>();
+        final Map<String,Long> nativeLibs = new HashMap<>();
+
+        JmodInfo(Path jmod) throws IOException {
+            long total = 0;
+            long cBytes = 0, rBytes = 0, cfBytes = 0, dizLibBytes = 0, dizCmdBytes = 0;
+            int  cCount = 0, rCount = 0, cfCount = 0, dizLibCount = 0, dizCmdCount = 0;
+            try (ZipFile zf = new ZipFile(jmod.toFile())) {
+                for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements(); ) {
+                    ZipEntry ze = e.nextElement();
+                    String fn = ze.getName();
+                    int pos = fn.indexOf('/');
+                    String dir = fn.substring(0, pos);
+                    String filename = fn.substring(fn.lastIndexOf('/') + 1);
+                    // name shown in the column
+                    String name = filename;
+
+                    long len = ze.getSize();
+                    total += len;
+                    switch (dir) {
+                        case NATIVE_LIBS:
+                            nativeLibs.put(name, len);
+                            if (filename.endsWith(".diz")) {
+                                dizLibCount++;
+                                dizLibBytes += len;
+                            }
+                            break;
+                        case NATIVE_CMDS:
+                            nativeCmds.put(name, len);
+                            if (filename.endsWith(".diz")) {
+                                dizCmdCount++;
+                                dizCmdBytes += len;
+                            }
+                            break;
+                        case CLASSES:
+                            if (filename.endsWith(".class")) {
+                                cCount++;
+                                cBytes += len;
+                            } else {
+                                rCount++;
+                                rBytes += len;
+                            }
+                            break;
+                        case CONFIG:
+                            configFiles.put(name, len);
+                            cfCount++;
+                            cfBytes += len;
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                this.filesize = jmod.toFile().length();
+                this.classCount = cCount;
+                this.classBytes = cBytes;
+                this.resourceCount = rCount;
+                this.resourceBytes = rBytes;
+                this.configCount = cfCount;
+                this.configBytes = cfBytes;
+                this.size = total;
+                this.debugInfoLibCount = dizLibCount;
+                this.debugInfoLibBytes = dizLibBytes;
+                this.debugInfoCmdCount = dizCmdCount;
+                this.debugInfoCmdBytes = dizCmdBytes;
+            }
+        }
+
+        static final String NATIVE_LIBS = "native";
+        static final String NATIVE_CMDS = "bin";
+        static final String CLASSES     = "classes";
+        static final String CONFIG      = "conf";
+
+        static final String MODULE_ID = "module/id";
+        static final String MODULE_MAIN_CLASS = "module/main-class";
+    }
+
+    static Configuration resolve(Set<String> roots) {
+        return Configuration.empty()
+            .resolveRequires(ModuleFinder.ofSystem(),
+                             ModuleFinder.empty(),
+                             roots);
+    }
+
+    static class HtmlDocument {
+        final String title;
+        final Map<String, ModuleSummary> modules;
+        boolean requiresPublicNote = false;
+        boolean aggregatorNote = false;
+        boolean totalBytesNote = false;
+        HtmlDocument(String title, Map<String, ModuleSummary> modules) {
+            this.title = title;
+            this.modules = modules;
+        }
+
+        void writeTo(PrintStream out, Set<ModuleDescriptor> selectedModules) {
+            out.format("<html><head>%n");
+            out.format("<title>%s</title>%n", title);
+            // stylesheet
+            Arrays.stream(HtmlDocument.STYLES).forEach(out::println);
+            out.format("</head>%n");
+
+            // body begins
+            out.format("<body>%n");
+
+            // title and date
+            out.println(DOCTITLE.toString(title));
+            out.println(VERSION.toString(String.format("%tc", new Date())));
+
+            // total modules and sizes
+            long totalBytes = selectedModules.stream()
+                    .map(ModuleDescriptor::name)
+                    .map(modules::get)
+                    .mapToLong(ModuleSummary::uncompressedSize)
+                    .sum();
+            String[] sections = new String[] {
+                    String.format("%s: %d", "Total modules", selectedModules.size()),
+                    String.format("%s: %,d bytes (%s %s)", "Total size",
+                                  totalBytes,
+                                  System.getProperty("os.name"),
+                                  System.getProperty("os.arch"))
+            };
+            out.println(SECTION.toString(sections));
+
+            // write table and header
+            out.println(String.format("<table class=\"%s\">", MODULES));
+            out.println(header("Module", "Requires", "Exports",
+                    "Services", "Commands/Native Libraries/Configs"));
+
+            // write contents - one row per module
+            selectedModules.stream()
+                    .sorted(Comparator.comparing(ModuleDescriptor::name))
+                    .map(m -> modules.get(m.name()))
+                    .map(ModuleTableRow::new)
+                    .forEach(table -> table.writeTo(out));
+
+            out.format("</table>");  // end table
+            out.format("</body>");
+            out.println("</html>");
+        }
+
+        String header(String... columns) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("<tr>");
+            Arrays.stream(columns)
+                    .forEach(cn -> sb.append("  <th>").append(cn).append("</th>").append("\n"));
+            sb.append("</tr>");
+            return sb.toString();
+        }
+
+        static enum Selector {
+            MODULES("modules"),
+            MODULE("module"),
+            MODULE_DEF("code name def"),
+            AGGREGATOR("code name def agg"),
+            REQUIRES("code"),
+            REQUIRES_PUBLIC("code reexp"),
+            BR("br"),
+            CODE("code"),
+            NUMBER("number"),;
+            final String name;
+            Selector(String name) {
+                this.name = name;
+            }
+            @Override
+            public String toString() {
+                return name;
+            }
+        }
+
+        static enum Division {
+            DOCTITLE("doctitle"),
+            VERSION("versions"),
+            SECTION("section");
+            final String name;
+
+            Division(String name) {
+                this.name = name;
+            }
+
+            public String toString(String... lines) {
+                String value = Arrays.stream(lines).collect(Collectors.joining("<br>\n"));
+                return "<div class=\"" + name + "\">" + value + "</div>";
+            }
+        }
+
+        class ModuleTableRow {
+            private final ModuleSummary ms;
+            private final Set<ModuleDescriptor> deps;
+            private final int maxRows;
+            private final boolean aggregator;
+            ModuleTableRow(ModuleSummary ms) {
+                this.ms = ms;
+                Configuration cf = resolve(Set.of(ms.name()));
+                this.deps = cf.modules().stream()
+                        .map(ResolvedModule::reference)
+                        .map(ModuleReference::descriptor)
+                        .collect(Collectors.toSet());
+                int count = (ms.numClasses() > 0 ? 1 : 0) +
+                            (ms.numResources() > 0 ? 1 : 0) +
+                            (ms.numConfigs() > 0 ? 1 : 0) +
+                            (ms.numNativeLibraries() > 0 ? 1 : 0) +
+                            (ms.numNativeLibrariesDebug() > 0 ? 1 : 0) +
+                            (ms.numCommands() > 0 ? 1 : 0) +
+                            (ms.numCommandsDebug() > 0 ? 1 : 0);
+                this.aggregator = ms.numClasses() == 1 && count == 1; // only module-info.class
+
+                // 5 fixed rows (name + 2 transitive count/size + 2 blank rows)
+                this.maxRows = 5 + count + (aggregator && !aggregatorNote ? 2 : 0);
+            }
+
+            public void writeTo(PrintStream out) {
+                out.println(String.format("<tr id=\"%s\" class=\"%s\">", ms.name(), MODULE));
+                out.println(moduleColumn());
+                out.println(requiresColumn());
+                out.println(exportsColumn());
+                out.println(servicesColumn());
+                out.println(otherSectionColumn());
+                out.println("</td>");
+                out.println("</tr>");
+            }
+
+            public String moduleColumn() {
+                // module name
+                StringBuilder sb = new StringBuilder("  ");
+                sb.append("<td>");
+                sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
+                sb.append(moduleName(ms.name()));
+                sb.append(blankRow());
+                // metadata
+                sb.append(toTableRow("class", "classes", ms.numClasses(), ms.classBytes()));
+                sb.append(toTableRow("resource", "resources", ms.numResources(), ms.resourceBytes()));
+                sb.append(toTableRow("config", "configs", ms.numConfigs(), ms.configBytes()));
+                sb.append(toTableRow("native library", "native libraries",
+                                     ms.numNativeLibraries(), ms.nativeLibrariesBytes()));
+                sb.append(toTableRow("native library debug", "native libraries debug",
+                                     ms.numNativeLibrariesDebug(), ms.nativeLibrariesDebugBytes()));
+                sb.append(toTableRow("command", "commands", ms.numCommands(), ms.commandBytes()));
+                sb.append(toTableRow("command debug", "commands debug",
+                                     ms.numCommandsDebug(), ms.commandDebugBytes()));
+                sb.append(blankRow());
+
+                // transitive dependencies
+                long reqBytes = deps.stream()
+                                    .filter(d -> !d.name().equals(ms.name()))
+                                    .mapToLong(d -> modules.get(d.name()).uncompressedSize())
+                                    .sum();
+                long reqJmodFileSize = deps.stream()
+                                            .mapToLong(d -> modules.get(d.name()).jmodFileSize())
+                                            .sum();
+                // size
+                if (totalBytesNote) {
+                    sb.append(toTableRow("Total bytes", ms.uncompressedSize()));
+                    sb.append(toTableRow("Total bytes of dependencies", reqBytes));
+                } else {
+                    // print footnote
+                    sb.append(toTableRow("Total bytes<sup>1</sup>", ms.uncompressedSize()));
+                    sb.append(toTableRow("Total bytes of dependencies<sup>2</sup>", reqBytes));
+                }
+                String files = deps.size() == 1 ? "file" : "files";
+                sb.append(toTableRow(String.format("Total jmod bytes (%d %s)", deps.size(), files), reqJmodFileSize));
+
+                if (aggregator && !aggregatorNote) {
+                    aggregatorNote = true;
+                    sb.append(blankRow());
+                    sb.append(toTableRow("<i>* aggregator is a module with module-info.class only</i>", BR));
+                }
+                if (!totalBytesNote) {
+                    totalBytesNote = true;
+                    sb.append(blankRow());
+                    sb.append(toTableRow("<i><sup>1</sup>sum of all files including debug files</i>", BR));
+                    sb.append(toTableRow("<i><sup>2</sup>sum of direct and indirect dependencies</i>", BR));
+                }
+                sb.append("</table>").append("</td>");
+                return sb.toString();
+            }
+
+            private String moduleName(String mn) {
+                if (aggregator) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append(String.format("<tr><td colspan=\"2\"><span class=\"%s\">", AGGREGATOR))
+                      .append(mn)
+                      .append("</span>").append("&nbsp;&nbsp;");
+                    if (!aggregatorNote) {
+                        sb.append("(aggregator<sup>*</sup>)");
+                    } else {
+                        sb.append("(aggregator)");
+                    }
+                    sb.append("</td></tr>");
+                    return sb.toString();
+                } else {
+                    return toTableRow(mn, MODULE_DEF);
+                }
+            }
+
+            public String requiresColumn() {
+                StringBuilder sb = new StringBuilder();
+                sb.append(String.format("<td>"));
+                boolean footnote = requiresPublicNote;
+                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;
+                            String req = String.format("<a class=\"%s\" href=\"#%s\">%s</a>",
+                                                       sel, r.name(), r.name());
+                            if (!requiresPublicNote && requiresPublic) {
+                                requiresPublicNote = true;
+                                req += "<sup>*</sup>";
+                            }
+                            sb.append(req).append("\n").append("<br>");
+                        });
+
+                if (!ms.name().equals("java.base")) {
+                    int directDeps = ms.descriptor().requires().size();
+                    int indirectDeps = deps.size()-directDeps-1;
+                    for (int i=directDeps; i< (maxRows-1); i++) {
+                        sb.append("<br>");
+                    }
+                    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>");
+                }
+                sb.append("</td>");
+                return sb.toString();
+            }
+
+            public String exportsColumn() {
+                StringBuilder sb = new StringBuilder();
+                sb.append(String.format("  <td class=\"%s\">", CODE));
+                ms.descriptor().exports().stream()
+                        .sorted(Comparator.comparing(Exports::source))
+                        .filter(e -> !e.isQualified())
+                        .forEach(e -> sb.append(e.source()).append("<br>").append("\n"));
+                sb.append("</td>");
+                return sb.toString();
+            }
+
+            public String servicesColumn() {
+                StringBuilder sb = new StringBuilder();
+                sb.append(String.format("  <td class=\"%s\">", CODE));
+                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)))
+                        .forEach(p -> sb.append(p).append("<br>").append("\n"));
+                sb.append("</td>");
+                return sb.toString();
+            }
+
+            public String otherSectionColumn() {
+                StringBuilder sb = new StringBuilder();
+                sb.append("<td>");
+                sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
+                // commands
+                if (ms.numCommands() > 0) {
+                    sb.append(toTableRow("bin/", CODE));
+                    ms.commands().entrySet().stream()
+                            .sorted(Map.Entry.comparingByKey())
+                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
+                    sb.append(blankRow());
+                }
+
+                // native libraries
+                if (ms.numNativeLibraries() > 0) {
+                    sb.append(toTableRow("lib/", CODE));
+                    ms.nativeLibs().entrySet().stream()
+                            .sorted(Map.Entry.comparingByKey())
+                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
+                    sb.append(blankRow());
+                }
+
+                // config files
+                if (ms.numConfigs() > 0) {
+                    sb.append(toTableRow("conf/", CODE));
+                    ms.configFiles().entrySet().stream()
+                            .sorted(Map.Entry.comparingByKey())
+                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
+                }
+                // totals
+                sb.append("</table>").append("</td>");
+                return sb.toString();
+            }
+
+            private String blankRow() {
+                return toTableRow("&nbsp;", BR);
+            }
+
+            private String toTableRow(String col, Selector selector) {
+                TableDataBuilder builder = new TableDataBuilder();
+                builder.colspan(selector, 2, col);
+                return builder.build();
+            }
+
+            private String toTableRow(String col1, long col2) {
+                return toTableRow(col1, col2, BR);
+            }
+
+            private String toTableRow(String col1, long col2, Selector selector) {
+                TableDataBuilder builder = new TableDataBuilder();
+                builder.data(selector, col1);
+                builder.data(col2);
+                return builder.build();
+
+            }
+
+            private String toTableRow(String singular, String plural, int count, long bytes) {
+                if (count == 0) {
+                    return "";
+                }
+                TableDataBuilder builder = new TableDataBuilder();
+                if (count == 1) {
+                    builder.data(count + " " + singular);
+                } else {
+                    builder.data(count + " " + plural);
+                }
+                builder.data(bytes);
+                return builder.build();
+            }
+
+            class TableDataBuilder {
+                private final StringBuilder sb;
+                TableDataBuilder() {
+                    this.sb = new StringBuilder("<tr>");
+                }
+                TableDataBuilder data(String s) {
+                    data(BR, s);
+                    return this;
+                }
+                TableDataBuilder data(long num) {
+                    data(NUMBER, String.format("%,d", num));
+                    return this;
+                }
+                TableDataBuilder colspan(Selector selector, int columns, String data) {
+                    sb.append("<td colspan=\"").append(columns).append("\">");
+                    sb.append("<span class=\"").append(selector).append("\">");
+                    sb.append(data).append("</span></td>");
+                    return this;
+                }
+
+                TableDataBuilder data(Selector selector, String data) {
+                    sb.append("<td class=\"").append(selector).append("\">");
+                    sb.append(data).append("</td>");
+                    return this;
+                }
+                String build() {
+                    sb.append("</tr>");
+                    return sb.toString();
+                }
+            }
+        }
+
+        private static final String[] STYLES = new String[]{
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"/.fonts/dejavu.css\"/>",
+                "<style type=\"text/css\">",
+                "        HTML, BODY, DIV, SPAN, APPLET, OBJECT, IFRAME, H1, H2, H3, H4, H5, H6, P,",
+                "        BLOCKQUOTE, PRE, A, ABBR, ACRONYM, ADDRESS, BIG, CITE, CODE, DEL, DFN, EM,",
+                "        IMG, INS, KBD, Q, S, SAMP, SMALL, STRIKE, STRONG, SUB, SUP, TT, VAR, B, U,",
+                "        I, CENTER, DL, DT, DD, OL, UL, LI, FIELDSET, FORM, LABEL, LEGEND, TABLE,",
+                "        CAPTION, TBODY, TFOOT, THEAD, TR, TH, TD, ARTICLE, ASIDE, CANVAS, DETAILS,",
+                "        EMBED, FIGURE, FIGCAPTION, FOOTER, HEADER, HGROUP, MENU, NAV, OUTPUT, RUBY,",
+                "        SECTION, SUMMARY, TIME, MARK, AUDIO, VIDEO {",
+                "          margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit;",
+                "          vertical-align: baseline; }",
+                "        ARTICLE, ASIDE, DETAILS, FIGCAPTION, FIGURE, ",
+                "        FOOTER, HEADER, HGROUP, MENU, NAV, SECTION { display: block; }",
+                "        BLOCKQUOTE, Q { quotes: none; }",
+                "        BLOCKQUOTE:before, BLOCKQUOTE:after, Q:before, Q:after {",
+                "                content: ''; content: none; }",
+                "        TABLE { border-collapse: collapse; border-spacing: 0; }",
+                "        A { text-decoration: none; }",
+                "        A:link { color: #437291; }",
+                "        A:visited { color: #666666; }",
+                "        A.anchor:link, A.anchor:visited { color: black; }",
+                "        A[href]:hover { color: #e76f00; }",
+                "        A IMG { border-width: 0px; }",
+                "        HTML { font-size: 20px; } /* baseline grid */",
+                "        HTML > BODY { font-size: 14px; }",
+                "        BODY {",
+                "          background: white;",
+                "          margin: 40px;",
+                "          margin-bottom: 150%;",
+                "          line-height: 20px;",
+                "          -webkit-text-size-adjust: 100%; /* iOS */",
+                "          color: #222;",
+                "        }",
+                "        BODY { font-family: \"DejaVu Serif\", \"Lucida Bright\", \"Bookman Old Style\",",
+                "                            Georgia, serif; }",
+                "        CODE, TT, .jref, DIV.spec .open, TABLE.profiles {",
+                "          font-family: \"DejaVu Sans\", \"Lucida Sans\", Helvetica, sans-serif; }",
+                "        PRE, .code { font-family: \"DejaVu Sans Mono\", \"Bitstream Vera Sans Mono\",",
+                "                            Monaco, \"Courier New\", monospace; }",
+                "        H1, H2, H3, H4 { color: green; font-weight: bold; }",
+                "        I { font-style: italic; }",
+                "        TH { font-weight: bold; }",
+                "        P { text-indent: 40px; }",
+                "        P:first-child, UL + P, OL + P, BLOCKQUOTE + P, TABLE + P, P.subsection,",
+                "          P.break, DIV.profiles-table + P { text-indent: 0; }",
+                "        P.break { margin-top: 10px; }",
+                "        P.subsection { margin-top: 20px; }",
+                "        P.subsection SPAN.title { font-weight: bold; padding-right: 20px; }",
+                "        UL, OL { margin: 10px 0; padding-left: 40px; }",
+                "        LI { margin-bottom: 10px; }",
+                "        UL.compact LI { margin-bottom: 0; }",
+                "        PRE { padding: 0; margin: 10px 0 10px 20px; background: #eee; width: 45em; }",
+                "        BLOCKQUOTE { margin: 10px 0; margin-left: 20px; }",
+                "        LI BLOCKQUOTE { margin-left: 0; }",
+                "        UL LI { list-style-type: square; }",
+                "        .todo { color: darkred; text-align: right; }",
+                "        .error { color: red; font-weight: bold; }",
+                "        .warn { color: #ee0000; font-weight: bold; }",
+                "        DIV.doctitle { margin-top: -13px;",
+                "          font-size: 22px; line-height: 40px; font-weight: bold; }",
+                "        DIV.twarn { color: #cc0000; font-weight: bold; margin-bottom: 9px; }",
+                "        DIV.subtitle { margin-top: 2px; font-size: 18px; font-weight: bold; }",
+                "        DIV.authors { margin-top: 10px; margin-bottom: 10px; font-size: 16px; }",
+                "        DIV.author A { font-style: italic; }",
+                "        DIV.version { margin-top: 10px; font-size: 12px; }",
+                "        DIV.version, DIV.legal-notice { font-size: 12px; line-height: 15px; }",
+                "        SPAN.hash { font-size: 9px; }",
+                "        DIV.version SPAN.modified { color: green; font-weight: bold; }",
+                "        DIV.head { margin-bottom: 20px; }",
+                "        DIV.section > DIV.title, DIV.section DIV.number SPAN {",
+                "          font-size: 15px; font-weight: bold; }",
+                "        TABLE { border-collapse: collapse; border: none; }",
+                "        TD.number { text-align: right; }",
+                "        TD, TH { text-align: left; white-space: nowrap; }",
+                "        TD.name, SPAN.name { font-weight: bold; }",
+                "        ",
+                "        TABLE.module { width: 100%; }",
+                "        TABLE.module TD:first-child { padding-right: 10px; }",
+                "        TR.module > TD { padding: 10px 0; border-top: 1px solid black; }",
+                "        TR > TH { padding-bottom: 10px; }",
+                "        TR.br TD { padding-top: 20px; }",
+                "        TABLE.modules { margin-top: 20px; }",
+                "        TABLE.modules > TBODY > TR > TD:nth-child(even) { background: #eee; }",
+                "        TABLE.modules > TBODY > TR > TD, TABLE.modules > TBODY > TR > TH {",
+                "          padding-left: 10px; padding-right: 10px; }",
+                "        .reexp, .def { font-weight: bold; }",
+                "        .agg { font-style: italic; }",
+                "        SUP { height: 0; line-height: 1; position: relative;",
+                "              vertical-align: baseline; bottom: 1ex; font-size: 11px; }",
+                "</style>",
+        };
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html b/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html
new file mode 100644
index 0000000..8414f35
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html
@@ -0,0 +1,627 @@
+<html>

+<head>

+<title>JDK Technology Summary</title>

+<style type="text/css">

+table { border: 1px solid black; border-collapse: collapse; }

+tr.se-base { background-color: bisque; }

+tr.se-misc { background-color: lavender; }

+tr.se-ee   { background-color: lightgreen; }

+tr.se-ext  { background-color: pink; }

+td { font-family: monospace; padding: 4px; border: 1px solid; }

+</style>

+</head>

+

+<h1>JCP Technologies in the Modular JDK</h1>

+

+<p><em>Last updated 2015-03-06 (Added java.datatransfer. Assumes JNLP is modularized, and StAX joins the Java SE Platform.)</em></p>

+

+<p><a href="module-summary.html">JDK Module Summary</a> | Technologies in the <a href="https://docs.oracle.com/javase/8/docs/">Java SE Documentation</a></p>

+

+<table>

+<tr><th>Legend</th></tr>

+<tr class="se-base"><td><a href="https://jcp.org/en/jsr/platform?listBy=2&listByType=platform">JCP technology in the Java SE Platform only -- in java.base</a></td></tr>

+<tr class="se-misc"><td><a href="https://jcp.org/en/jsr/platform?listBy=2&listByType=platform">JCP technology in the Java SE Platform only -- not in java.base</a></td></tr>

+<tr class="se-ee"><td><a href="https://jcp.org/en/jsr/platform?listBy=3&listByType=platform">JCP technology in the Java SE Platform and the Java EE Platform</a></a></td></tr>

+<tr class="se-ext"><td><a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#endorsed-standards-apis">JCP technology in the Java SE Platform based on non-JCP standards</a></a></td></tr>

+<tr><td>JCP technology in neither the Java SE or EE Platforms</td></tr>

+</table>

+

+<p><em>An <strong>upgradeable</strong> module contains JCP technology that is in the Java SE Platform but is not exclusive to the Java SE Platform, i.e., the green and pink technologies. Most upgradeable modules are defined by loaders other than the bootstrap.</em></p>

+

+<br/>

+

+<table>

+<tr>

+<th>Technology</th>

+<th>Original JSR</th>

+<th><a href="https://jcp.org/en/procedures/jcp2#DEF">Original Target</a></th>

+<th>Module</th>

+<th><a href="https://jcp.org/en/procedures/jcp2#2.1.2">Evolved By</a></th>

+<th>History</th>

+<th>Profile/SE</th>

+<th>Loader</th>

+<th>Upg?</th>

+</tr>

+

+<tr class="se-misc">

+<td>JMX</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=3">3</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.management">java.management</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Print Service</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=6">6</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.desktop">java.desktop</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>SE</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Preferences</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=10">10</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.prefs">java.prefs</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Image I/O</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=15">15</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.desktop">java.desktop</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>SE</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>SASL</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=28">28</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.security.sasl"/>java.security.sasl</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Logging</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=47">47</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.logging">java.logging</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>NIO</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=51">51</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr>

+<td>JNLP</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=56">56</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.desktop">java.jnlp</a></td>

+<td>Original JSR</td>

+<td></td>

+<td>N/A</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Beans Persistence</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=57">57</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.desktop">java.desktop</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>SE</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>GSS</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=72">72</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.security.jgss">java.security.jgss</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>XML Digital Signature</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=105">105</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml.crypto">java.xml.crypto</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JDBC Rowset</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=114">114</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.sql.rowset">java.sql.rowset</a></td>

+<td>Original JSR</td>

+<td>Co-evolved with JDBC</td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JMX Remote</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=160">160</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.management">java.management</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Profiling (Agent)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=163">163</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.instrument">java.instrument</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Profiling (JMX)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=163">163</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.management">java.management</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Concurrency Utilities</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=166">166</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Annotations</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=175">175</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>StAX</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=173">173</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml">java.xml</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Annotations (Language Model)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=175">175</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.compiler"/>java.compiler</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Compiler</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=199">199</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.compiler">java.compiler</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Pack200</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=200">200</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>NIO.2</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=203">203</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JAXP</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=206">206</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml">java.xml</a></td>

+<td>UJSR for Java SE</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JDBC</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=221">221</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.sql">java.sql</a></td>

+<td>Original JSR</td>

+<td>Co-evolved with JDBC Rowset</td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Scripting</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=223">223</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.scripting">java.scripting</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr>

+<td>Smart Card I/O</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=268">268</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.smartcardio">java.smartcardio</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>N/A</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Annotation Processing</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=269">269</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.compiler">java.compiler</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>InvokeDynamic</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=292">292</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Type Annotations</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=308">308</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Type Annotations (Language Model)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=308">308</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.compiler"/>java.compiler</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Date and Time</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=310">310</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Streams</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=335">335</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>Collections, Math, I18N, I/O, Net, Reflection</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-base">

+<td>JCA, JAAS, JSSE</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.base"/>java.base</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>1</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Applet, AWT, Swing, Java 2D, Beans, A11Y, Sound</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.desktop"/>java.desktop</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>SE</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>Data Transfer</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.datatransfer"/>java.datatransfer</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>SE</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JNDI</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.naming"/>java.naming</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>3</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>RMI</td>

+<td>---</td>

+<td>---</td>

+<td><a href="module-summary.html#java.rmi"/>java.rmi</a></td>

+<td>UJSR for Java SE</td>

+<td></td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-misc">

+<td>JAF</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=925">925</a></td>

+<td>---</td>

+<td><a href="module-summary.html#java.activation">java.activation</a></a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<tr class="se-ext">

+<td>RMI-IIOP, IDL</td>

+<td>(OMG)</td>

+<td>---</td>

+<td><a href="module-summary.html#java.corba"/>java.corba</a></td>

+<td>UJSR for Java SE</td>

+<td>Formerly an <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#endorsed-standards-apis">Endorsed Standard</a></td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<tr class="se-ext">

+<td>DOM, SAX</td>

+<td>(W3C)</td>

+<td>---</td>

+<td><a href="module-summary.html#java.xml">java.xml</a></td>

+<td>UJSR for Java SE</td>

+<td>Formerly an <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#endorsed-standards-apis">Endorsed Standard</a></td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+<tr class="se-ee">

+<td>SAAJ</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=67">67</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml.ws">java.xml.ws</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (f.k.a. JAXM)</td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<tr class="se-ee">

+<td>Web Services Metadata</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=181">181</a></td>

+<td>Java EE</td>

+<td><a href="module-summary.html#java.xml.ws">java.xml.ws</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<tr class="se-ee">

+<td>JAXB</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=222">222</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml.bind">java.xml.bind</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<tr class="se-ee">

+<td>JAXWS</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=224">224</a></td>

+<td>Java SE</td>

+<td><a href="module-summary.html#java.xml.ws">java.xml.ws</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a></td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<!-- Alex: The Java SE Platform incorporates a cutdown version of the javax.annotation package from the Java EE Platform. -->

+<tr class="se-ee">

+<td>Common Annotations</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=250">250</a></td>

+<td>Java SE,EE</td>

+<td><a href="module-summary.html#java.annotations.common">java.annotations.common</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<!-- Alex: The Java SE Platform incorporates a cutdown version of the javax.transaction package from the Java EE Platform. -->

+<tr class="se-ee">

+<td>JTA (non-XA)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=907">907</a></td>

+<td>---</td>

+<td><a href="module-summary.html#java.transaction">java.transaction</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>SE</td>

+<td>ext</td>

+<td>Yes</td>

+</tr>

+

+<!-- Alex: The Java SE Platform incorporates the same version of the javax.transaction.xa package as the Java EE Platform. -->

+<tr class="se-ee">

+<td>JTA (XA)</td>

+<td><a href="https://jcp.org/en/jsr/detail?id=907">907</a></td>

+<td>---</td>

+<td><a href="module-summary.html#java.sql"/>java.sql</a></td>

+<td>Original JSR</td>

+<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>

+<td>2</td>

+<td>boot</td>

+<td>No</td>

+</tr>

+

+</table>

+

+</html>

diff --git a/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java
deleted file mode 100644
index 17a63e7..0000000
--- a/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * GenJdepsModulesXml augments the input modules.xml file(s)
- * to include the module membership from the given path to
- * the JDK exploded image.  The output file is used by jdeps
- * to analyze dependencies and enforce module boundaries.
- *
- * The input modules.xml file defines the modular structure of
- * the JDK as described in JEP 200: The Modular JDK
- * (http://openjdk.java.net/jeps/200).
- *
- * $ java build.tools.module.GenJdepsModulesXml \
- *        -o com/sun/tools/jdeps/resources/modules.xml \
- *        -mp $OUTPUTDIR/modules \
- *        top/modules.xml
- */
-public final class GenJdepsModulesXml {
-    private final static String USAGE =
-        "Usage: GenJdepsModulesXml -o <output file> -mp build/modules path-to-modules-xml";
-
-    public static void main(String[] args) throws Exception {
-        Path outfile = null;
-        Path modulepath = null;
-        int i = 0;
-        while (i < args.length) {
-            String arg = args[i];
-            if (arg.equals("-o")) {
-                outfile = Paths.get(args[i+1]);
-                i = i+2;
-            } else if (arg.equals("-mp")) {
-                modulepath = Paths.get(args[i+1]);
-                i = i+2;
-                if (!Files.isDirectory(modulepath)) {
-                    System.err.println(modulepath + " is not a directory");
-                    System.exit(1);
-                }
-            } else {
-                break;
-            }
-        }
-        if (outfile == null || modulepath == null || i >= args.length) {
-            System.err.println(USAGE);
-            System.exit(-1);
-        }
-
-        GenJdepsModulesXml gentool = new GenJdepsModulesXml(modulepath);
-        Set<Module> modules = new HashSet<>();
-        for (; i < args.length; i++) {
-            Path p = Paths.get(args[i]);
-            modules.addAll(ModulesXmlReader.readModules(p)
-                    .stream()
-                    .map(gentool::buildIncludes)
-                    .collect(Collectors.toSet()));
-        }
-
-        Files.createDirectories(outfile.getParent());
-        ModulesXmlWriter.writeModules(modules, outfile);
-    }
-
-    final Path modulepath;
-    public GenJdepsModulesXml(Path modulepath) {
-        this.modulepath = modulepath;
-    }
-
-    private static String packageName(Path p) {
-        return packageName(p.toString().replace(File.separatorChar, '/'));
-    }
-    private static String packageName(String name) {
-        int i = name.lastIndexOf('/');
-        return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
-    }
-
-    private static boolean includes(String name) {
-        return name.endsWith(".class");
-    }
-
-    public Module buildIncludes(Module module) {
-        Module.Builder mb = new Module.Builder(module);
-        Path mclasses = modulepath.resolve(module.name());
-        try {
-            Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
-                         -> includes(p.getFileName().toString()))
-                 .map(p -> packageName(mclasses.relativize(p)))
-                 .forEach(mb::include);
-        } catch (NoSuchFileException e) {
-            // aggregate module may not have class
-        } catch (IOException ioe) {
-            throw new UncheckedIOException(ioe);
-        }
-        return mb.build();
-    }
-}
diff --git a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
new file mode 100644
index 0000000..255e5ef
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package build.tools.module;
+
+import java.io.BufferedWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 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.
+ *
+ * GenModulesList build tool currently generates the modules.list from
+ * the module-info.java from the source tree that will be used for
+ * the make target and dependences.
+ *
+ * The build currently invokes gensrc-$MODULE.gmk after modules.list
+ * is generated.  Hence, platform-specific requires is not supported.
+ */
+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";
+
+    public static void main(String... args) throws Exception {
+        Path outfile = null;
+        Path moduleInfoJava = null;
+        Map<String, Set<String>> options = new HashMap<>();
+
+        // 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") ||
+                        option.equals("-uses") ||
+                        option.equals("-provides")) {
+                    options.computeIfAbsent(option, _k -> new HashSet<>()).add(arg);
+                } else if (option.equals("-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");
+                }
+            }
+        }
+
+        if (moduleInfoJava == null || outfile == null) {
+            System.err.println(USAGE);
+            System.exit(-1);
+        }
+        // read module-info.java
+        Module.Builder builder = ModuleInfoReader.builder(moduleInfoJava);
+        augment(builder, options);
+
+        // generate new module-info.java
+        Module module = builder.build();
+        Path parent = outfile.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+
+        try (BufferedWriter writer = Files.newBufferedWriter(outfile)) {
+            writer.write(module.toString());
+        }
+    }
+
+    private static void augment(Module.Builder builder, Map<String, Set<String>> options) {
+        for (String opt : options.keySet()) {
+            if (opt.equals("-exports")) {
+                for (String arg : options.get(opt)) {
+                    int index = arg.indexOf('/');
+                    if (index > 0) {
+                        String pn = arg.substring(0, index);
+                        String mn = arg.substring(index + 1, arg.length());
+                        builder.exportTo(pn, mn);
+                    } else {
+                        builder.export(arg);
+                    }
+                }
+            } else if (opt.equals("-uses")) {
+                options.get(opt).stream()
+                        .forEach(builder::use);
+            } else if (opt.equals("-provides")) {
+                for (String arg : options.get(opt)) {
+                    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());
+                    builder.provide(service, impl);
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/module/GenModuleLoaderMap.java b/jdk/make/src/classes/build/tools/module/GenModuleLoaderMap.java
new file mode 100644
index 0000000..6719277
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/module/GenModuleLoaderMap.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.module;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class GenModuleLoaderMap {
+    private static final String USAGE =
+        "GenModuleLoaderMap -o <output-file> -boot m1[,m2]* -platform m3[,m4]* <original-source>";
+
+    public static void main(String... args) throws Exception {
+        // default set of boot modules and ext modules
+        Stream<String> bootModules = Stream.empty();
+        Stream<String> platformModules = Stream.empty();
+        Path outfile = null;
+        Path source = null;
+        for (int i=0; i < args.length; i++) {
+            String option = args[i];
+            if (option.startsWith("-")) {
+                String arg = args[++i];
+                if (option.equals("-boot")) {
+                    String[] mns = arg.split(",");
+                    bootModules = Stream.concat(bootModules, Arrays.stream(mns));
+                } else if (option.equals("-platform")) {
+                    String[] mns = arg.split(",");
+                    platformModules = Stream.concat(platformModules, Arrays.stream(mns));
+                } else if (option.equals("-o")) {
+                    outfile = Paths.get(arg);
+                } else {
+                    throw new IllegalArgumentException("invalid option: " + option);
+                }
+            } else {
+                source = Paths.get(option);
+            }
+        }
+
+        if (outfile == null) {
+            throw new IllegalArgumentException("-o must be specified");
+        }
+        if (Files.notExists(source)) {
+            throw new IllegalArgumentException(source + " not exist");
+        }
+
+        boolean needsQuotes = outfile.toString().contains(".java.tmp");
+
+        try (BufferedWriter bw = Files.newBufferedWriter(outfile, StandardCharsets.UTF_8);
+             PrintWriter writer = new PrintWriter(bw)) {
+            for (String line : Files.readAllLines(source)) {
+                if (line.contains("@@BOOT_MODULE_NAMES@@")) {
+                    line = patch(line, "@@BOOT_MODULE_NAMES@@", bootModules, needsQuotes);
+                } else if (line.contains("@@PLATFORM_MODULE_NAMES@@")) {
+                    line = patch(line, "@@PLATFORM_MODULE_NAMES@@", platformModules, needsQuotes);
+                }
+                writer.println(line);
+            }
+        }
+    }
+
+    private static String patch(String s, String tag, Stream<String> stream, boolean needsQuotes) {
+        String mns = null;
+        if (needsQuotes) {
+            mns = stream.sorted()
+                .collect(Collectors.joining("\",\n            \""));
+        } else {
+            mns = stream.sorted()
+                .collect(Collectors.joining("\n"));
+        }
+        return s.replace(tag, mns);
+    }
+
+    /**
+     * Reads the contents of the given modules file.
+     */
+    private static Set<String> readModuleSet(String name) throws IOException {
+        try (InputStream is = GenModuleLoaderMap.class.getResourceAsStream(name);
+             BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
+            return reader.lines().collect(Collectors.toSet());
+        }
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/module/GenModulesList.java b/jdk/make/src/classes/build/tools/module/GenModulesList.java
deleted file mode 100644
index 66a9f8c..0000000
--- a/jdk/make/src/classes/build/tools/module/GenModulesList.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import java.io.PrintWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * $ java build.tools.module.GenModulesList \
- *        -o modules.list \
- *        top/modules.xml ...
- */
-public final class GenModulesList {
-    private final static String USAGE =
-        "Usage: GenModulesList -o <output file> path-to-modules-xml";
-
-    private Set<Module> modules = new HashSet<>();
-    private HashMap<String,Module> nameToModule = new HashMap<>();
-
-    public static void main(String[] args) throws Exception {
-        GenModulesList gen = new GenModulesList();
-        gen.run(args);
-    }
-
-    void run(String[] args) throws Exception {
-        Path outfile = null;
-        int i = 0;
-        while (i < args.length) {
-            String arg = args[i];
-            if (arg.equals("-o")) {
-                outfile = Paths.get(args[i+1]);
-                i = i+2;
-            } else {
-                break;
-            }
-        }
-        if (outfile == null || i >= args.length) {
-            System.err.println(USAGE);
-            System.exit(-1);
-        }
-
-        for (; i < args.length; i++) {
-            Path p = Paths.get(args[i]);
-            modules.addAll(ModulesXmlReader.readModules(p));
-        }
-
-        modules.stream()
-               .forEach(m -> nameToModule.put(m.name(), m));
-
-        Path parent = outfile.getParent();
-        if (parent != null)
-            Files.createDirectories(parent);
-
-        Iterable<Module> sortedModules = (new TopoSorter(modules)).result();
-        try (PrintWriter writer = new PrintWriter(outfile.toFile())) {
-            for (Module m : sortedModules) {
-                if (isNotAggregator(m)) {
-                    String deps = getModuleDependences(m).stream()
-                            .filter(GenModulesList::isNotAggregator)
-                            .map(Module::name)
-                            .collect(Collectors.joining(" "));
-                    writer.format("%s: %s%n", m.name(), deps);
-                }
-            }
-        }
-    }
-
-    private Module nameToModule(String name) {
-        return nameToModule.get(name);
-    }
-
-    private Set<Module> getModuleDependences(Module m) {
-        return m.requires().stream()
-                .map(d -> d.name())
-                .map(this::nameToModule)
-                .collect(Collectors.toSet());
-    }
-
-    static boolean isNotAggregator(Module m) {
-        return isNotAggregator(m.name());
-    }
-
-    static boolean isNotAggregator(String name) {
-        return AGGREGATORS.contains(name) ? false : true;
-    }
-
-    static final List<String> AGGREGATORS = Arrays.asList(new String[] {
-            "java.se", "java.compact1", "java.compact2", "java.compact3"});
-
-    class TopoSorter {
-        final Deque<Module> result = new LinkedList<>();
-        final Deque<Module> nodes = new LinkedList<>();
-
-        TopoSorter(Collection<Module> nodes) {
-            nodes.stream()
-                 .forEach(m -> this.nodes.add(m));
-
-            sort();
-        }
-
-        public Iterable<Module> result() {
-            return result;
-        }
-
-        private void sort() {
-            Deque<Module> visited = new LinkedList<>();
-            Deque<Module> done = new LinkedList<>();
-            Module node;
-            while ((node = nodes.poll()) != null) {
-                if (!visited.contains(node)) {
-                    visit(node, visited, done);
-                }
-            }
-        }
-
-        private void visit(Module m, Deque<Module> visited, Deque<Module> done) {
-            if (visited.contains(m)) {
-                if (!done.contains(m)) {
-                    throw new IllegalArgumentException("Cyclic detected: " +
-                            m + " " + getModuleDependences(m));
-                }
-                return;
-            }
-            visited.add(m);
-            getModuleDependences(m).stream()
-                                   .forEach(x -> visit(x, visited, done));
-            done.add(m);
-            result.addLast(m);
-        }
-    }
-}
diff --git a/jdk/make/src/classes/build/tools/module/ImageBuilder.java b/jdk/make/src/classes/build/tools/module/ImageBuilder.java
deleted file mode 100644
index b87d593..0000000
--- a/jdk/make/src/classes/build/tools/module/ImageBuilder.java
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import jdk.internal.jimage.Archive;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.nio.ByteOrder;
-import java.nio.file.Files;
-import java.nio.file.InvalidPathException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import jdk.internal.jimage.ImageFileCreator;
-
-/**
- * A tool for building a runtime image.
- *
- * java build.tools.module.ImageBuilder <options> --output <path> top/modules.xml,...
- *  Possible options are:
- *  --cmds                  Location of native commands
- *  --configs               Location of config files
- *  --help                  Print this usage message
- *  --classes               Location of module classes files
- *  --libs                  Location of native libraries
- *  --mods                  Comma separated list of module names
- *  --output                Location of the output path
- *  --endian                Byte order of the target runtime; {little,big}
- */
-class ImageBuilder {
-    static class BadArgs extends Exception {
-        private static final long serialVersionUID = 0L;
-        BadArgs(String format, Object... args) {
-            super(String.format(format, args));
-            this.format = format;
-            this.args = args;
-        }
-        BadArgs showUsage(boolean b) {
-            showUsage = b;
-            return this;
-        }
-        final String format;
-        final Object[] args;
-        boolean showUsage;
-    }
-
-    static class Option {
-
-        interface Processing {
-
-            void process(ImageBuilder task, String opt, String arg) throws BadArgs;
-        }
-
-        final boolean hasArg;
-        final String[] aliases;
-        final String description;
-        final Processing processing;
-
-        Option(boolean hasArg, String description, Processing processing,
-                String... aliases) {
-            this.hasArg = hasArg;
-            this.description = description;
-            this.processing = processing;
-            this.aliases = aliases;
-        }
-        boolean isHidden() {
-            return false;
-        }
-        boolean matches(String opt) {
-            for (String a : aliases) {
-                if (a.equals(opt)) {
-                    return true;
-                } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        boolean ignoreRest() {
-            return false;
-        }
-        void process(ImageBuilder task, String opt, String arg) throws BadArgs {
-            processing.process(task, opt, arg);
-        }
-        String description() {
-            return description;
-        }
-    }
-
-    private static Path CWD = Paths.get("");
-
-    private static List<Path> splitPath(String arg, String separator)
-        throws BadArgs
-    {
-        List<Path> paths = new ArrayList<>();
-        for (String p: arg.split(separator)) {
-            if (p.length() > 0) {
-                try {
-                    Path path = CWD.resolve(p);
-                    if (Files.notExists(path))
-                        throw new BadArgs("path not found: %s", path);
-                    paths.add(path);
-                } catch (InvalidPathException x) {
-                    throw new BadArgs("path not valid: %s", p);
-                }
-            }
-        }
-        return paths;
-    }
-
-    static Option[] recognizedOptions = {
-        new Option(true, "Location of native commands", (task, opt, arg) -> {
-            task.options.cmds = splitPath(arg, File.pathSeparator);
-        }, "--cmds"),
-        new Option(true, "Location of config files", (task, opt, arg) -> {
-            task.options.configs = splitPath(arg, File.pathSeparator);
-        }, "--configs"),
-        new Option(false, "Print this usage message", (task, opt, arg) -> {
-            task.options.help = true;
-        }, "--help"),
-        new Option(true, "Location of module classes files", (task, opt, arg) -> {
-            task.options.classes = splitPath(arg, File.pathSeparator);
-        }, "--classes"),
-        new Option(true, "Location of native libraries", (task, opt, arg) -> {
-            task.options.libs = splitPath(arg, File.pathSeparator);
-        }, "--libs"),
-        new Option(true, "Comma separated list of module names",
-        (task, opt, arg) -> {
-            for (String mn : arg.split(",")) {
-                if (mn.isEmpty()) {
-                    throw new BadArgs("Module not found", mn);
-                }
-                task.options.mods.add(mn);
-            }
-        }, "--mods"),
-        new Option(true, "Location of the output path", (task, opt, arg) -> {
-            Path path = Paths.get(arg);
-            task.options.output = path;
-        }, "--output"),
-        new Option(true, "Byte order of the target runtime; {little,big}",
-        (task, opt, arg) -> {
-            if (arg.equals("little")) {
-                task.options.endian = ByteOrder.LITTLE_ENDIAN;
-            } else if (arg.equals("big")) {
-                task.options.endian = ByteOrder.BIG_ENDIAN;
-            } else {
-                throw new BadArgs("Unknown byte order " + arg);
-            }
-        }, "--endian")
-    };
-
-    private final Options options = new Options();
-
-    private PrintWriter log;
-    void setLog(PrintWriter out) {
-        log = out;
-    }
-
-    Set<Module> moduleGraph = new java.util.HashSet<>();
-
-    /** Module list files */
-    private static final String BOOT_MODULES = "boot.modules";
-    private static final String EXT_MODULES = "ext.modules";
-
-    /**
-     * Result codes.
-     */
-    static final int EXIT_OK = 0,       // Completed with no errors.
-                     EXIT_ERROR = 1,    // Completed but reported errors.
-                     EXIT_CMDERR = 2,   // Bad command-line arguments
-                     EXIT_SYSERR = 3,   // System error or resource exhaustion.
-                     EXIT_ABNORMAL = 4; // terminated abnormally
-
-
-    static class Options {
-        boolean help;
-        List<Path> classes;
-        List<Path> cmds;
-        List<Path> configs;
-        List<Path> libs;
-        Set<String> mods = new HashSet<>();
-        Path output;
-        ByteOrder endian = ByteOrder.nativeOrder(); // default, if not specified
-    }
-
-    public static void main(String[] args) throws Exception {
-        ImageBuilder builder = new ImageBuilder();
-        int rc = builder.run(args);
-        System.exit(rc);
-    }
-
-    int run(String[] args) {
-        if (log == null)
-            log = new PrintWriter(System.out);
-
-        try {
-            handleOptions(args);
-            if (options.help) {
-                showHelp();
-                return EXIT_OK;
-            }
-
-            if (options.classes == null)
-                throw new BadArgs("--classes must be specified").showUsage(true);
-
-            Path output = options.output;
-            if (output == null)
-                throw new BadArgs("--output must be specified").showUsage(true);
-            Files.createDirectories(output);
-            if (Files.list(output).findFirst().isPresent())
-                throw new BadArgs("dir not empty", output);
-
-            if (options.mods.isEmpty())
-                throw new BadArgs("--mods must be specified").showUsage(true);
-
-            if (moduleGraph.isEmpty())
-                throw new BadArgs("modules.xml must be specified").showUsage(true);
-
-            if (options.cmds == null || options.cmds.isEmpty())
-                warning("--commands is not set");
-            if (options.libs == null || options.libs.isEmpty())
-                warning("--libs is not set");
-            //if (options.configs == null || options.configs.isEmpty())
-            //    warning("--configs is not set");
-
-            // additional option combination validation
-
-            boolean ok = run();
-            return ok ? EXIT_OK : EXIT_ERROR;
-        } catch (BadArgs e) {
-            reportError(e.format, e.args);
-            if (e.showUsage)
-                log.println(USAGE_SUMMARY);
-            return EXIT_CMDERR;
-        } catch (Exception x) {
-            x.printStackTrace();
-            return EXIT_ABNORMAL;
-        } finally {
-            log.flush();
-        }
-    }
-
-    private boolean run() throws IOException {
-        createImage();
-        return true;
-    }
-
-    class SimpleResolver {
-        private final Set<Module> initialMods;
-        private final Map<String,Module> nameToModule = new HashMap<>();
-
-        SimpleResolver(Set<String> mods, Set<Module> graph) {
-            graph.stream()
-                 .forEach(m -> nameToModule.put(m.name(), m));
-            initialMods = mods.stream()
-                         .map(this::nameToModule)
-                         .collect(Collectors.toSet());
-        }
-
-        /** Returns the transitive closure, in topological order */
-        List<String> resolve() {
-            List<Module> result = new LinkedList<>();
-            Set<Module> visited = new HashSet<>();
-            Set<Module> done = new HashSet<>();
-            for (Module m : initialMods) {
-                if (!visited.contains(m))
-                    visit(m, visited, result, done);
-            }
-            return result.stream()
-                         .map(m -> m.name())
-                         .collect(Collectors.toList());
-        }
-
-        private void visit(Module m, Set<Module> visited,
-                           List<Module> result, Set<Module> done) {
-            if (visited.contains(m)) {
-                if (!done.contains(m))
-                    throw new IllegalArgumentException("Cyclic detected: " +
-                            m + " " + getModuleDependences(m));
-                return;
-            }
-            visited.add(m);
-            getModuleDependences(m).stream()
-                                   .forEach(d -> visit(d, visited, result, done));
-            done.add(m);
-            result.add(m);
-        }
-
-        private Module nameToModule(String name) {
-            Module m = nameToModule.get(name);
-            if (m == null)
-                throw new RuntimeException("No module definition for " + name);
-            return m;
-        }
-
-        private Set<Module> getModuleDependences(Module m) {
-            return m.requires().stream()
-                    .map(d -> d.name())
-                    .map(this::nameToModule)
-                    .collect(Collectors.toSet());
-        }
-    }
-
-    private List<String> resolve(Set<String> mods ) {
-        return (new SimpleResolver(mods, moduleGraph)).resolve();
-    }
-
-    private void createImage() throws IOException {
-        Collection<String> modules = resolve(options.mods);
-        log.print(modules.stream().collect(Collectors.joining(" ")));
-        ImageFileHelper imageHelper = new ImageFileHelper(modules);
-        imageHelper.createModularImage(options.output);
-
-        // jspawnhelper, might be in lib or lib/ARCH
-        Path jspawnhelper = Paths.get("jspawnhelper");
-        Path lib = options.output.resolve("lib");
-        Optional<Path> helper = Files.walk(lib, 2)
-                                     .filter(f -> f.getFileName().equals(jspawnhelper))
-                                     .findFirst();
-        if (helper.isPresent())
-            helper.get().toFile().setExecutable(true, false);
-    }
-
-    private class ImageFileHelper {
-        final Collection<String> modules;
-        final Set<String> bootModules;
-        final Set<String> extModules;
-        final Set<String> appModules;
-
-        ImageFileHelper(Collection<String> modules) throws IOException {
-            this.modules = modules;
-            this.bootModules = modulesFor(BOOT_MODULES).stream()
-                    .filter(modules::contains)
-                    .collect(Collectors.toSet());
-            this.extModules = modulesFor(EXT_MODULES).stream()
-                    .filter(modules::contains)
-                    .collect(Collectors.toSet());
-            this.appModules = modules.stream()
-                    .filter(m -> m.length() != 0 &&
-                                 !bootModules.contains(m) &&
-                                 !extModules.contains(m))
-                    .collect(Collectors.toSet());
-        }
-
-        void createModularImage(Path output) throws IOException {
-            Set<Archive> bootArchives = bootModules.stream()
-                    .map(this::toModuleArchive)
-                    .collect(Collectors.toSet());
-            Set<Archive> extArchives = extModules.stream()
-                    .map(this::toModuleArchive)
-                    .collect(Collectors.toSet());
-            Set<Archive> appArchives = appModules.stream()
-                    .map(this::toModuleArchive)
-                    .collect(Collectors.toSet());
-            ImageFileCreator.create(output, "bootmodules", bootArchives, options.endian);
-            ImageFileCreator.create(output, "extmodules", extArchives, options.endian);
-            ImageFileCreator.create(output, "appmodules", appArchives, options.endian);
-        }
-
-        ModuleArchive toModuleArchive(String mn) {
-            return new ModuleArchive(mn,
-                                     moduleToPath(mn, options.classes, false/*true*/),
-                                     moduleToPath(mn, options.cmds, false),
-                                     moduleToPath(mn, options.libs, false),
-                                     moduleToPath(mn, options.configs, false));
-        }
-
-        private Path moduleToPath(String name, List<Path> paths, boolean expect) {
-            Set<Path> foundPaths = new HashSet<>();
-            if (paths != null) {
-                for (Path p : paths) {
-                    Path rp = p.resolve(name);
-                    if (Files.exists(rp))
-                        foundPaths.add(rp);
-                }
-            }
-            if (foundPaths.size() > 1)
-                throw new RuntimeException("Found more that one path for " + name);
-            if (expect && foundPaths.size() != 1)
-                throw new RuntimeException("Expected to find classes path for " + name);
-            return foundPaths.size() == 0 ? null : foundPaths.iterator().next();
-        }
-
-        private List<String> modulesFor(String name) throws IOException {
-            try (InputStream is = ImageBuilder.class.getResourceAsStream(name);
-                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
-                return reader.lines().collect(Collectors.toList());
-            }
-        }
-    }
-
-    public void handleOptions(String[] args) throws BadArgs {
-        // process options
-        for (int i=0; i < args.length; i++) {
-            if (args[i].charAt(0) == '-') {
-                String name = args[i];
-                Option option = getOption(name);
-                String param = null;
-                if (option.hasArg) {
-                    if (name.startsWith("--") && name.indexOf('=') > 0) {
-                        param = name.substring(name.indexOf('=') + 1, name.length());
-                    } else if (i + 1 < args.length) {
-                        param = args[++i];
-                    }
-                    if (param == null || param.isEmpty() || param.charAt(0) == '-') {
-                        throw new BadArgs("Missing arg for %n", name).showUsage(true);
-                    }
-                }
-                option.process(this, name, param);
-                if (option.ignoreRest()) {
-                    i = args.length;
-                }
-            } else {
-                // process rest of the input arguments
-                Path p = Paths.get(args[i]);
-                try {
-                    moduleGraph.addAll(ModulesXmlReader.readModules(p)
-                            .stream()
-                            .collect(Collectors.toSet()));
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }
-    }
-
-    private Option getOption(String name) throws BadArgs {
-        for (Option o : recognizedOptions) {
-            if (o.matches(name)) {
-                return o;
-            }
-        }
-        throw new BadArgs("Unknown option %s", name).showUsage(true);
-    }
-
-    private void reportError(String format, Object... args) {
-        log.format("Error: " + format + "%n", args);
-    }
-
-    private void warning(String format, Object... args) {
-        log.format("Warning: " + format + "%n", args);
-    }
-
-    private static final String USAGE =
-            "ImageBuilder <options> --output <path> path-to-modules-xml\n";
-
-    private static final String USAGE_SUMMARY =
-            USAGE + "Use --help for a list of possible options.";
-
-    private void showHelp() {
-        log.format(USAGE);
-        log.format("Possible options are:%n");
-        for (Option o : recognizedOptions) {
-            String name = o.aliases[0].substring(1); // there must always be at least one name
-            name = name.charAt(0) == '-' ? name.substring(1) : name;
-            if (o.isHidden() || name.equals("h"))
-                continue;
-
-            log.format("  --%s\t\t\t%s%n", name, o.description());
-        }
-    }
-}
diff --git a/jdk/make/src/classes/build/tools/module/Module.java b/jdk/make/src/classes/build/tools/module/Module.java
index 8264f3c..e553d92 100644
--- a/jdk/make/src/classes/build/tools/module/Module.java
+++ b/jdk/make/src/classes/build/tools/module/Module.java
@@ -25,10 +25,17 @@
 
 package build.tools.module;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 public class Module {
-    static class Dependence {
+    public static class Dependence implements Comparable<Dependence> {
         final String name;
         final boolean reexport;
         Dependence(String name) {
@@ -43,6 +50,10 @@
             return name;
         }
 
+        public boolean reexport(){
+            return reexport;
+        }
+
         @Override
         public int hashCode() {
             int hash = 5;
@@ -55,20 +66,35 @@
             Dependence d = (Dependence)o;
             return this.name.equals(d.name) && this.reexport == d.reexport;
         }
+
+        @Override
+        public int compareTo(Dependence o) {
+            int rc = this.name.compareTo(o.name);
+            return rc != 0 ? rc : Boolean.compare(this.reexport, o.reexport);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("requires %s%s;",
+                                 reexport ? "public " : "", name);
+        }
     }
     private final String moduleName;
     private final Set<Dependence> requires;
     private final Map<String, Set<String>> exports;
-    private final Set<String> packages;
+    private final Set<String> uses;
+    private final Map<String, Set<String>> provides;
 
     private Module(String name,
-            Set<Dependence> requires,
-            Map<String, Set<String>> exports,
-            Set<String> packages) {
+                   Set<Dependence> requires,
+                   Map<String, Set<String>> exports,
+                   Set<String> uses,
+                   Map<String, Set<String>> provides) {
         this.moduleName = name;
         this.requires = Collections.unmodifiableSet(requires);
         this.exports = Collections.unmodifiableMap(exports);
-        this.packages = Collections.unmodifiableSet(packages);
+        this.uses  = Collections.unmodifiableSet(uses);
+        this.provides = Collections.unmodifiableMap(provides);
     }
 
     public String name() {
@@ -83,8 +109,12 @@
         return exports;
     }
 
-    public Set<String> packages() {
-        return packages;
+    public Set<String> uses() {
+        return uses;
+    }
+
+    public Map<String, Set<String>> provides() {
+        return provides;
     }
 
     @Override
@@ -95,8 +125,7 @@
         Module that = (Module) ob;
         return (moduleName.equals(that.moduleName)
                 && requires.equals(that.requires)
-                && exports.equals(that.exports)
-                && packages.equals(that.packages));
+                && exports.equals(that.exports));
     }
 
     @Override
@@ -104,43 +133,55 @@
         int hc = moduleName.hashCode();
         hc = hc * 43 + requires.hashCode();
         hc = hc * 43 + exports.hashCode();
-        hc = hc * 43 + packages.hashCode();
         return hc;
     }
 
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("module ").append(moduleName).append(" {").append("\n");
-        requires.stream().sorted().forEach(d ->
-                sb.append(String.format("   requires %s%s%n", d.reexport ? "public " : "", d.name)));
-        exports.entrySet().stream().filter(e -> e.getValue().isEmpty())
+        sb.append(String.format("module %s {%n", moduleName));
+        requires.stream()
+                .sorted()
+                .map(d -> String.format("    requires %s%s;%n", d.reexport ? "public " : "", d.name))
+                .forEach(sb::append);
+        exports.entrySet().stream()
+                .filter(e -> e.getValue().isEmpty())
                 .sorted(Map.Entry.comparingByKey())
-                .forEach(e -> sb.append(String.format("   exports %s%n", e.getKey())));
-        exports.entrySet().stream().filter(e -> !e.getValue().isEmpty())
+                .map(e -> String.format("    exports %s;%n", e.getKey()))
+                .forEach(sb::append);
+        exports.entrySet().stream()
+                .filter(e -> !e.getValue().isEmpty())
                 .sorted(Map.Entry.comparingByKey())
-                .forEach(e -> sb.append(String.format("   exports %s to %s%n", e.getKey(), e.getValue())));
-        packages.stream().sorted().forEach(pn -> sb.append(String.format("   includes %s%n", pn)));
-        sb.append("}");
+                .map(e -> String.format("    exports %s to%n%s;%n", e.getKey(),
+                        e.getValue().stream().sorted()
+                                .map(mn -> String.format("        %s", mn))
+                                .collect(Collectors.joining(",\n"))))
+                .forEach(sb::append);
+        uses.stream().sorted()
+                .map(s -> String.format("    uses %s;%n", s))
+                .forEach(sb::append);
+        provides.entrySet().stream()
+                .sorted(Map.Entry.comparingByKey())
+                .flatMap(e -> e.getValue().stream().sorted()
+                        .map(impl -> String.format("    provides %s with %s;%n", e.getKey(), impl)))
+                .forEach(sb::append);
+        sb.append("}").append("\n");
         return sb.toString();
     }
 
+    /**
+     * Module Builder
+     */
     static class Builder {
         private String name;
-        private final Set<Dependence> requires = new HashSet<>();
-        private final Map<String, Set<String>> exports = new HashMap<>();
-        private final Set<String> packages = new HashSet<>();
+        final Set<Dependence> requires = new HashSet<>();
+        final Map<String, Set<String>> exports = new HashMap<>();
+        final Set<String> uses = new HashSet<>();
+        final Map<String, Set<String>> provides = new HashMap<>();
 
         public Builder() {
         }
 
-        public Builder(Module module) {
-            name = module.name();
-            requires.addAll(module.requires());
-            exports.putAll(module.exports());
-            packages.addAll(module.packages());
-        }
-
         public Builder name(String n) {
             name = n;
             return this;
@@ -151,28 +192,89 @@
             return this;
         }
 
-        public Builder include(String p) {
-            packages.add(p);
-            return this;
+        public Builder export(String p) {
+            Objects.requireNonNull(p);
+            if (exports.containsKey(p)) {
+                throw new RuntimeException(name + " already exports " + p +
+                        " " + exports.get(p));
+            }
+            return exportTo(p, Collections.emptySet());
         }
 
-        public Builder export(String p) {
-            return exportTo(p, Collections.emptySet());
+        public Builder exportTo(String p, String mn) {
+            Objects.requireNonNull(p);
+            Objects.requireNonNull(mn);
+            Set<String> ms = exports.get(p);
+            if (ms != null && ms.isEmpty()) {
+                throw new RuntimeException(name + " already has unqualified exports " + p);
+            }
+            exports.computeIfAbsent(p, _k -> new HashSet<>()).add(mn);
+            return this;
         }
 
         public Builder exportTo(String p, Set<String> ms) {
             Objects.requireNonNull(p);
             Objects.requireNonNull(ms);
             if (exports.containsKey(p)) {
-                throw new RuntimeException(name + " already exports " + p);
+                throw new RuntimeException(name + " already exports " + p +
+                        " " + exports.get(p));
             }
             exports.put(p, new HashSet<>(ms));
             return this;
         }
 
+        public Builder use(String cn) {
+            uses.add(cn);
+            return this;
+        }
+
+        public Builder provide(String s, String impl) {
+            provides.computeIfAbsent(s, _k -> new HashSet<>()).add(impl);
+            return this;
+        }
+
+        public Builder merge(Module m1, Module m2) {
+            if (!m1.name().equals(m2.name())) {
+                throw new IllegalArgumentException(m1.name() + " != " + m2.name());
+            }
+            name = m1.name();
+            // ## reexports
+            requires.addAll(m1.requires());
+            requires.addAll(m2.requires());
+            Stream.concat(m1.exports().keySet().stream(), m2.exports().keySet().stream())
+                    .distinct()
+                    .forEach(pn -> {
+                        Set<String> s1 = m2.exports().get(pn);
+                        Set<String> s2 = m2.exports().get(pn);
+                        if (s1 == null || s2 == null) {
+                            exportTo(pn, s1 != null ? s1 : s2);
+                        } else if (s1.isEmpty() || s2.isEmpty()) {
+                            // unqualified exports
+                            export(pn);
+                        } else {
+                            exportTo(pn, Stream.concat(s1.stream(), s2.stream())
+                                               .collect(Collectors.toSet()));
+                        }
+                    });
+            uses.addAll(m1.uses());
+            uses.addAll(m2.uses());
+            m1.provides().keySet().stream()
+                    .forEach(s -> m1.provides().get(s).stream()
+                            .forEach(impl -> provide(s, impl)));
+            m2.provides().keySet().stream()
+                    .forEach(s -> m2.provides().get(s).stream()
+                            .forEach(impl -> provide(s, impl)));
+            return this;
+        }
+
         public Module build() {
-            Module m = new Module(name, requires, exports, packages);
+            Module m = new Module(name, requires, exports, uses, provides);
             return m;
         }
+
+        @Override
+        public String toString() {
+            return name != null ? name : "Unknown";
+        }
     }
 }
diff --git a/jdk/make/src/classes/build/tools/module/ModuleArchive.java b/jdk/make/src/classes/build/tools/module/ModuleArchive.java
deleted file mode 100644
index c4be7b5..0000000
--- a/jdk/make/src/classes/build/tools/module/ModuleArchive.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.module;
-
-import jdk.internal.jimage.Archive;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import jdk.internal.jimage.Archive.Entry.EntryType;
-
-/**
- * An Archive backed by an exploded representation on disk.
- */
-public class ModuleArchive implements Archive {
-    private final Path classes;
-    private final Path cmds;
-    private final Path libs;
-    private final Path configs;
-    private final String moduleName;
-
-    private final List<InputStream> opened = new ArrayList<>();
-
-    public ModuleArchive(String moduleName, Path classes, Path cmds,
-                         Path libs, Path configs) {
-        this.moduleName = moduleName;
-        this.classes = classes;
-        this.cmds = cmds;
-        this.libs = libs;
-        this.configs = configs;
-    }
-
-    @Override
-    public String moduleName() {
-        return moduleName;
-    }
-
-    @Override
-    public void open() throws IOException {
-        // NOOP
-    }
-
-    @Override
-    public void close() throws IOException {
-        IOException e = null;
-        for (InputStream stream : opened) {
-            try {
-                stream.close();
-            } catch (IOException ex) {
-                if (e == null) {
-                    e = ex;
-                } else {
-                    e.addSuppressed(ex);
-                }
-            }
-        }
-        if (e != null) {
-            throw e;
-        }
-    }
-
-    @Override
-    public Stream<Entry> entries() {
-        List<Entry> entries = new ArrayList<>();
-        try {
-            /*
-             * This code should be revisited to avoid buffering of the entries.
-             * 1) Do we really need sorting classes? This force buffering of entries.
-             *    libs, cmds and configs are not sorted.
-             * 2) I/O streams should be concatenated instead of buffering into
-             *    entries list.
-             * 3) Close I/O streams in a close handler.
-             */
-            if (classes != null) {
-                try (Stream<Path> stream = Files.walk(classes)) {
-                    entries.addAll(stream
-                            .filter(p -> !Files.isDirectory(p)
-                                    && !classes.relativize(p).toString().startsWith("_the.")
-                                    && !classes.relativize(p).toString().endsWith(".bc")
-                                    && !classes.relativize(p).toString().equals("javac_state"))
-                            .sorted()
-                            .map(p -> toEntry(p, classes, EntryType.CLASS_OR_RESOURCE))
-                            .collect(Collectors.toList()));
-                }
-            }
-            if (cmds != null) {
-                try (Stream<Path> stream = Files.walk(cmds)) {
-                    entries.addAll(stream
-                            .filter(p -> !Files.isDirectory(p))
-                            .map(p -> toEntry(p, cmds, EntryType.NATIVE_CMD))
-                            .collect(Collectors.toList()));
-                }
-            }
-            if (libs != null) {
-                try (Stream<Path> stream = Files.walk(libs)) {
-                    entries.addAll(stream
-                            .filter(p -> !Files.isDirectory(p))
-                            .map(p -> toEntry(p, libs, EntryType.NATIVE_LIB))
-                            .collect(Collectors.toList()));
-                }
-            }
-            if (configs != null) {
-                try (Stream<Path> stream = Files.walk(configs)) {
-                entries.addAll(stream
-                        .filter(p -> !Files.isDirectory(p))
-                        .map(p -> toEntry(p, configs, EntryType.CONFIG))
-                        .collect(Collectors.toList()));
-                }
-            }
-        } catch (IOException ioe) {
-            throw new UncheckedIOException(ioe);
-        }
-        return entries.stream();
-    }
-
-    private class FileEntry extends Entry {
-        private final boolean isDirectory;
-        private final long size;
-        private final Path entryPath;
-        FileEntry(Path entryPath, String path, EntryType type,
-                  boolean isDirectory, long size) {
-            super(ModuleArchive.this, path, path, type);
-            this.entryPath = entryPath;
-            this.isDirectory = isDirectory;
-            this.size = size;
-        }
-
-        public boolean isDirectory() {
-            return isDirectory;
-        }
-
-        @Override
-        public long size() {
-            return size;
-        }
-
-        @Override
-        public InputStream stream() throws IOException {
-            InputStream stream = Files.newInputStream(entryPath);
-            opened.add(stream);
-            return stream;
-        }
-    }
-
-    private Entry toEntry(Path entryPath, Path basePath, EntryType section) {
-        try {
-            String path = basePath.relativize(entryPath).toString().replace('\\', '/');
-            return new FileEntry(entryPath, path, section,
-                    false, Files.size(entryPath));
-        } catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-}
-
diff --git a/jdk/make/src/classes/build/tools/module/ModuleInfoReader.java b/jdk/make/src/classes/build/tools/module/ModuleInfoReader.java
new file mode 100644
index 0000000..04ff42b
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/module/ModuleInfoReader.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package build.tools.module;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import build.tools.module.Module.Builder;
+
+/**
+ * Source reader of module-info.java
+ */
+public class ModuleInfoReader {
+    private final Path sourcefile;
+    private final Builder builder;
+    private ModuleInfoReader(Path file) {
+        this.sourcefile = file;
+        this.builder = new Builder();
+    }
+
+    public static Builder builder(Path file) throws IOException {
+        ModuleInfoReader reader = new ModuleInfoReader(file);
+        reader.readFile();
+        return reader.builder;
+    }
+
+    /**
+     * Reads the source file.
+     */
+    void readFile() throws IOException {
+        List<String> lines = Files.readAllLines(sourcefile);
+        boolean done = false;
+        int lineNumber = 0;
+        boolean inBlockComment = false;
+        boolean inRequires = false;
+        boolean reexports = false;
+        boolean inProvides = false;
+        boolean inWith = false;
+        String serviceIntf = null;
+        String providerClass = null;
+        boolean inUses = false;
+        boolean inExports = false;
+        boolean inExportsTo = false;
+        String qualifiedExports = null;
+        Counter counter = new Counter();
+
+        for (String line : lines) {
+            lineNumber++;
+            if (inBlockComment) {
+                int c = line.indexOf("*/");
+                if (c >= 0) {
+                    line = line.substring(c + 2, line.length());
+                    inBlockComment = false;
+                } else {
+                    // skip lines until end of comment block
+                    continue;
+                }
+            }
+            inBlockComment = beginBlockComment(line);
+
+            line = trimComment(line).trim();
+            // ignore empty lines
+            if (line.length() == 0) {
+                continue;
+            }
+            String values;
+            if (inRequires || inExports | inUses | (inWith && providerClass == null)) {
+                values = line;
+            } else {
+                String[] s = line.split("\\s+");
+                String keyword = s[0].trim();
+                int nextIndex = keyword.length();
+                switch (keyword) {
+                    case "module":
+                        if (s.length != 3 || !s[2].trim().equals("{")) {
+                            throw new RuntimeException(sourcefile + ", line " +
+                                    lineNumber + ", is malformed");
+                        }
+                        builder.name(s[1].trim());
+                        continue;  // next line
+                    case "requires":
+                        inRequires = true;
+                        counter.numRequires++;
+                        if (s.length >= 2) {
+                            String ss = s[1].trim();
+                            if (ss.equals("public")) {
+                                nextIndex = line.indexOf(ss) + ss.length();
+                                reexports = true;
+                            }
+                        }
+                        break;
+                    case "exports":
+                        inExports = true;
+                        inExportsTo = false;
+                        counter.numExports++;
+                        qualifiedExports = null;
+                        if (s.length >= 3) {
+                            qualifiedExports = s[1].trim();
+                            nextIndex = line.indexOf(qualifiedExports, nextIndex)
+                                            + qualifiedExports.length();
+                            if (s[2].trim().equals("to")) {
+                                inExportsTo = true;
+                                nextIndex = line.indexOf("to", nextIndex) + "to".length();
+                            } else {
+                                throw new RuntimeException(sourcefile + ", line " +
+                                        lineNumber + ", is malformed: " + s[2]);
+                            }
+                        }
+                        break;
+                    case "to":
+                        if (!inExports || qualifiedExports == null) {
+                            throw new RuntimeException(sourcefile + ", line " +
+                                    lineNumber + ", is malformed");
+                        }
+                        inExportsTo = true;
+                        break;
+                    case "uses":
+                        inUses = true;
+                        counter.numUses++;
+                        break;
+                    case "provides":
+                        inProvides = true;
+                        inWith = false;
+                        counter.numProvides++;
+                        serviceIntf = null;
+                        providerClass = null;
+                        if (s.length >= 2) {
+                            serviceIntf = s[1].trim();
+                            nextIndex = line.indexOf(serviceIntf) + serviceIntf.length();
+                        }
+                        if (s.length >= 3) {
+                            if (s[2].trim().equals("with")) {
+                                inWith = true;
+                                nextIndex = line.indexOf("with") + "with".length();
+                            } else {
+                                throw new RuntimeException(sourcefile + ", line " +
+                                        lineNumber + ", is malformed: " + s[2]);
+                            }
+                        }
+                        break;
+                    case "with":
+                        if (!inProvides || serviceIntf == null) {
+                            throw new RuntimeException(sourcefile + ", line " +
+                                    lineNumber + ", is malformed");
+                        }
+                        inWith = true;
+                        nextIndex = line.indexOf("with") + "with".length();
+                        break;
+                    case "}":
+                        counter.validate(builder);
+                        done = true;
+                        continue;  // next line
+                    default:
+                        throw new RuntimeException(sourcefile + ", \"" +
+                                keyword + "\" on line " +
+                                lineNumber + ", is not recognized");
+                }
+                values = line.substring(nextIndex, line.length()).trim();
+            }
+
+            int len = values.length();
+            if (len == 0) {
+                continue;  // next line
+            }
+            char lastchar = values.charAt(len - 1);
+            if (lastchar != ',' && lastchar != ';') {
+                throw new RuntimeException(sourcefile + ", line " +
+                        lineNumber + ", is malformed:" +
+                        " ',' or ';' is missing.");
+            }
+
+            values = values.substring(0, len - 1).trim();
+            // parse the values specified for a keyword specified
+            for (String s : values.split(",")) {
+                s = s.trim();
+                if (s.length() > 0) {
+                    if (inRequires) {
+                        if (builder.requires.contains(s)) {
+                            throw new RuntimeException(sourcefile + ", line "
+                                    + lineNumber + " duplicated requires: \"" + s + "\"");
+                        }
+                        builder.require(s, reexports);
+                    } else if (inExports) {
+                        if (!inExportsTo && qualifiedExports == null) {
+                            builder.export(s);
+                        } else {
+                            builder.exportTo(qualifiedExports, s);
+                        }
+                    } else if (inUses) {
+                        builder.use(s);
+                    } else if (inProvides) {
+                        if (!inWith) {
+                            serviceIntf = s;
+                        } else {
+                            providerClass = s;
+                            builder.provide(serviceIntf, providerClass);
+                        }
+                    }
+                }
+            }
+            if (lastchar == ';') {
+                inRequires = false;
+                reexports = false;
+                inExports = false;
+                inExportsTo = false;
+                inProvides = false;
+                inWith = false;
+                inUses = false;
+            }
+        }
+
+        if (inBlockComment) {
+            throw new RuntimeException(sourcefile + ", line " +
+                    lineNumber + ", missing \"*/\" to end a block comment");
+        }
+        if (!done) {
+            throw new RuntimeException(sourcefile + ", line " +
+                    lineNumber + ", missing \"}\" to end module definition" +
+                    " for \"" + builder + "\"");
+        }
+        return;
+    }
+
+    // the naming convention for the module names without dashes
+    private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("[\\w\\.\\*_$/]+");
+    private static boolean beginBlockComment(String line) {
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c = line.indexOf("/*", pos);
+            if (c < 0) {
+                return false;
+            }
+
+            if (c > 0 && !Character.isWhitespace(line.charAt(c - 1))) {
+                return false;
+            }
+
+            int c1 = line.indexOf("//", pos);
+            if (c1 >= 0 && c1 < c) {
+                return false;
+            }
+
+            int c2 = line.indexOf("*/", c + 2);
+            if (c2 < 0) {
+                return true;
+            }
+            pos = c + 2;
+        }
+        return false;
+    }
+    private static String trimComment(String line) {
+        StringBuilder sb = new StringBuilder();
+
+        int pos = 0;
+        while (pos >= 0 && pos < line.length()) {
+            int c1 = line.indexOf("//", pos);
+            if (c1 > 0 && !Character.isWhitespace(line.charAt(c1 - 1))) {
+                // not a comment
+                c1 = -1;
+            }
+
+            int c2 = line.indexOf("/*", pos);
+            if (c2 > 0 && !Character.isWhitespace(line.charAt(c2 - 1))) {
+                // not a comment
+                c2 = -1;
+            }
+
+            int c = line.length();
+            int n = line.length();
+            if (c1 >= 0 || c2 >= 0) {
+                if (c1 >= 0) {
+                    c = c1;
+                }
+                if (c2 >= 0 && c2 < c) {
+                    c = c2;
+                }
+                int c3 = line.indexOf("*/", c2 + 2);
+                if (c == c2 && c3 > c2) {
+                    n = c3 + 2;
+                }
+            }
+            if (c > 0) {
+                if (sb.length() > 0) {
+                    // add a whitespace if multiple comments on one line
+                    sb.append(" ");
+                }
+                sb.append(line.substring(pos, c));
+            }
+            pos = n;
+        }
+        return sb.toString();
+    }
+
+
+    static class Counter {
+        int numRequires;
+        int numExports;
+        int numUses;
+        int numProvides;
+
+        void validate(Builder builder) {
+            assertEquals("requires", numRequires, builder.requires.size(),
+                         () -> builder.requires.stream()
+                                      .map(Module.Dependence::toString));
+            assertEquals("exports", numExports, builder.exports.size(),
+                         () -> builder.exports.entrySet().stream()
+                                      .map(e -> "exports " + e.getKey() + " to " + e.getValue()));
+            assertEquals("uses", numUses, builder.uses.size(),
+                         () -> builder.uses.stream());
+            assertEquals("provides", numProvides,
+                         (int)builder.provides.values().stream()
+                                     .flatMap(s -> s.stream())
+                                     .count(),
+                         () -> builder.provides.entrySet().stream()
+                                      .map(e -> "provides " + e.getKey() + " with " + e.getValue()));
+        }
+
+        private static void assertEquals(String msg, int expected, int got,
+                                         Supplier<Stream<String>> supplier) {
+            if (expected != got){
+                System.err.println("ERROR: mismatched " + msg +
+                        " expected: " + expected + " got: " + got );
+                supplier.get().sorted()
+                        .forEach(System.err::println);
+                throw new AssertionError("mismatched " + msg +
+                        " expected: " + expected + " got: " + got + " ");
+            }
+        }
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules
deleted file mode 100644
index 0bf1c55..0000000
--- a/jdk/make/src/classes/build/tools/module/boot.modules
+++ /dev/null
@@ -1,36 +0,0 @@
-java.base
-java.compiler
-java.datatransfer
-java.desktop
-java.httpclient
-java.instrument
-java.logging
-java.management
-java.naming
-java.prefs
-java.rmi
-java.scripting
-java.security.jgss
-java.security.sasl
-java.smartcardio
-java.sql
-java.sql.rowset
-java.xml
-java.xml.crypto
-jdk.charsets
-jdk.deploy
-jdk.httpserver
-jdk.jfr
-jdk.jsobject
-jdk.net
-jdk.vm.cds
-jdk.vm.ci
-jdk.management
-jdk.management.cmm
-jdk.management.jfr
-jdk.management.resource
-jdk.naming.rmi
-jdk.sctp
-jdk.security.auth
-jdk.security.jgss
-jdk.snmp
diff --git a/jdk/make/src/classes/build/tools/module/ext.modules b/jdk/make/src/classes/build/tools/module/ext.modules
deleted file mode 100644
index d266d40..0000000
--- a/jdk/make/src/classes/build/tools/module/ext.modules
+++ /dev/null
@@ -1,17 +0,0 @@
-java.activation
-java.annotations.common
-java.corba
-java.transaction
-java.xml.bind
-java.xml.ws
-jdk.accessibility
-jdk.crypto.ec
-jdk.crypto.mscapi
-jdk.crypto.pkcs11
-jdk.crypto.ucrypto
-jdk.dynalink
-jdk.localedata
-jdk.naming.dns
-jdk.scripting.nashorn
-jdk.xml.dom
-jdk.zipfs
diff --git a/jdk/src/demo/share/java2d/J2DBench/src/j2dbench/ResultSet.java b/jdk/src/demo/share/java2d/J2DBench/src/j2dbench/ResultSet.java
index f84f883..018a9d5 100644
--- a/jdk/src/demo/share/java2d/J2DBench/src/j2dbench/ResultSet.java
+++ b/jdk/src/demo/share/java2d/J2DBench/src/j2dbench/ResultSet.java
@@ -84,7 +84,6 @@
         "java.util.prefs.PreferencesFactory",
         "sun.java2d.fontpath",
         "sun.boot.library.path",
-        "sun.boot.class.path",
     };
 
     /*
diff --git a/jdk/src/java.base/macosx/classes/module-info.java.extra b/jdk/src/java.base/macosx/classes/module-info.java.extra
new file mode 100644
index 0000000..6815c12
--- /dev/null
+++ b/jdk/src/java.base/macosx/classes/module-info.java.extra
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+exports jdk.internal.loader to java.desktop;
+provides java.security.Provider with apple.security.AppleProvider;
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 f29fee3..be16870 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
@@ -6,7 +6,7 @@
 # but may be overridden here, if necessary.
 
 # The makefile for this directory must copy this file
-# into the target class hierarchy so it will get into rt.jar.
+# into the target class hierarchy so it will get into runtime image.
 
 # JCOV attributes
 pack.code.attribute.CoverageTable = NH[PHHII]
@@ -14,6 +14,15 @@
 pack.class.attribute.SourceID = RUH
 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 = RUH
+pack.class.attribute.TargetPlatform = RUHRUHRUH
+pack.class.attribute.Hashes = RUHNH[RUHRUH]
+
+
 # Note:  Zero-length ("marker") attributes do not need to be specified here.
 # They are automatically defined to have an empty layout.
 #pack.class.attribute.Deprecated =
diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
index ee25d91..73741eb 100644
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
@@ -713,9 +713,11 @@
             classObjs[i] = cl;
         }
         try {
-            return Proxy.getProxyClass(
+            @SuppressWarnings("deprecation")
+            Class<?> proxyClass = Proxy.getProxyClass(
                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
                 classObjs);
+            return proxyClass;
         } catch (IllegalArgumentException e) {
             throw new ClassNotFoundException(null, e);
         }
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 af75faf..fa6971d 100644
--- a/jdk/src/java.base/share/classes/java/lang/Class.java
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import java.lang.annotation.Annotation;
+import java.lang.module.ModuleReader;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
@@ -33,15 +35,19 @@
 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.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -55,9 +61,11 @@
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.StringJoiner;
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.BuiltinClassLoader;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
-import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.reflect.CallerSensitive;
 import sun.reflect.ConstantPool;
 import sun.reflect.Reflection;
@@ -69,8 +77,6 @@
 import sun.reflect.generics.repository.ConstructorRepository;
 import sun.reflect.generics.scope.ClassScope;
 import sun.security.util.SecurityConstants;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Proxy;
 import sun.reflect.annotation.*;
 import sun.reflect.misc.ReflectUtil;
 
@@ -378,6 +384,86 @@
                                             Class<?> caller)
         throws ClassNotFoundException;
 
+
+    /**
+     * Returns the {@code Class} with the given <a href="ClassLoader.html#name">
+     * binary name</a> in the given module.
+     *
+     * <p> This method attempts to locate, load, and link the class or interface.
+     * It does not run the class initializer.  If the class is not found, this
+     * method returns {@code null}. </p>
+     *
+     * <p> If the class loader of the given module defines other modules and
+     * the given name is a class defined in a different module, this method
+     * returns {@code null} after the class is loaded. </p>
+     *
+     * <p> This method does not check whether the requested class is
+     * accessible to its caller. </p>
+     *
+     * @apiNote
+     * This method returns {@code null} on failure rather than
+     * throwing a {@link ClassNotFoundException}, as is done by
+     * the {@link #forName(String, boolean, ClassLoader)} method.
+     * The security check is a stack-based permission check if the caller
+     * loads a class in another module.
+     *
+     * @param  module   A module
+     * @param  name     The <a href="ClassLoader.html#name">binary name</a>
+     *                  of the class
+     * @return {@code Class} object of the given name defined in the given module;
+     *         {@code null} if not found.
+     *
+     * @throws NullPointerException if the given module or name is {@code null}
+     *
+     * @throws LinkageError if the linkage fails
+     *
+     * @throws SecurityException
+     *         <ul>
+     *         <li> if the caller is not the specified module and
+     *         {@code RuntimePermission("getClassLoader")} permission is denied; or</li>
+     *         <li> access to the module content is denied. For example,
+     *         permission check will be performed when a class loader calls
+     *         {@link ModuleReader#open(String)} to read the bytes of a class file
+     *         in a module.</li>
+     *         </ul>
+     *
+     * @since 9
+     */
+    @CallerSensitive
+    public static Class<?> forName(Module module, String name) {
+        Objects.requireNonNull(module);
+        Objects.requireNonNull(name);
+
+        Class<?> caller = Reflection.getCallerClass();
+        if (caller != null && caller.getModule() != module) {
+            // if caller is null, Class.forName is the last java frame on the stack.
+            // java.base has all permissions
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+            }
+        }
+
+        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);
+        } else {
+            c = BootLoader.loadClassOrNull(name);
+        }
+
+        if (c != null && c.getModule() == module) {
+            return c;
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Creates a new instance of the class represented by this {@code Class}
      * object.  The class is instantiated as if by a {@code new}
@@ -453,13 +539,11 @@
         }
         Constructor<T> tmpConstructor = cachedConstructor;
         // Security check (same as in java.lang.reflect.Constructor)
-        int modifiers = tmpConstructor.getModifiers();
-        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
-            Class<?> caller = Reflection.getCallerClass();
-            if (newInstanceCallerCache != caller) {
-                Reflection.ensureMemberAccess(caller, this, null, modifiers);
-                newInstanceCallerCache = caller;
-            }
+        Class<?> caller = Reflection.getCallerClass();
+        if (newInstanceCallerCache != caller) {
+            int modifiers = tmpConstructor.getModifiers();
+            Reflection.ensureMemberAccess(caller, this, null, modifiers);
+            newInstanceCallerCache = caller;
         }
         // Run constructor
         try {
@@ -717,6 +801,29 @@
     // Package-private to allow ClassLoader access
     ClassLoader getClassLoader0() { return classLoader; }
 
+    /**
+     * Returns the module that this class or interface is a member of.
+     *
+     * If this class represents an array type then this method returns the
+     * {@code Module} for the element type. If this class represents a
+     * primitive type or void, then the {@code Module} object for the
+     * {@code java.base} module is returned.
+     *
+     * If this class is in an unnamed module then the {@link
+     * ClassLoader#getUnnamedModule() unnamed} {@code Module} of the class
+     * loader for this class is returned.
+     *
+     * @return the module that this class or interface is a member of
+     *
+     * @since 9
+     */
+    public Module getModule() {
+        return module;
+    }
+
+    // set by VM
+    private transient Module module;
+
     // Initialized in JVM not by private constructor
     // This field is filtered from reflection access, i.e. getDeclaredField
     // will throw NoSuchFieldException
@@ -808,24 +915,60 @@
     }
 
     /**
-     * Gets the package for this class.  The class loader of this class is used
-     * to find the package.  If the class was loaded by the bootstrap class
-     * loader the set of packages loaded from CLASSPATH is searched to find the
-     * package of the class. Null is returned if no package object was created
-     * by the class loader of this class.
+     * Gets the package of this class.
      *
-     * <p> Packages have attributes for versions and specifications only if the
-     * information was defined in the manifests that accompany the classes, and
-     * if the class loader created the package instance with the attributes
-     * from the manifest.
+     * <p>If this class represents an array type, a primitive type or void,
+     * this method returns {@code null}.
      *
-     * @return the package of the class, or null if no package
-     *         information is available from the archive or codebase.
+     * @return the package of this class.
      */
     public Package getPackage() {
-        return Package.getPackage(this);
+        if (isPrimitive() || isArray()) {
+            return null;
+        }
+        ClassLoader cl = getClassLoader0();
+        return cl != null ? cl.definePackage(this)
+                          : BootLoader.definePackage(this);
     }
 
+    /**
+     * Returns the fully qualified package name.
+     *
+     * <p> If this class is a top level class, then this method returns the fully
+     * qualified name of the package that the class is a member of, or the
+     * empty string if the class is in an unnamed package.
+     *
+     * <p> If this class is a member class, then this method is equivalent to
+     * invoking {@code getPackageName()} on the {@link #getEnclosingClass
+     * enclosing class}.
+     *
+     * <p> If this class is a {@link #isLocalClass local class} or an {@link
+     * #isAnonymousClass() anonymous class}, then this method is equivalent to
+     * invoking {@code getPackageName()} on the {@link #getDeclaringClass
+     * declaring class} of the {@link #getEnclosingMethod enclosing method} or
+     * {@link #getEnclosingConstructor enclosing constructor}.
+     *
+     * <p> This method returns {@code null} if this class represents an array type,
+     * a primitive type or void.
+     *
+     * @return the fully qualified package name
+     *
+     * @since 9
+     * @jls 6.7  Fully Qualified Names
+     */
+    public String getPackageName() {
+        String pn = this.packageName;
+        if (pn == null && !isArray() && !isPrimitive()) {
+            String cn = getName();
+            int dot = cn.lastIndexOf('.');
+            pn = (dot != -1) ? cn.substring(0, dot).intern() : "";
+            this.packageName = pn;
+        }
+        return pn;
+    }
+
+    // cached package name
+    private String packageName;
 
     /**
      * Returns the interfaces directly implemented by the class or interface
@@ -2213,15 +2356,19 @@
     }
 
     /**
-     * Finds a resource with a given name.  The rules for searching resources
+     * 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
      * delegates to this object's class loader.  If this object was loaded by
      * the bootstrap class loader, the method delegates to {@link
      * ClassLoader#getSystemResourceAsStream}.
      *
-     * <p> Before delegation, an absolute resource name is constructed from the
-     * given resource name using this algorithm:
+     * <p> Before finding a resource in the caller's module or delegation to a
+     * class loader, an absolute resource name is constructed from the given
+     * resource name using this algorithm:
      *
      * <ul>
      *
@@ -2242,26 +2389,60 @@
      * </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 or {@code null} if
+     *          no resource with this name is found
      * @throws  NullPointerException If {@code name} is {@code null}
      * @since  1.1
      */
-     public InputStream getResourceAsStream(String name) {
+    @CallerSensitive
+    public InputStream getResourceAsStream(String name) {
         name = resolveName(name);
-        ClassLoader cl = getClassLoader0();
-        if (cl==null) {
-            // A system class.
-            return ClassLoader.getSystemResourceAsStream(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;
+                    }
+
+                } catch (IOException | SecurityException e) {
+                    return null;
+                }
+            }
         }
-        return cl.getResourceAsStream(name);
+
+        // this Class and caller not in the same named module
+        ClassLoader cl = getClassLoader0();
+        if (cl == null) {
+            return ClassLoader.getSystemResourceAsStream(name);
+        } else {
+            return cl.getResourceAsStream(name);
+        }
     }
 
     /**
-     * Finds a resource with a given name.  The rules for searching resources
+     * 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
-     * delegates to this object's class loader.  If this object was loaded by
+     * delegates to this object's class loader. If this object was loaded by
      * the bootstrap class loader, the method delegates to {@link
      * ClassLoader#getSystemResource}.
      *
@@ -2287,22 +2468,43 @@
      * </ul>
      *
      * @param  name name of the desired resource
-     * @return      A  {@link java.net.URL} object or {@code null} if no
-     *              resource with this name is found
+     * @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.
      * @since  1.1
      */
-    public java.net.URL getResource(String name) {
+    @CallerSensitive
+    public URL getResource(String name) {
         name = resolveName(name);
-        ClassLoader cl = getClassLoader0();
-        if (cl==null) {
-            // A system class.
-            return ClassLoader.getSystemResource(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);
+                    }
+                } catch (IOException ioe) {
+                    return null;
+                }
+            }
         }
-        return cl.getResource(name);
+
+        ClassLoader cl = getClassLoader0();
+        if (cl == null) {
+            return ClassLoader.getSystemResource(name);
+        } else {
+            return cl.getResource(name);
+        }
     }
 
-
-
     /** protection domain returned when the internal domain is null */
     private static java.security.ProtectionDomain allPermDomain;
 
@@ -2845,15 +3047,15 @@
         private void remove(int i) {
             if (methods[i] != null && methods[i].isDefault())
                 defaults--;
-            methods[i] = null;
-        }
+                    methods[i] = null;
+                }
 
         private boolean matchesNameAndDescriptor(Method m1, Method m2) {
             return m1.getReturnType() == m2.getReturnType() &&
                    m1.getName() == m2.getName() && // name is guaranteed to be interned
                    arrayContentsEq(m1.getParameterTypes(),
                            m2.getParameterTypes());
-        }
+            }
 
         void compactAndTrim() {
             int newPos = 0;
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 1bb1580..fa6a652 100644
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.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
@@ -22,38 +22,44 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.lang;
 
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.File;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Module;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.AccessControlContext;
 import java.security.CodeSource;
 import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
 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.Objects;
 import java.util.Set;
 import java.util.Stack;
-import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Vector;
-import java.util.Hashtable;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
 
 import jdk.internal.perf.PerfCounter;
-import sun.misc.Resource;
-import sun.misc.URLClassPath;
+import jdk.internal.module.ServicesCatalog;
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.ClassLoaders;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.misc.VM;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
@@ -90,9 +96,7 @@
  * associated parent class loader.  When requested to find a class or
  * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
  * class or resource to its parent class loader before attempting to find the
- * class or resource itself.  The virtual machine's built-in class loader,
- * called the "bootstrap class loader", does not itself have a parent but may
- * serve as the parent of a <tt>ClassLoader</tt> instance.
+ * class or resource itself.
  *
  * <p> Class loaders that support concurrent loading of classes are known as
  * <em>parallel capable</em> class loaders and are required to register
@@ -101,19 +105,39 @@
  * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
  * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
  * capable by default. However, its subclasses still need to register themselves
- * if they are parallel capable. <br>
+ * if they are parallel capable.
  * In environments in which the delegation model is not strictly
  * hierarchical, class loaders need to be parallel capable, otherwise class
  * loading can lead to deadlocks because the loader lock is held for the
  * duration of the class loading process (see {@link #loadClass
  * <tt>loadClass</tt>} methods).
  *
- * <p> Normally, the Java virtual machine loads classes from the local file
- * system in a platform-dependent manner.  For example, on UNIX systems, the
- * virtual machine loads classes from the directory defined by the
- * <tt>CLASSPATH</tt> environment variable.
+ * <h3> <a name="builtinLoaders">Run-time Built-in Class Loaders</a></h3>
  *
- * <p> However, some classes may not originate from a file; they may originate
+ * The Java run-time has the following built-in class loaders:
+ *
+ * <ul>
+ * <li>Bootstrap class loader.
+ *     It is the virtual machine's built-in class loader, typically represented
+ *     as {@code null}, and does not have a parent.</li>
+ * <li>{@linkplain #getPlatformClassLoader() Platform class loader}.
+ *     All <em>platform classes</em> are visible to the platform class loader
+ *     that can be used as the parent of a {@code ClassLoader} instance.
+ *     Platform classes include Java SE platform APIs, their implementation
+ *     classes and JDK-specific run-time classes that are defined by the
+ *     platform class loader or its ancestors.</li>
+ * <li>{@linkplain #getSystemClassLoader() System class loader}.
+ *     It is also known as <em>application class
+ *     loader</em> and is distinct from the platform class loader.
+ *     The system class loader is typically used to define classes on the
+ *     application class path, module path, and JDK-specific tools.
+ *     The platform class loader is a parent or an ancestor of the system class
+ *     loader that all platform classes are visible to it.</li>
+ * </ul>
+ *
+ * <p> Normally, the Java virtual machine loads classes from the local file
+ * system in a platform-dependent manner.
+ * However, some classes may not originate from a file; they may originate
  * from other sources, such as the network, or they could be constructed by an
  * application.  The method {@link #defineClass(String, byte[], int, int)
  * <tt>defineClass</tt>} converts an array of bytes into an instance of class
@@ -159,8 +183,8 @@
  *
  * <h3> <a name="name">Binary names</a> </h3>
  *
- * <p> Any class name provided as a {@link String} parameter to methods in
- * <tt>ClassLoader</tt> must be a binary name as defined by
+ * <p> Any class name provided as a {@code String} parameter to methods in
+ * {@code ClassLoader} must be a binary name as defined by
  * <cite>The Java&trade; Language Specification</cite>.
  *
  * <p> Examples of valid class names include:
@@ -171,9 +195,12 @@
  *   "java.net.URLClassLoader$3$1"
  * </pre></blockquote>
  *
- * {@code Class} objects for array classes are not created by {@code ClassLoader};
- * use the {@link Class#forName} method instead.
+ * <p> Any package name provided as a {@code String} parameter to methods in
+ * {@code ClassLoader} must be either the empty string (denoting an unnamed package)
+ * or a fully qualified name as defined by
+ * <cite>The Java&trade; Language Specification</cite>.
  *
+ * @jls 6.7  Fully Qualified Names
  * @jls 13.1 The Form of a Binary
  * @see      #resolveClass(Class)
  * @since 1.0
@@ -190,6 +217,9 @@
     // must be added *after* it.
     private final ClassLoader parent;
 
+    // the unnamed module for this ClassLoader
+    private final Module unnamedModule;
+
     /**
      * Encapsulates the set of parallel capable loader types.
      */
@@ -241,7 +271,7 @@
     // is parallel capable and the appropriate lock object for class loading.
     private final ConcurrentHashMap<String, Object> parallelLockMap;
 
-    // Hashtable that maps packages to certs
+    // Maps packages to certs
     private final Map <String, Certificate[]> package2certs;
 
     // Shared among all packages with unsigned classes
@@ -265,11 +295,39 @@
         classes.addElement(c);
     }
 
-    // The packages defined in this class loader.  Each package name is mapped
-    // to its corresponding Package object.
-    private final ConcurrentHashMap<String, Package> packages
+    // The packages defined in this class loader.  Each package name is
+    // mapped to its corresponding NamedPackage object.
+    //
+    // The value is a Package object if ClassLoader::definePackage,
+    // Class::getPackage, ClassLoader::getDefinePackage(s) or
+    // Package::getPackage(s) method is called to define it.
+    // Otherwise, the value is a NamedPackage object.
+    private final ConcurrentHashMap<String, NamedPackage> packages
             = new ConcurrentHashMap<>();
 
+    /*
+     * Returns a named package for the given module.
+     */
+    private NamedPackage getNamedPackage(String pn, Module m) {
+        NamedPackage p = packages.get(pn);
+        if (p == null) {
+            p = new NamedPackage(pn, m);
+
+            NamedPackage value = packages.putIfAbsent(pn, p);
+            if (value != null) {
+                // Package object already be defined for the named package
+                p = value;
+                // if definePackage is called by this class loader to define
+                // a package in a named module, this will return Package
+                // object of the same name.  Package object may contain
+                // unexpected information but it does not impact the runtime.
+                // this assertion may be helpful for troubleshooting
+                assert value.module() == m;
+            }
+        }
+        return p;
+    }
+
     private static Void checkCreateClassLoader() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
@@ -280,6 +338,9 @@
 
     private ClassLoader(Void unused, ClassLoader parent) {
         this.parent = parent;
+        this.unnamedModule
+            = SharedSecrets.getJavaLangReflectModuleAccess()
+                           .defineUnnamedModule(this);
         if (ParallelLoaders.isRegistered(this.getClass())) {
             parallelLockMap = new ConcurrentHashMap<>();
             package2certs = new ConcurrentHashMap<>();
@@ -438,6 +499,74 @@
     }
 
     /**
+     * Loads the class with the specified <a href="#name">binary name</a>
+     * in a module defined to 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.
+     *
+     * @implSpec The default implementation of this method searches for classes
+     * in the following order:
+     *
+     * <ol>
+     *   <li>Invoke {@link #findLoadedClass(String)} to check if the class
+     *   has already been loaded.</li>
+     *   <li>Invoke the {@link #findClass(String, String)} method to find the
+     *   class in the given module.</li>
+     * </ol>
+     *
+     * @param  module
+     *         The module
+     * @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(Module module, String name) {
+        synchronized (getClassLoadingLock(name)) {
+            // First, check if the class has already been loaded
+            Class<?> c = findLoadedClass(name);
+            if (c == null) {
+                c = findClass(module.getName(), name);
+            }
+            if (c != null && c.getModule() == module) {
+                return c;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * 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
@@ -532,6 +661,32 @@
     }
 
     /**
+     * Finds the class with the given <a href="#name">binary name</a>
+     * in a module defined to this class loader.
+     * Class loader implementations that support the loading from modules
+     * should override this method.
+     *
+     * @apiNote This method returns {@code null} rather than throwing
+     *          {@code ClassNotFoundException} if the class could not be found
+     *
+     * @implSpec The default implementation returns {@code null}.
+     *
+     * @param  moduleName
+     *         The module name
+     * @param  name
+     *         The <a href="#name">binary name</a> of the class
+     *
+     * @return The resulting {@code Class} object, or {@code null}
+     *         if the class could not be found.
+     *
+     * @since 9
+     */
+    protected Class<?> findClass(String moduleName, String name) {
+        return null;
+    }
+
+
+    /**
      * Converts an array of bytes into an instance of class <tt>Class</tt>.
      * Before the <tt>Class</tt> can be used it must be resolved.  This method
      * is deprecated in favor of the version that takes a <a
@@ -580,55 +735,63 @@
     }
 
     /**
-     * Converts an array of bytes into an instance of class <tt>Class</tt>.
-     * Before the <tt>Class</tt> can be used it must be resolved.
+     * Converts an array of bytes into an instance of class {@code Class}.
+     * Before the {@code Class} can be used it must be resolved.
      *
      * <p> This method assigns a default {@link java.security.ProtectionDomain
-     * <tt>ProtectionDomain</tt>} to the newly defined class.  The
-     * <tt>ProtectionDomain</tt> is effectively granted the same set of
+     * ProtectionDomain} to the newly defined class.  The
+     * {@code ProtectionDomain} is effectively granted the same set of
      * permissions returned when {@link
      * java.security.Policy#getPermissions(java.security.CodeSource)
-     * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
-     * is invoked.  The default domain is created on the first invocation of
-     * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
+     * Policy.getPolicy().getPermissions(new CodeSource(null, null))}
+     * is invoked.  The default protection domain is created on the first invocation
+     * of {@link #defineClass(String, byte[], int, int) defineClass},
      * and re-used on subsequent invocations.
      *
-     * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
+     * <p> To assign a specific {@code ProtectionDomain} to the class, use
      * the {@link #defineClass(String, byte[], int, int,
-     * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
-     * <tt>ProtectionDomain</tt> as one of its arguments.  </p>
+     * java.security.ProtectionDomain) defineClass} method that takes a
+     * {@code ProtectionDomain} as one of its arguments.  </p>
+     *
+     * <p>
+     * This method defines a package in this class loader corresponding to the
+     * package of the {@code Class} (if such a package has not already been defined
+     * in this class loader). The name of the defined package is derived from
+     * the <a href="#name">binary name</a> of the class specified by
+     * the byte array {@code b}.
+     * Other properties of the defined package are as specified by {@link Package}.
      *
      * @param  name
      *         The expected <a href="#name">binary name</a> of the class, or
-     *         <tt>null</tt> if not known
+     *         {@code null} if not known
      *
      * @param  b
      *         The bytes that make up the class data.  The bytes in positions
-     *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
+     *         {@code off} through {@code off+len-1} should have the format
      *         of a valid class file as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *
      * @param  off
-     *         The start offset in <tt>b</tt> of the class data
+     *         The start offset in {@code b} of the class data
      *
      * @param  len
      *         The length of the class data
      *
-     * @return  The <tt>Class</tt> object that was created from the specified
+     * @return  The {@code Class} object that was created from the specified
      *          class data.
      *
      * @throws  ClassFormatError
      *          If the data did not contain a valid class
      *
      * @throws  IndexOutOfBoundsException
-     *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
-     *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
+     *          If either {@code off} or {@code len} is negative, or if
+     *          {@code off+len} is greater than {@code b.length}.
      *
      * @throws  SecurityException
      *          If an attempt is made to add this class to a package that
      *          contains classes that were signed by a different set of
      *          certificates than this class (which is unsigned), or if
-     *          <tt>name</tt> begins with "<tt>java.</tt>".
+     *          {@code name} begins with "{@code java.}".
      *
      * @see  #loadClass(String, boolean)
      * @see  #resolveClass(Class)
@@ -654,7 +817,8 @@
         if (!checkName(name))
             throw new NoClassDefFoundError("IllegalName: " + name);
 
-        if ((name != null) && name.startsWith("java.")) {
+        if ((name != null) && name.startsWith("java.")
+                && this != getBuiltinPlatformClassLoader()) {
             throw new SecurityException
                 ("Prohibited package name: " +
                  name.substring(0, name.lastIndexOf('.')));
@@ -663,13 +827,14 @@
             pd = defaultDomain;
         }
 
-        if (name != null) checkCerts(name, pd.getCodeSource());
+        if (name != null) {
+            checkCerts(name, pd.getCodeSource());
+        }
 
         return pd;
     }
 
-    private String defineClassSourceLocation(ProtectionDomain pd)
-    {
+    private String defineClassSourceLocation(ProtectionDomain pd) {
         CodeSource cs = pd.getCodeSource();
         String source = null;
         if (cs != null && cs.getLocation() != null) {
@@ -678,8 +843,10 @@
         return source;
     }
 
-    private void postDefineClass(Class<?> c, ProtectionDomain pd)
-    {
+    private void postDefineClass(Class<?> c, ProtectionDomain pd) {
+        // define a named package, if not present
+        getNamedPackage(c.getPackageName(), c.getModule());
+
         if (pd.getCodeSource() != null) {
             Certificate certs[] = pd.getCodeSource().getCertificates();
             if (certs != null)
@@ -688,69 +855,80 @@
     }
 
     /**
-     * Converts an array of bytes into an instance of class <tt>Class</tt>,
-     * with an optional <tt>ProtectionDomain</tt>.  If the domain is
-     * <tt>null</tt>, then a default domain will be assigned to the class as
-     * specified in the documentation for {@link #defineClass(String, byte[],
-     * int, int)}.  Before the class can be used it must be resolved.
+     * Converts an array of bytes into an instance of class {@code Class},
+     * with a given {@code ProtectionDomain}.
+     *
+     * <p> If the given {@code ProtectionDomain} is {@code null},
+     * then a default protection domain will be assigned to the class as specified
+     * in the documentation for {@link #defineClass(String, byte[], int, int)}.
+     * Before the class can be used it must be resolved.
      *
      * <p> The first class defined in a package determines the exact set of
      * certificates that all subsequent classes defined in that package must
      * contain.  The set of certificates for a class is obtained from the
-     * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
-     * <tt>ProtectionDomain</tt> of the class.  Any classes added to that
+     * {@link java.security.CodeSource CodeSource} within the
+     * {@code ProtectionDomain} of the class.  Any classes added to that
      * package must contain the same set of certificates or a
-     * <tt>SecurityException</tt> will be thrown.  Note that if
-     * <tt>name</tt> is <tt>null</tt>, this check is not performed.
+     * {@code SecurityException} will be thrown.  Note that if
+     * {@code name} is {@code null}, this check is not performed.
      * You should always pass in the <a href="#name">binary name</a> of the
      * class you are defining as well as the bytes.  This ensures that the
      * class you are defining is indeed the class you think it is.
      *
-     * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
-     * all classes in the "<tt>java.*</tt> packages can only be defined by the
-     * bootstrap class loader.  If <tt>name</tt> is not <tt>null</tt>, it
-     * must be equal to the <a href="#name">binary name</a> of the class
-     * specified by the byte array "<tt>b</tt>", otherwise a {@link
-     * NoClassDefFoundError <tt>NoClassDefFoundError</tt>} will be thrown. </p>
+     * <p> If the specified {@code name} begins with "{@code java.}", it can
+     * only be defined by the {@linkplain #getPlatformClassLoader()
+     * platform class loader} or its ancestors; otherwise {@code SecurityException}
+     * will be thrown.  If {@code name} is not {@code null}, it must be equal to
+     * the <a href="#name">binary name</a> of the class
+     * specified by the byte array {@code b}, otherwise a {@link
+     * NoClassDefFoundError NoClassDefFoundError} will be thrown.
+     *
+     * <p> This method defines a package in this class loader corresponding to the
+     * package of the {@code Class} (if such a package has not already been defined
+     * in this class loader). The name of the defined package is derived from
+     * the <a href="#name">binary name</a> of the class specified by
+     * the byte array {@code b}.
+     * Other properties of the defined package are as specified by {@link Package}.
      *
      * @param  name
      *         The expected <a href="#name">binary name</a> of the class, or
-     *         <tt>null</tt> if not known
+     *         {@code null} if not known
      *
      * @param  b
      *         The bytes that make up the class data. The bytes in positions
-     *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
+     *         {@code off} through {@code off+len-1} should have the format
      *         of a valid class file as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *
      * @param  off
-     *         The start offset in <tt>b</tt> of the class data
+     *         The start offset in {@code b} of the class data
      *
      * @param  len
      *         The length of the class data
      *
      * @param  protectionDomain
-     *         The ProtectionDomain of the class
+     *         The {@code ProtectionDomain} of the class
      *
-     * @return  The <tt>Class</tt> object created from the data,
-     *          and optional <tt>ProtectionDomain</tt>.
+     * @return  The {@code Class} object created from the data,
+     *          and {@code ProtectionDomain}.
      *
      * @throws  ClassFormatError
      *          If the data did not contain a valid class
      *
      * @throws  NoClassDefFoundError
-     *          If <tt>name</tt> is not equal to the <a href="#name">binary
-     *          name</a> of the class specified by <tt>b</tt>
+     *          If {@code name} is not {@code null} and not equal to the
+     *          <a href="#name">binary name</a> of the class specified by {@code b}
      *
      * @throws  IndexOutOfBoundsException
-     *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
-     *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
+     *          If either {@code off} or {@code len} is negative, or if
+     *          {@code off+len} is greater than {@code b.length}.
      *
      * @throws  SecurityException
      *          If an attempt is made to add this class to a package that
      *          contains classes that were signed by a different set of
-     *          certificates than this class, or if <tt>name</tt> begins with
-     *          "<tt>java.</tt>".
+     *          certificates than this class, or if {@code name} begins with
+     *          "{@code java.}" and this class loader is not the platform
+     *          class loader or its ancestor.
      */
     protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                          ProtectionDomain protectionDomain)
@@ -764,15 +942,16 @@
     }
 
     /**
-     * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
-     * into an instance of class <tt>Class</tt>,
-     * with an optional <tt>ProtectionDomain</tt>.  If the domain is
-     * <tt>null</tt>, then a default domain will be assigned to the class as
+     * Converts a {@link java.nio.ByteBuffer ByteBuffer} into an instance
+     * of class {@code Class}, with the given {@code ProtectionDomain}.
+     * If the given {@code ProtectionDomain} is {@code null}, then a default
+     * protection domain will be assigned to the class as
      * specified in the documentation for {@link #defineClass(String, byte[],
      * int, int)}.  Before the class can be used it must be resolved.
      *
      * <p>The rules about the first class defined in a package determining the
-     * set of certificates for the package, and the restrictions on class names
+     * set of certificates for the package, the restrictions on class names,
+     * and the defined package of the class
      * are identical to those specified in the documentation for {@link
      * #defineClass(String, byte[], int, int, ProtectionDomain)}.
      *
@@ -803,23 +982,23 @@
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *
      * @param  protectionDomain
-     *         The ProtectionDomain of the class, or <tt>null</tt>.
+     *         The {@code ProtectionDomain} of the class, or {@code null}.
      *
-     * @return  The <tt>Class</tt> object created from the data,
-     *          and optional <tt>ProtectionDomain</tt>.
+     * @return  The {@code Class} object created from the data,
+     *          and {@code ProtectionDomain}.
      *
      * @throws  ClassFormatError
      *          If the data did not contain a valid class.
      *
      * @throws  NoClassDefFoundError
-     *          If <tt>name</tt> is not equal to the <a href="#name">binary
-     *          name</a> of the class specified by <tt>b</tt>
+     *          If {@code name} is not {@code null} and not equal to the
+     *          <a href="#name">binary name</a> of the class specified by {@code b}
      *
      * @throws  SecurityException
      *          If an attempt is made to add this class to a package that
      *          contains classes that were signed by a different set of
-     *          certificates than this class, or if <tt>name</tt> begins with
-     *          "<tt>java.</tt>".
+     *          certificates than this class, or if {@code name} begins with
+     *          "{@code java.}".
      *
      * @see      #defineClass(String, byte[], int, int, ProtectionDomain)
      *
@@ -1002,8 +1181,7 @@
      * Returns a class loaded by the bootstrap class loader;
      * or return null if not found.
      */
-    private Class<?> findBootstrapClassOrNull(String name)
-    {
+    Class<?> findBootstrapClassOrNull(String name) {
         if (!checkName(name)) return null;
 
         return findBootstrapClass(name);
@@ -1051,13 +1229,44 @@
     }
 
 
-    // -- Resource --
+    // -- Resources --
+
+    /**
+     * Returns a URL to a resource in a module defined to this class loader.
+     * Class loader implementations that support the loading from modules
+     * should override this method.
+     *
+     * @implSpec The default implementation returns {@code null}.
+     *
+     * @param  moduleName
+     *         The module name
+     * @param  name
+     *         The resource name
+     *
+     * @return A URL to the resource; {@code null} if the resource could not be
+     *         found, a URL could not be constructed to locate the resource,
+     *         access to the resource is denied by the security manager, or
+     *         there isn't a module of the given name defined to the class
+     *         loader.
+     *
+     * @throws IOException
+     *         If I/O errors occur
+     *
+     * @see java.lang.module.ModuleReader#find(String)
+     * @since 9
+     */
+    protected URL findResource(String moduleName, String name) throws IOException {
+        return null;
+    }
 
     /**
      * Finds the resource with the given name.  A resource is some data
      * (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.
      *
@@ -1084,7 +1293,7 @@
         if (parent != null) {
             url = parent.getResource(name);
         } else {
-            url = getBootstrapResource(name);
+            url = BootLoader.findResource(name);
         }
         if (url == null) {
             url = findResource(name);
@@ -1097,6 +1306,9 @@
      * (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
      * identifies the resource.
      *
@@ -1131,7 +1343,7 @@
         if (parent != null) {
             tmp[0] = parent.getResources(name);
         } else {
-            tmp[0] = getBootstrapResources(name);
+            tmp[0] = BootLoader.findResources(name);
         }
         tmp[1] = findResources(name);
 
@@ -1142,6 +1354,9 @@
      * 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.
+     *
      * @param  name
      *         The resource name
      *
@@ -1160,6 +1375,9 @@
      * 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.
+     *
      * @param  name
      *         The resource name
      *
@@ -1204,6 +1422,9 @@
      * 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.
+     *
      * @param  name
      *         The resource name
      *
@@ -1215,7 +1436,7 @@
     public static URL getSystemResource(String name) {
         ClassLoader system = getSystemClassLoader();
         if (system == null) {
-            return getBootstrapResource(name);
+            return BootLoader.findResource(name);
         }
         return system.getResource(name);
     }
@@ -1226,6 +1447,9 @@
      * {@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>
      *
@@ -1245,47 +1469,17 @@
     {
         ClassLoader system = getSystemClassLoader();
         if (system == null) {
-            return getBootstrapResources(name);
+            return BootLoader.findResources(name);
         }
         return system.getResources(name);
     }
 
     /**
-     * Find resources from the VM's built-in classloader.
-     */
-    private static URL getBootstrapResource(String name) {
-        URLClassPath ucp = getBootstrapClassPath();
-        Resource res = ucp.getResource(name);
-        return res != null ? res.getURL() : null;
-    }
-
-    /**
-     * Find resources from the VM's built-in classloader.
-     */
-    private static Enumeration<URL> getBootstrapResources(String name)
-        throws IOException
-    {
-        final Enumeration<Resource> e =
-            getBootstrapClassPath().getResources(name);
-        return new Enumeration<> () {
-            public URL nextElement() {
-                return e.nextElement().getURL();
-            }
-            public boolean hasMoreElements() {
-                return e.hasMoreElements();
-            }
-        };
-    }
-
-    // Returns the URLClassPath that is used for finding system resources.
-    static URLClassPath getBootstrapClassPath() {
-        return sun.misc.Launcher.getBootstrapClassPath();
-    }
-
-
-    /**
      * 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>
      *
@@ -1311,6 +1505,9 @@
      * 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.
+     *
      * @param  name
      *         The resource name
      *
@@ -1371,13 +1568,54 @@
     }
 
     /**
+     * Returns the unnamed {@code Module} for this class loader.
+     *
+     * @return The unnamed Module for this class loader
+     *
+     * @see Module#isNamed()
+     * @since 9
+     */
+    public final Module getUnnamedModule() {
+        return unnamedModule;
+    }
+
+    /**
+     * Returns the platform class loader for delegation.  All
+     * <a href="#builtinLoaders">platform classes</a> are visible to
+     * the platform class loader.
+     *
+     * @return  The platform {@code ClassLoader}.
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and the caller's class loader is
+     *          not {@code null} and the caller's class loader is not the same
+     *          as or an ancestor of the platform class loader,
+     *          and the {@link SecurityManager#checkPermission(java.security.Permission)
+     *          checkPermission} method denies {@code RuntimePermission("getClassLoader")}
+     *          to access the platform class loader.
+     *
+     * @since 9
+     */
+    @CallerSensitive
+    public static ClassLoader getPlatformClassLoader() {
+        SecurityManager sm = System.getSecurityManager();
+        ClassLoader loader = getBuiltinPlatformClassLoader();
+        if (sm != null) {
+            checkClassLoaderPermission(loader, Reflection.getCallerClass());
+        }
+        return loader;
+    }
+
+    /**
      * Returns the system class loader for delegation.  This is the default
      * delegation parent for new <tt>ClassLoader</tt> instances, and is
      * typically the class loader used to start the application.
      *
      * <p> This method is first invoked early in the runtime's startup
-     * sequence, at which point it creates the system class loader and sets it
-     * as the context class loader of the invoking <tt>Thread</tt>.
+     * sequence, at which point it creates the system class loader. This
+     * class loader will be the context class loader for the main application
+     * thread (for example, the thread that invokes the {@code main} method of
+     * the main class).
      *
      * <p> The default system class loader is an implementation-dependent
      * instance of this class.
@@ -1390,7 +1628,10 @@
      * type <tt>ClassLoader</tt> which is used as the delegation parent.  An
      * instance is then created using this constructor with the default system
      * class loader as the parameter.  The resulting class loader is defined
-     * to be the system class loader.
+     * to be the system class loader. During construction, the class loader
+     * should take great care to avoid calling {@code getSystemClassLoader()}.
+     * If circular initialization of the system class loader is detected then
+     * an unspecified error or exception is thrown.
      *
      * <p> If a security manager is present, and the invoker's class loader is
      * not <tt>null</tt> and the invoker's class loader is not the same as or
@@ -1403,6 +1644,11 @@
      * access to the system class loader.  If not, a
      * <tt>SecurityException</tt> will be thrown.  </p>
      *
+     * @implNote The system property to override the system class loader is not
+     * examined until the VM is almost fully initialized. Code that executes
+     * this method during startup should take care not to cache the return
+     * value until the system is fully initialized.
+     *
      * @return  The system <tt>ClassLoader</tt> for delegation, or
      *          <tt>null</tt> if none
      *
@@ -1427,45 +1673,69 @@
      */
     @CallerSensitive
     public static ClassLoader getSystemClassLoader() {
-        initSystemClassLoader();
-        if (scl == null) {
-            return null;
+        switch (VM.initLevel()) {
+            case 0:
+            case 1:
+            case 2:
+                // the system class loader is the built-in app class loader during startup
+                return getBuiltinAppClassLoader();
+            case 3:
+                throw new InternalError("getSystemClassLoader should only be called after VM booted");
+            case 4:
+                // system fully initialized
+                assert VM.isBooted() && scl != null;
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    checkClassLoaderPermission(scl, Reflection.getCallerClass());
+                }
+                return scl;
+            default:
+                throw new InternalError("should not reach here");
         }
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            checkClassLoaderPermission(scl, Reflection.getCallerClass());
-        }
-        return scl;
     }
 
-    private static synchronized void initSystemClassLoader() {
-        if (!sclSet) {
-            if (scl != null)
-                throw new IllegalStateException("recursive invocation");
-            sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
-            if (l != null) {
-                Throwable oops = null;
-                scl = l.getClassLoader();
-                try {
-                    scl = AccessController.doPrivileged(
-                        new SystemClassLoaderAction(scl));
-                } catch (PrivilegedActionException pae) {
-                    oops = pae.getCause();
-                    if (oops instanceof InvocationTargetException) {
-                        oops = oops.getCause();
-                    }
-                }
-                if (oops != null) {
-                    if (oops instanceof Error) {
-                        throw (Error) oops;
-                    } else {
-                        // wrap the exception
-                        throw new Error(oops);
-                    }
-                }
-            }
-            sclSet = true;
+    static ClassLoader getBuiltinPlatformClassLoader() {
+        return ClassLoaders.platformClassLoader();
+    }
+
+    static ClassLoader getBuiltinAppClassLoader() {
+        return ClassLoaders.appClassLoader();
+    }
+
+    /*
+     * Initialize the system class loader that may be a custom class on the
+     * application class path or application module path.
+     *
+     * @see java.lang.System#initPhase3
+     */
+    static synchronized ClassLoader initSystemClassLoader() {
+        if (VM.initLevel() != 3) {
+            throw new InternalError("system class loader cannot be set at initLevel " +
+                                    VM.initLevel());
         }
+
+        // detect recursive initialization
+        if (scl != null) {
+            throw new IllegalStateException("recursive invocation");
+        }
+
+        ClassLoader builtinLoader = getBuiltinAppClassLoader();
+
+        // All are privileged frames.  No need to call doPrivileged.
+        String cn = System.getProperty("java.system.class.loader");
+        if (cn != null) {
+            try {
+                // custom class loader is only supported to be loaded from unnamed module
+                Constructor<?> ctor = Class.forName(cn, false, builtinLoader)
+                                           .getDeclaredConstructor(ClassLoader.class);
+                scl = (ClassLoader) ctor.newInstance(builtinLoader);
+            } catch (Exception e) {
+                throw new Error(e);
+            }
+        } else {
+            scl = builtinLoader;
+        }
+        return scl;
     }
 
     // Returns true if the specified class loader can be found in this class
@@ -1524,26 +1794,102 @@
         }
     }
 
-    // The class loader for the system
+    // The system class loader
     // @GuardedBy("ClassLoader.class")
-    private static ClassLoader scl;
-
-    // Set to true once the system class loader has been set
-    // @GuardedBy("ClassLoader.class")
-    private static boolean sclSet;
-
+    private static volatile ClassLoader scl;
 
     // -- Package --
 
     /**
-     * Defines a package by name in this <tt>ClassLoader</tt>.  This allows
-     * class loaders to define the packages for their classes. Packages must
-     * be created before the class is defined, and package names must be
-     * unique within a class loader and cannot be redefined or changed once
-     * created.
+     * Define a Package of the given Class object.
+     *
+     * If the given class represents an array type, a primitive type or void,
+     * this method returns {@code null}.
+     *
+     * This method does not throw IllegalArgumentException.
+     */
+    Package definePackage(Class<?> c) {
+        if (c.isPrimitive() || c.isArray()) {
+            return null;
+        }
+
+        return definePackage(c.getPackageName(), c.getModule());
+    }
+
+    /**
+     * Defines a Package of the given name and module
+     *
+     * This method does not throw IllegalArgumentException.
+     *
+     * @param name package name
+     * @param m    module
+     */
+    Package definePackage(String name, Module m) {
+        if (name.isEmpty() && m.isNamed()) {
+            throw new InternalError("unnamed package in  " + m);
+        }
+
+        // check if Package object is already defined
+        NamedPackage pkg = packages.get(name);
+        if (pkg instanceof Package)
+            return (Package)pkg;
+
+        return (Package)packages.compute(name, (n, p) -> toPackage(n, p, m));
+    }
+
+    /*
+     * Returns a Package object for the named package
+     */
+    private Package toPackage(String name, NamedPackage p, Module m) {
+        // define Package object if the named package is not yet defined
+        if (p == null)
+            return NamedPackage.toPackage(name, m);
+
+        // otherwise, replace the NamedPackage object with Package object
+        if (p instanceof Package)
+            return (Package)p;
+
+        return NamedPackage.toPackage(p.packageName(), p.module());
+    }
+
+    /**
+     * Defines a package by <a href="#name">name</a> in this {@code ClassLoader}.
+     * <p>
+     * <a href="#name">Package names</a> must be unique within a class loader and
+     * cannot be redefined or changed once created.
+     * <p>
+     * If a class loader wishes to define a package with specific properties,
+     * such as version information, then the class loader should call this
+     * {@code definePackage} method before calling {@code defineClass}.
+     * Otherwise, the
+     * {@link #defineClass(String, byte[], int, int, ProtectionDomain) defineClass}
+     * method will define a package in this class loader corresponding to the package
+     * of the newly defined class; the properties of this defined package are
+     * specified by {@link Package}.
+     *
+     * @apiNote
+     * A class loader that wishes to define a package for classes in a JAR
+     * typically uses the specification and implementation titles, versions, and
+     * vendors from the JAR's manifest. If the package is specified as
+     * {@linkplain java.util.jar.Attributes.Name#SEALED sealed} in the JAR's manifest,
+     * the {@code URL} of the JAR file is typically used as the {@code sealBase}.
+     * If classes of package {@code 'p'} defined by this class loader
+     * are loaded from multiple JARs, the {@code Package} object may contain
+     * different information depending on the first class of package {@code 'p'}
+     * defined and which JAR's manifest is read first to explicitly define
+     * package {@code 'p'}.
+     *
+     * <p> It is strongly recommended that a class loader does not call this
+     * method to explicitly define packages in <em>named modules</em>; instead,
+     * the package will be automatically defined when a class is {@linkplain
+     * #defineClass(String, byte[], int, int, ProtectionDomain) being defined}.
+     * If it is desirable to define {@code Package} explicitly, it should ensure
+     * that all packages in a named module are defined with the properties
+     * specified by {@link Package}.  Otherwise, some {@code Package} objects
+     * in a named module may be for example sealed with different seal base.
      *
      * @param  name
-     *         The package name
+     *         The <a href="#name">package name</a>
      *
      * @param  specTitle
      *         The specification title
@@ -1564,89 +1910,155 @@
      *         The implementation vendor
      *
      * @param  sealBase
-     *         If not <tt>null</tt>, then this package is sealed with
-     *         respect to the given code source {@link java.net.URL
-     *         <tt>URL</tt>}  object.  Otherwise, the package is not sealed.
+     *         If not {@code null}, then this package is sealed with
+     *         respect to the given code source {@link java.net.URL URL}
+     *         object.  Otherwise, the package is not sealed.
      *
-     * @return  The newly defined <tt>Package</tt> object
+     * @return  The newly defined {@code Package} object
+     *
+     * @throws  NullPointerException
+     *          if {@code name} is {@code null}.
      *
      * @throws  IllegalArgumentException
-     *          If package name duplicates an existing package either in this
-     *          class loader or one of its ancestors
+     *          if a package of the given {@code name} is already
+     *          defined by this class loader
      *
      * @since  1.2
+     *
+     * @see <a href="../../../technotes/guides/jar/jar.html#versioning">
+     *      The JAR File Specification: Package Versioning</a>
+     * @see <a href="../../../technotes/guides/jar/jar.html#sealing">
+     *      The JAR File Specification: Package Sealing</a>
      */
     protected Package definePackage(String name, String specTitle,
                                     String specVersion, String specVendor,
                                     String implTitle, String implVersion,
                                     String implVendor, URL sealBase)
-        throws IllegalArgumentException
     {
-        Package pkg = getPackage(name);
-        if (pkg != null) {
+        Objects.requireNonNull(name);
+
+        // definePackage is not final and may be overridden by custom class loader
+        Package p = new Package(name, specTitle, specVersion, specVendor,
+                                implTitle, implVersion, implVendor,
+                                sealBase, this);
+
+        if (packages.putIfAbsent(name, p) != null)
             throw new IllegalArgumentException(name);
-        }
-        pkg = new Package(name, specTitle, specVersion, specVendor,
-                          implTitle, implVersion, implVendor,
-                          sealBase, this);
-        if (packages.putIfAbsent(name, pkg) != null) {
-            throw new IllegalArgumentException(name);
-        }
-        return pkg;
+
+        return p;
     }
 
     /**
-     * Returns a <tt>Package</tt> that has been defined by this class loader
-     * or any of its ancestors.
+     * Returns a {@code Package} of the given <a href="#name">name</a> that has been
+     * defined by this class loader.
+     *
+     * @param  name The <a href="#name">package name</a>
+     *
+     * @return The {@code Package} of the given name defined by this class loader,
+     *         or {@code null} if not found
+     *
+     * @since  9
+     */
+    public final Package getDefinedPackage(String name) {
+        NamedPackage p = packages.get(name);
+        if (p == null)
+            return null;
+
+        return definePackage(name, p.module());
+    }
+
+    /**
+     * Returns all of the {@code Package}s defined by this class loader.
+     * The returned array has no duplicated {@code Package}s of the same name.
+     *
+     * @apiNote This method returns an array rather than a {@code Set} or {@code Stream}
+     *          for consistency with the existing {@link #getPackages} method.
+     *
+     * @return The array of {@code Package} objects defined by this class loader;
+     *         or an zero length array if no package has been defined by this class loader.
+     *
+     * @since  9
+     */
+    public final Package[] getDefinedPackages() {
+        return packages().toArray(Package[]::new);
+    }
+
+    /**
+     * Finds a package by <a href="#name">name</a> in this class loader and its ancestors.
+     * <p>
+     * If this class loader defines a {@code Package} of the given name,
+     * the {@code Package} is returned. Otherwise, the ancestors of
+     * this class loader are searched recursively (parent by parent)
+     * for a {@code Package} of the given name.
      *
      * @param  name
-     *         The package name
+     *         The <a href="#name">package name</a>
      *
-     * @return  The <tt>Package</tt> corresponding to the given name, or
-     *          <tt>null</tt> if not found
+     * @return The {@code Package} corresponding to the given name defined by
+     *         this class loader or its ancestors, or {@code null} if not found.
+     *
+     * @deprecated
+     * If multiple class loaders delegate to each other and define classes
+     * with the same package name, and one such loader relies on the lookup
+     * behavior of {@code getPackage} to return a {@code Package} from
+     * a parent loader, then the properties exposed by the {@code Package}
+     * may not be as expected in the rest of the program.
+     * For example, the {@code Package} will only expose annotations from the
+     * {@code package-info.class} file defined by the parent loader, even if
+     * annotations exist in a {@code package-info.class} file defined by
+     * a child loader.  A more robust approach is to use the
+     * {@link ClassLoader#getDefinedPackage} method which returns
+     * a {@code Package} for the specified class loader.
      *
      * @since  1.2
      */
+    @Deprecated
     protected Package getPackage(String name) {
-        Package pkg = packages.get(name);
+        Package pkg = getDefinedPackage(name);
         if (pkg == null) {
             if (parent != null) {
                 pkg = parent.getPackage(name);
             } else {
-                pkg = Package.getSystemPackage(name);
+                pkg = BootLoader.getDefinedPackage(name);
             }
         }
         return pkg;
     }
 
     /**
-     * Returns all of the <tt>Packages</tt> defined by this class loader and
-     * its ancestors.
+     * Returns all of the {@code Package}s defined by this class loader
+     * and its ancestors.  The returned array may contain more than one
+     * {@code Package} object of the same package name, each defined by
+     * a different class loader in the class loader hierarchy.
      *
-     * @return  The array of <tt>Package</tt> objects defined by this
-     *          <tt>ClassLoader</tt>
+     * @return  The array of {@code Package} objects defined by this
+     *          class loader and its ancestors
      *
      * @since  1.2
      */
     protected Package[] getPackages() {
-        Package[] pkgs;
-        if (parent != null) {
-            pkgs = parent.getPackages();
-        } else {
-            pkgs = Package.getSystemPackages();
+        Stream<Package> pkgs = packages();
+        ClassLoader ld = parent;
+        while (ld != null) {
+            pkgs = Stream.concat(ld.packages(), pkgs);
+            ld = ld.parent;
         }
-
-        Map<String, Package> map = packages;
-        if (pkgs != null) {
-            map = new HashMap<>(packages);
-            for (Package pkg : pkgs) {
-                map.putIfAbsent(pkg.getName(), pkg);
-            }
-        }
-        return map.values().toArray(new Package[map.size()]);
+        return Stream.concat(BootLoader.packages(), pkgs)
+                     .toArray(Package[]::new);
     }
 
 
+
+    // package-private
+
+    /**
+     * Returns a stream of Packages defined in this class loader
+     */
+    Stream<Package> packages() {
+        return packages.values().stream()
+                       .map(p -> definePackage(p.packageName(), p.module()));
+    }
+
     // -- Native library access --
 
     /**
@@ -2183,29 +2595,53 @@
 
     // Retrieves the assertion directives from the VM.
     private static native AssertionStatusDirectives retrieveDirectives();
-}
 
 
-class SystemClassLoaderAction
-    implements PrivilegedExceptionAction<ClassLoader> {
-    private ClassLoader parent;
-
-    SystemClassLoaderAction(ClassLoader parent) {
-        this.parent = parent;
+    /**
+     * 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;
     }
 
-    public ClassLoader run() throws Exception {
-        String cls = System.getProperty("java.system.class.loader");
-        if (cls == null) {
-            return parent;
+    /**
+     * 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 = new ServicesCatalog();
+            boolean set = trySetObjectField("servicesCatalog", catalog);
+            if (!set) {
+                // beaten by someone else
+                catalog = servicesCatalog;
+            }
         }
+        return catalog;
+    }
 
-        Constructor<?> ctor = Class.forName(cls, true, parent)
-            .getDeclaredConstructor(new Class<?>[] { ClassLoader.class });
-        ClassLoader sys = (ClassLoader) ctor.newInstance(
-            new Object[] { parent });
-        Thread.currentThread().setContextClassLoader(sys);
-        return sys;
+    // the ServiceCatalog for modules associated with this class loader.
+    private volatile ServicesCatalog servicesCatalog;
+
+
+    /**
+     * Attempts to atomically set a volatile field in this object. Returns
+     * {@code true} if not beaten by another thread. Avoids the use of
+     * AtomicReferenceFieldUpdater in this class.
+     */
+    private boolean trySetObjectField(String name, Object obj) {
+        Unsafe unsafe = Unsafe.getUnsafe();
+        Class<?> k = ClassLoader.class;
+        long offset;
+        try {
+            Field f = k.getDeclaredField(name);
+            offset = unsafe.objectFieldOffset(f);
+        } catch (NoSuchFieldException e) {
+            throw new InternalError(e);
+        }
+        return unsafe.compareAndSwapObject(this, offset, null, obj);
     }
 }
 
diff --git a/jdk/src/java.base/share/classes/java/lang/NamedPackage.java b/jdk/src/java.base/share/classes/java/lang/NamedPackage.java
new file mode 100644
index 0000000..5d86cc7
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/NamedPackage.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Module;
+import java.net.URI;
+
+/**
+ * A NamedPackage represents a package by name in a specific module.
+ *
+ * A class loader will automatically create NamedPackage for each
+ * package when a class is defined.  Package object is lazily
+ * defined until Class::getPackage, Package::getPackage(s), or
+ * ClassLoader::getDefinedPackage(s) method is called.
+ *
+ * NamedPackage allows ClassLoader to keep track of the runtime
+ * packages with minimal footprint and avoid constructing Package
+ * object.
+ */
+class NamedPackage {
+    private final String name;
+    private final Module module;
+
+    NamedPackage(String pn, Module module) {
+        if (pn.isEmpty() && module.isNamed()) {
+            throw new InternalError("unnamed package in  " + module);
+        }
+        this.name = pn.intern();
+        this.module = module;
+    }
+
+    /**
+     * Returns the name of this package.
+     */
+    String packageName() {
+        return name;
+    }
+
+    /**
+     * Returns the module of this named package.
+     */
+    Module module() {
+        return module;
+    }
+
+    /**
+     * Returns the location of the module if this named package is in
+     * a named module; otherwise, returns null.
+     */
+    URI location() {
+        if (module.isNamed() && module.getLayer() != null) {
+            Configuration cf = module.getLayer().configuration();
+            ModuleReference mref
+                = cf.findModule(module.getName()).get().reference();
+            return mref.location().orElse(null);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a Package object of the given name and module.
+     */
+    static Package toPackage(String name, Module module) {
+        return new Package(name, module);
+    }
+}
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 2ab9fe3..5b80278 100644
--- a/jdk/src/java.base/share/classes/java/lang/Package.java
+++ b/jdk/src/java.base/share/classes/java/lang/Package.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,85 +25,94 @@
 
 package java.lang;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URL;
+import java.lang.reflect.Module;
 import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Objects;
 
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.util.Map;
-
-import sun.net.www.ParseUtil;
+import jdk.internal.loader.BootLoader;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 
-import java.lang.annotation.Annotation;
 
 /**
- * {@code Package} objects contain version information
- * about the implementation and specification of a Java package.
- * This versioning information is retrieved and made available
- * by the {@link ClassLoader} instance that
- * loaded the class(es).  Typically, it is stored in the manifest that is
- * distributed with the classes.
+ * Represents metadata about a run-time package associated with a class loader.
+ * Metadata includes annotations, versioning, and sealing.
+ * <p>
+ * Annotations for the run-time package are read from {@code package-info.class}
+ * at the same code source as classes in the run-time package.
+ * <p>
+ * The set of classes that make up the run-time package may implement a
+ * particular specification. The specification title, version, and vendor
+ * (indicating the owner/maintainer of the specification) can be provided
+ * when the {@code Package} is defined. An application can ask if the
+ * {@code Package} is compatible with a particular specification version
+ * by using the {@link #isCompatibleWith Package.isCompatibleWith(String)}
+ * method. In addition, information about the actual classes that make up the
+ * run-time package can be provided when the Package is defined.
+ * This information consists of an implementation title, version, and vendor
+ * (indicating the supplier of the classes).
+ * <p>
+ * A {@code Package} may be explicitly defined with
+ * the {@link ClassLoader#definePackage(String, String, String, String,
+ * String, String, String, URL)} method.
+ * The caller supplies the specification and implementation titles, versions, and
+ * vendors. The caller also indicates whether the package is
+ * {@linkplain java.util.jar.Attributes.Name#SEALED sealed}.
+ * If a {@code Package} is not explicitly defined for a run-time package when
+ * a class in that run-time package is defined, then a {@code Package} is
+ * automatically defined by the class's defining class loader, as follows.
+ * <p>
+ * A {@code Package} automatically defined for classes in a named module has
+ * the following properties:
+ * <ul>
+ * <li>The name of the package is derived from the {@linkplain Class#getName() binary names}
+ *     of the classes. Since classes in a named module must be in a named package,
+ *     the derived name is never empty.</li>
+ * <li>The package is sealed with the {@linkplain java.lang.module.ModuleReference#location()
+ *     module location} as the code source, if known.</li>
+ * <li>The specification and implementation titles, versions, and vendors
+ *     are unspecified.</li>
+ * <li>Any annotations on the package are read from {@code package-info.class}
+ *     as specified above.</li>
+ * </ul>
+ * <p>
+ * A {@code Package} automatically defined for classes in an unnamed module
+ * has the following properties:
+ * <ul>
+ * <li>The name of the package is either {@code ""} (for classes in an unnamed package)
+ *     or derived from the {@linkplain Class#getName() binary names} of the classes
+ *     (for classes in a named package).</li>
+ * <li>The package is not sealed.</li>
+ * <li>The specification and implementation titles, versions, and vendors
+ *     are unspecified.</li>
+ * <li>Any annotations on the package are read from {@code package-info.class}
+ *     as specified above.</li>
+ * </ul>
  *
- * <p>The set of classes that make up the package may implement a
- * particular specification and if so the specification title, version number,
- * and vendor strings identify that specification.
- * An application can ask if the package is
- * compatible with a particular version, see the {@link
- * #isCompatibleWith isCompatibleWith}
- * method for details.
+ * <p>
+ * A {@code Package} can be obtained with the {@link Package#getPackage
+ * Package.getPackage(String)} and {@link ClassLoader#getDefinedPackage
+ * ClassLoader.getDefinedPackage(String)} methods.
+ * Every {@code Package} defined by a class loader can be obtained
+ * with the {@link Package#getPackages Package.getPackages()} and
+ * {@link ClassLoader#getDefinedPackages} methods.
  *
- * <p>Specification version numbers use a syntax that consists of nonnegative
- * decimal integers separated by periods ".", for example "2.0" or
- * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
- * major, minor, micro, etc. versions.  The version specification is described
- * by the following formal grammar:
- * <blockquote>
- * <dl>
- * <dt><i>SpecificationVersion:</i>
- * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
-
- * <dt><i>RefinedVersion:</i>
- * <dd>{@code .} <i>Digits</i>
- * <dd>{@code .} <i>Digits RefinedVersion</i>
+ * @jvms 5.3 Run-time package
+ * @see <a href="../../../technotes/guides/jar/jar.html#versioning">
+ * The JAR File Specification: Package Versioning</a>
+ * @see <a href="../../../technotes/guides/jar/jar.html#sealing">
+ * The JAR File Specification: Package Sealing</a>
+ * @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)
  *
- * <dt><i>Digits:</i>
- * <dd><i>Digit</i>
- * <dd><i>Digits</i>
- *
- * <dt><i>Digit:</i>
- * <dd>any character for which {@link Character#isDigit} returns {@code true},
- * e.g. 0, 1, 2, ...
- * </dl>
- * </blockquote>
- *
- * <p>The implementation title, version, and vendor strings identify an
- * implementation and are made available conveniently to enable accurate
- * reporting of the packages involved when a problem occurs. The contents
- * all three implementation strings are vendor specific. The
- * implementation version strings have no specified syntax and should
- * only be compared for equality with desired version identifiers.
- *
- * <p>Within each {@code ClassLoader} instance all classes from the same
- * java package have the same Package object.  The static methods allow a package
- * to be found by name or the set of all packages known to the current class
- * loader to be found.
- *
- * @see ClassLoader#definePackage
  * @since 1.2
  */
-public class Package implements java.lang.reflect.AnnotatedElement {
+public class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
     /**
      * Return the name of this package.
      *
@@ -112,47 +121,72 @@
      *          for example, {@code java.lang}
      */
     public String getName() {
-        return pkgName;
+        return packageName();
     }
 
-
     /**
      * Return the title of the specification that this package implements.
-     * @return the specification title, null is returned if it is not known.
+     * @return the specification title, {@code null} is returned if it is not known.
      */
     public String getSpecificationTitle() {
-        return specTitle;
+        return versionInfo.specTitle;
     }
 
     /**
      * Returns the version number of the specification
      * that this package implements.
-     * This version string must be a sequence of nonnegative decimal
+     * This version string must be a sequence of non-negative decimal
      * integers separated by "."'s and may have leading zeros.
      * When version strings are compared the most significant
      * numbers are compared.
-     * @return the specification version, null is returned if it is not known.
+     *
+     *
+     * <p>Specification version numbers use a syntax that consists of non-negative
+     * decimal integers separated by periods ".", for example "2.0" or
+     * "1.2.3.4.5.6.7".  This allows an extensible number to be used to represent
+     * major, minor, micro, etc. versions.  The version specification is described
+     * by the following formal grammar:
+     * <blockquote>
+     * <dl>
+     * <dt><i>SpecificationVersion:</i>
+     * <dd><i>Digits RefinedVersion<sub>opt</sub></i>
+
+     * <dt><i>RefinedVersion:</i>
+     * <dd>{@code .} <i>Digits</i>
+     * <dd>{@code .} <i>Digits RefinedVersion</i>
+     *
+     * <dt><i>Digits:</i>
+     * <dd><i>Digit</i>
+     * <dd><i>Digits</i>
+     *
+     * <dt><i>Digit:</i>
+     * <dd>any character for which {@link Character#isDigit} returns {@code true},
+     * e.g. 0, 1, 2, ...
+     * </dl>
+     * </blockquote>
+     *
+     * @return the specification version, {@code null} is returned if it is not known.
      */
     public String getSpecificationVersion() {
-        return specVersion;
+        return versionInfo.specVersion;
     }
 
     /**
      * Return the name of the organization, vendor,
      * or company that owns and maintains the specification
      * of the classes that implement this package.
-     * @return the specification vendor, null is returned if it is not known.
+     * @return the specification vendor, {@code null} is returned if it is not known.
      */
     public String getSpecificationVendor() {
-        return specVendor;
+        return versionInfo.specVendor;
     }
 
     /**
      * Return the title of this package.
-     * @return the title of the implementation, null is returned if it is not known.
+     * @return the title of the implementation, {@code null} is returned if it is not known.
      */
     public String getImplementationTitle() {
-        return implTitle;
+        return versionInfo.implTitle;
     }
 
     /**
@@ -162,19 +196,20 @@
      * runtime. It may be compared for equality with other
      * package version strings used for this implementation
      * by this vendor for this package.
-     * @return the version of the implementation, null is returned if it is not known.
+     * @return the version of the implementation, {@code null} is returned if it is not known.
      */
     public String getImplementationVersion() {
-        return implVersion;
+        return versionInfo.implVersion;
     }
 
     /**
-     * Returns the name of the organization,
-     * vendor or company that provided this implementation.
-     * @return the vendor that implemented this package..
+     * Returns the vendor that implemented this package, {@code null}
+     * is returned if it is not known.
+     * @return the vendor that implemented this package, {@code null}
+     * is returned if it is not known.
      */
     public String getImplementationVendor() {
-        return implVendor;
+        return versionInfo.implVendor;
     }
 
     /**
@@ -183,17 +218,29 @@
      * @return true if the package is sealed, false otherwise
      */
     public boolean isSealed() {
-        return sealBase != null;
+        return module().isNamed() || versionInfo.sealBase != null;
     }
 
     /**
      * Returns true if this package is sealed with respect to the specified
-     * code source url.
+     * code source {@code url}.
      *
-     * @param url the code source url
-     * @return true if this package is sealed with respect to url
+     * @param url the code source URL
+     * @return true if this package is sealed with respect to the given {@code url}
      */
     public boolean isSealed(URL url) {
+        Objects.requireNonNull(url);
+
+        URL sealBase = null;
+        if (versionInfo != VersionInfo.NULL_VERSION_INFO) {
+            sealBase = versionInfo.sealBase;
+        } else {
+            try {
+                URI uri = location();
+                sealBase = uri != null ? uri.toURL() : null;
+            } catch (MalformedURLException e) {
+            }
+        }
         return url.equals(sealBase);
     }
 
@@ -216,17 +263,17 @@
      * @return true if this package's version number is greater
      *          than or equal to the desired version number
      *
-     * @exception NumberFormatException if the desired or current version
-     *          is not of the correct dotted form.
+     * @exception NumberFormatException if the current version is not known or
+     *          the desired or current version is not of the correct dotted form.
      */
     public boolean isCompatibleWith(String desired)
         throws NumberFormatException
     {
-        if (specVersion == null || specVersion.length() < 1) {
+        if (versionInfo.specVersion == null || versionInfo.specVersion.length() < 1) {
             throw new NumberFormatException("Empty version string");
         }
 
-        String [] sa = specVersion.split("\\.", -1);
+        String [] sa = versionInfo.specVersion.split("\\.", -1);
         int [] si = new int[sa.length];
         for (int i = 0; i < sa.length; i++) {
             si[i] = Integer.parseInt(sa[i]);
@@ -255,92 +302,71 @@
     }
 
     /**
-     * Find a package by name in the callers {@code ClassLoader} instance.
-     * The callers {@code ClassLoader} instance is used to find the package
-     * instance corresponding to the named class. If the callers
-     * {@code ClassLoader} instance is null then the set of packages loaded
-     * by the system {@code ClassLoader} instance is searched to find the
-     * named package. <p>
+     * Finds a package by name in the caller's class loader and its
+     * ancestors.
+     * <p>
+     * If the caller's class loader defines a {@code Package} of the given name,
+     * the {@code Package} is returned. Otherwise, the ancestors of the
+     * caller's class loader are searched recursively (parent by parent)
+     * for a {@code Package} of the given name.
+     * <p>
+     * Calling this method is equivalent to calling {@link ClassLoader#getPackage}
+     * on a {@code ClassLoader} instance which is the caller's class loader.
      *
-     * Packages have attributes for versions and specifications only if the class
-     * loader created the package instance with the appropriate attributes. Typically,
-     * those attributes are defined in the manifests that accompany the classes.
+     * @param name A package name, such as "{@code java.lang}".
+     * @return The {@code Package} of the given name defined by the caller's
+     *         class loader or its ancestors, or {@code null} if not found.
      *
-     * @param name a package name, for example, java.lang.
-     * @return the package of the requested name. It may be null if no package
-     *          information is available from the archive or codebase.
+     * @deprecated
+     * If multiple class loaders delegate to each other and define classes
+     * with the same package name, and one such loader relies on the lookup
+     * behavior of {@code getPackage} to return a {@code Package} from
+     * a parent loader, then the properties exposed by the {@code Package}
+     * may not be as expected in the rest of the program.
+     * For example, the {@code Package} will only expose annotations from the
+     * {@code package-info.class} file defined by the parent loader, even if
+     * annotations exist in a {@code package-info.class} file defined by
+     * a child loader.  A more robust approach is to use the
+     * {@link ClassLoader#getDefinedPackage} method which returns
+     * a {@code Package} for the specified class loader.
+     *
+     * @see ClassLoader#getDefinedPackage
      */
     @CallerSensitive
+    @Deprecated
+    @SuppressWarnings("deprecation")
     public static Package getPackage(String name) {
         ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
-        if (l != null) {
-            return l.getPackage(name);
-        } else {
-            return getSystemPackage(name);
-        }
+        return l != null ? l.getPackage(name) : BootLoader.getDefinedPackage(name);
     }
 
     /**
-     * Get all the packages currently known for the caller's {@code ClassLoader}
-     * instance.  Those packages correspond to classes loaded via or accessible by
-     * name to that {@code ClassLoader} instance.  If the caller's
-     * {@code ClassLoader} instance is the bootstrap {@code ClassLoader}
-     * instance, which may be represented by {@code null} in some implementations,
-     * only packages corresponding to classes loaded by the bootstrap
-     * {@code ClassLoader} instance will be returned.
+     * Returns all of the {@code Package}s defined by the caller's class loader
+     * and its ancestors.  The returned array may contain more than one
+     * {@code Package} object of the same package name, each defined by
+     * a different class loader in the class loader hierarchy.
+     * <p>
+     * Calling this method is equivalent to calling {@link ClassLoader#getPackages}
+     * on a {@code ClassLoader} instance which is the caller's class loader.
      *
-     * @return a new array of packages known to the callers {@code ClassLoader}
-     * instance.  An zero length array is returned if none are known.
+     * @return  The array of {@code Package} objects defined by this
+     *          class loader and its ancestors
+     *
+     * @see ClassLoader#getDefinedPackages
      */
     @CallerSensitive
     public static Package[] getPackages() {
-        ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
-        if (l != null) {
-            return l.getPackages();
-        } else {
-            return getSystemPackages();
-        }
-    }
-
-    /**
-     * Get the package for the specified class.
-     * The class's class loader is used to find the package instance
-     * corresponding to the specified class. If the class loader
-     * is the bootstrap class loader, which may be represented by
-     * {@code null} in some implementations, then the set of packages
-     * loaded by the bootstrap class loader is searched to find the package.
-     * <p>
-     * Packages have attributes for versions and specifications only
-     * if the class loader created the package
-     * instance with the appropriate attributes. Typically those
-     * attributes are defined in the manifests that accompany
-     * the classes.
-     *
-     * @param c the class to get the package of.
-     * @return the package of the class. It may be null if no package
-     *          information is available from the archive or codebase.  */
-    static Package getPackage(Class<?> c) {
-        String name = c.getName();
-        int i = name.lastIndexOf('.');
-        if (i != -1) {
-            name = name.substring(0, i);
-            ClassLoader cl = c.getClassLoader();
-            if (cl != null) {
-                return cl.getPackage(name);
-            } else {
-                return getSystemPackage(name);
-            }
-        } else {
-            return null;
-        }
+        ClassLoader cl = ClassLoader.getClassLoader(Reflection.getCallerClass());
+        return cl != null ? cl.getPackages() : BootLoader.packages().toArray(Package[]::new);
     }
 
     /**
      * Return the hash code computed from the package name.
      * @return the hash code computed from the package name.
      */
+    @Override
     public int hashCode(){
-        return pkgName.hashCode();
+        return packageName().hashCode();
     }
 
     /**
@@ -350,9 +376,10 @@
      * If the package version is defined it is appended.
      * @return the string representation of the package.
      */
+    @Override
     public String toString() {
-        String spec = specTitle;
-        String ver =  specVersion;
+        String spec = versionInfo.specTitle;
+        String ver =  versionInfo.specVersion;
         if (spec != null && spec.length() > 0)
             spec = ", " + spec;
         else
@@ -361,14 +388,20 @@
             ver = ", version " + ver;
         else
             ver = "";
-        return "package " + pkgName + spec + ver;
+        return "package " + packageName() + spec + ver;
     }
 
     private Class<?> getPackageInfo() {
         if (packageInfo == null) {
-            try {
-                packageInfo = Class.forName(pkgName + ".package-info", false, loader);
-            } catch (ClassNotFoundException ex) {
+            // find package-info.class defined by loader
+            String cn = packageName() + ".package-info";
+            PrivilegedAction<ClassLoader> pa = module()::getClassLoader;
+            ClassLoader loader = AccessController.doPrivileged(pa);
+            Class<?> c = loader != null ? loader.loadLocalClass(cn)
+                                        : BootLoader.loadClassOrNull(cn);
+            if (c != null) {
+                packageInfo = c;
+            } else {
                 // store a proxy for the package info that has no annotations
                 class PackageInfoProxy {}
                 packageInfo = PackageInfoProxy.class;
@@ -437,8 +470,12 @@
     }
 
     /**
-     * Construct a package instance with the specified version
-     * information.
+     * Construct a package instance for an unnamed module
+     * with the specified version information.
+     *
+     * @apiNote
+     * This method should not be called to define a Package for named module.
+     *
      * @param name the name of the package
      * @param spectitle the title of the specification
      * @param specversion the version of the specification
@@ -446,216 +483,73 @@
      * @param impltitle the title of the implementation
      * @param implversion the version of the implementation
      * @param implvendor the organization that maintains the implementation
+     * @param sealbase code source where this Package comes from
+     * @param loader defining class loader
      */
     Package(String name,
             String spectitle, String specversion, String specvendor,
             String impltitle, String implversion, String implvendor,
             URL sealbase, ClassLoader loader)
     {
-        pkgName = name;
-        implTitle = impltitle;
-        implVersion = implversion;
-        implVendor = implvendor;
-        specTitle = spectitle;
-        specVersion = specversion;
-        specVendor = specvendor;
-        sealBase = sealbase;
-        this.loader = loader;
+        super(Objects.requireNonNull(name),
+              loader != null ? loader.getUnnamedModule()
+                             : BootLoader.getUnnamedModule());
+
+        this.versionInfo = VersionInfo.getInstance(spectitle, specversion,
+                                                   specvendor, impltitle,
+                                                   implversion, implvendor,
+                                                   sealbase);
+    }
+
+    Package(String name, Module module) {
+        super(name, module);
+        this.versionInfo = VersionInfo.NULL_VERSION_INFO;
     }
 
     /*
-     * Construct a package using the attributes from the specified manifest.
-     *
-     * @param name the package name
-     * @param man the optional manifest for the package
-     * @param url the optional code source url for the package
+     * Versioning information.  Only for packages in unnamed modules.
      */
-    private Package(String name, Manifest man, URL url, ClassLoader loader) {
-        String path = name.replace('.', '/').concat("/");
-        String sealed = null;
-        String specTitle= null;
-        String specVersion= null;
-        String specVendor= null;
-        String implTitle= null;
-        String implVersion= null;
-        String implVendor= null;
-        URL sealBase= null;
-        Attributes attr = man.getAttributes(path);
-        if (attr != null) {
-            specTitle   = attr.getValue(Name.SPECIFICATION_TITLE);
-            specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
-            specVendor  = attr.getValue(Name.SPECIFICATION_VENDOR);
-            implTitle   = attr.getValue(Name.IMPLEMENTATION_TITLE);
-            implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
-            implVendor  = attr.getValue(Name.IMPLEMENTATION_VENDOR);
-            sealed      = attr.getValue(Name.SEALED);
-        }
-        attr = man.getMainAttributes();
-        if (attr != null) {
-            if (specTitle == null) {
-                specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
-            }
-            if (specVersion == null) {
-                specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
-            }
-            if (specVendor == null) {
-                specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
-            }
-            if (implTitle == null) {
-                implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
-            }
-            if (implVersion == null) {
-                implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
-            }
-            if (implVendor == null) {
-                implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
-            }
-            if (sealed == null) {
-                sealed = attr.getValue(Name.SEALED);
-            }
-        }
-        if ("true".equalsIgnoreCase(sealed)) {
-            sealBase = url;
-        }
-        pkgName = name;
-        this.specTitle = specTitle;
-        this.specVersion = specVersion;
-        this.specVendor = specVendor;
-        this.implTitle = implTitle;
-        this.implVersion = implVersion;
-        this.implVendor = implVendor;
-        this.sealBase = sealBase;
-        this.loader = loader;
-    }
+    static class VersionInfo {
+        static final VersionInfo NULL_VERSION_INFO
+            = new VersionInfo(null, null, null, null, null, null, null);
 
-    /*
-     * Returns the loaded system package for the specified name.
-     */
-    static Package getSystemPackage(String name) {
-        Package pkg = pkgs.get(name);
-        if (pkg == null) {
-            name = name.replace('.', '/').concat("/");
-            String fn = getSystemPackage0(name);
-            if (fn != null) {
-                pkg = defineSystemPackage(name, fn);
+        private final String specTitle;
+        private final String specVersion;
+        private final String specVendor;
+        private final String implTitle;
+        private final String implVersion;
+        private final String implVendor;
+        private final URL sealBase;
+
+        static VersionInfo getInstance(String spectitle, String specversion,
+                                       String specvendor, String impltitle,
+                                       String implversion, String implvendor,
+                                       URL sealbase) {
+            if (spectitle == null && specversion == null &&
+                    specvendor == null && impltitle == null &&
+                    implvendor == null && sealbase == null) {
+                return NULL_VERSION_INFO;
             }
-        }
-        return pkg;
-    }
-
-    /*
-     * Return an array of loaded system packages.
-     */
-    static Package[] getSystemPackages() {
-        // First, update the system package map with new package names
-        String[] names = getSystemPackages0();
-        for (String name : names) {
-            if (!pkgs.containsKey(name)) {
-                defineSystemPackage(name, getSystemPackage0(name));
-            }
-        }
-        return pkgs.values().toArray(new Package[pkgs.size()]);
-    }
-
-    private static Package defineSystemPackage(final String iname,
-                                               final String fn)
-    {
-        // Convert to "."-separated package name
-        String name = iname.substring(0, iname.length() - 1).replace('/', '.');
-        // Creates a cached manifest for the file name, allowing
-        // only-once, lazy reads of manifest from jar files
-        CachedManifest cachedManifest = createCachedManifest(fn);
-        pkgs.putIfAbsent(name, new Package(name, cachedManifest.getManifest(),
-                                           cachedManifest.getURL(), null));
-        // Ensure we only expose one Package object
-        return pkgs.get(name);
-    }
-
-    private static CachedManifest createCachedManifest(String fn) {
-        if (!manifests.containsKey(fn)) {
-            manifests.putIfAbsent(fn, new CachedManifest(fn));
-        }
-        return manifests.get(fn);
-    }
-
-    // The map of loaded system packages
-    private static final ConcurrentHashMap<String, Package> pkgs
-            = new ConcurrentHashMap<>();
-
-    // Maps each directory or zip file name to its corresponding manifest, if
-    // it exists
-    private static final ConcurrentHashMap<String, CachedManifest> manifests
-            = new ConcurrentHashMap<>();
-
-    private static class CachedManifest {
-        private static final Manifest EMPTY_MANIFEST = new Manifest();
-        private final String fileName;
-        private final URL url;
-        private volatile Manifest manifest;
-
-        CachedManifest(final String fileName) {
-            this.fileName = fileName;
-            this.url = AccessController.doPrivileged(new PrivilegedAction<>() {
-                public URL run() {
-                    final File file = new File(fileName);
-                    if (file.isFile()) {
-                        try {
-                            return ParseUtil.fileToEncodedURL(file);
-                        } catch (MalformedURLException e) {
-                        }
-                    }
-                    return null;
-                }
-            });
+            return new VersionInfo(spectitle, specversion, specvendor,
+                    impltitle, implversion, implvendor,
+                    sealbase);
         }
 
-        public URL getURL() {
-            return url;
-        }
-
-        public Manifest getManifest() {
-            if (url == null) {
-                return EMPTY_MANIFEST;
-            }
-            Manifest m = manifest;
-            if (m != null) {
-                return m;
-            }
-            synchronized (this) {
-                m = manifest;
-                if (m != null) {
-                    return m;
-                }
-                m = AccessController.doPrivileged(new PrivilegedAction<>() {
-                    public Manifest run() {
-                        try (FileInputStream fis = new FileInputStream(fileName);
-                             JarInputStream jis = new JarInputStream(fis, false)) {
-                            return jis.getManifest();
-                        } catch (IOException e) {
-                            return null;
-                        }
-                    }
-                });
-                manifest = m = (m == null ? EMPTY_MANIFEST : m);
-            }
-            return m;
+        private VersionInfo(String spectitle, String specversion,
+                            String specvendor, String impltitle,
+                            String implversion, String implvendor,
+                            URL sealbase)
+        {
+            this.implTitle = impltitle;
+            this.implVersion = implversion;
+            this.implVendor = implvendor;
+            this.specTitle = spectitle;
+            this.specVersion = specversion;
+            this.specVendor = specvendor;
+            this.sealBase = sealbase;
         }
     }
 
-    private static native String getSystemPackage0(String name);
-    private static native String[] getSystemPackages0();
-
-    /*
-     * Private storage for the package name and attributes.
-     */
-    private final String pkgName;
-    private final String specTitle;
-    private final String specVersion;
-    private final String specVendor;
-    private final String implTitle;
-    private final String implVersion;
-    private final String implVendor;
-    private final URL sealBase;
-    private final transient ClassLoader loader;
-    private transient Class<?> packageInfo;
+    private final VersionInfo versionInfo;
+    private Class<?> packageInfo;
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java
index 5c7fbde..0750af1 100644
--- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java
+++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java
@@ -29,6 +29,7 @@
 
 import static java.lang.StackWalker.Option.*;
 import java.lang.StackWalker.StackFrame;
+import java.lang.reflect.Module;
 import java.util.Optional;
 import java.util.OptionalInt;
 
@@ -133,4 +134,21 @@
     static native void fillInStackFrames(int startIndex,
                                          Object[] stackframes,
                                          int fromIndex, int toIndex);
+
+    @Override
+    public StackTraceElement toStackTraceElement() {
+        ensureMethodInfoInitialized();
+
+        Module module = declaringClass.getModule();
+        String moduleName = module.isNamed() ? module.getName() : null;
+        String moduleVersion = null;
+        if (module.isNamed() && module.getDescriptor().version().isPresent()) {
+            moduleVersion = module.getDescriptor().version().get().toString();
+        }
+        return new StackTraceElement(moduleName, moduleVersion,
+                                     getClassName(), getMethodName(),
+                                     fileName,
+                                     lineNumber);
+    }
+
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
index 58738d8..1ad9a9c 100644
--- a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
+++ b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
  */
 public final class StackTraceElement implements java.io.Serializable {
     // Normally initialized by VM (public constructor added in 1.5)
+    private String moduleName;
+    private String moduleVersion;
     private String declaringClass;
     private String methodName;
     private String fileName;
@@ -48,7 +50,9 @@
 
     /**
      * Creates a stack trace element representing the specified execution
-     * point.
+     * point. The {@link #getModuleName module name} and {@link
+     * #getModuleVersion module version} of the stack trace element will
+     * be {@code null}.
      *
      * @param declaringClass the fully qualified name of the class containing
      *        the execution point represented by the stack trace element
@@ -68,6 +72,40 @@
      */
     public StackTraceElement(String declaringClass, String methodName,
                              String fileName, int lineNumber) {
+        this(null, null, declaringClass, methodName, fileName, lineNumber);
+    }
+
+    /**
+     * Creates a stack trace element representing the specified execution
+     * point.
+     *
+     * @param moduleName the module name if the class containing the
+     *        execution point represented by the stack trace is in a named
+     *        module; can be {@code null}
+     * @param moduleVersion the module version if the class containing the
+     *        execution point represented by the stack trace is in a named
+     *        module that has a version; can be {@code null}
+     * @param declaringClass the fully qualified name of the class containing
+     *        the execution point represented by the stack trace element
+     * @param methodName the name of the method containing the execution point
+     *        represented by the stack trace element
+     * @param fileName the name of the file containing the execution point
+     *        represented by the stack trace element, or {@code null} if
+     *        this information is unavailable
+     * @param lineNumber the line number of the source line containing the
+     *        execution point represented by this stack trace element, or
+     *        a negative number if this information is unavailable. A value
+     *        of -2 indicates that the method containing the execution point
+     *        is a native method
+     * @throws NullPointerException if {@code declaringClass} is {@code null}
+     *         or {@code methodName} is {@code null}
+     * @since 9
+     */
+    public StackTraceElement(String moduleName, String moduleVersion,
+                             String declaringClass, String methodName,
+                             String fileName, int lineNumber) {
+        this.moduleName     = moduleName;
+        this.moduleVersion  = moduleVersion;
         this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null");
         this.methodName     = Objects.requireNonNull(methodName, "Method name is null");
         this.fileName       = fileName;
@@ -106,6 +144,34 @@
     }
 
     /**
+     * Returns the module name of the module containing the execution point
+     * represented by this stack trace element.
+     *
+     * @return the module name of the {@code Module} containing the execution
+     *         point represented by this stack trace element; {@code null}
+     *         if the module name is not available.
+     * @since 9
+     * @see java.lang.reflect.Module#getName()
+     */
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    /**
+     * Returns the module version of the module containing the execution point
+     * represented by this stack trace element.
+     *
+     * @return the module version of the {@code Module} containing the execution
+     *         point represented by this stack trace element; {@code null}
+     *         if the module version is not available.
+     * @since 9
+     * @see java.lang.module.ModuleDescriptor.Version
+     */
+    public String getModuleVersion() {
+        return moduleVersion;
+    }
+
+    /**
      * Returns the fully qualified name of the class containing the
      * execution point represented by this stack trace element.
      *
@@ -148,32 +214,42 @@
      * examples may be regarded as typical:
      * <ul>
      * <li>
-     *   {@code "MyClass.mash(MyClass.java:9)"} - Here, {@code "MyClass"}
-     *   is the <i>fully-qualified name</i> of the class containing the
-     *   execution point represented by this stack trace element,
+     *   {@code "MyClass.mash(my.module@9.0/MyClass.java:101)"} - Here,
+     *   {@code "MyClass"} is the <i>fully-qualified name</i> of the class
+     *   containing the execution point represented by this stack trace element,
      *   {@code "mash"} is the name of the method containing the execution
-     *   point, {@code "MyClass.java"} is the source file containing the
-     *   execution point, and {@code "9"} is the line number of the source
+     *   point, {@code "my.module"} is the module name, {@code "9.0"} is the
+     *   module version, and {@code "101"} is the line number of the source
      *   line containing the execution point.
      * <li>
-     *   {@code "MyClass.mash(MyClass.java)"} - As above, but the line
-     *   number is unavailable.
+     *   {@code "MyClass.mash(my.module@9.0/MyClass.java)"} - As above, but the
+     *   line number is unavailable.
      * <li>
-     *   {@code "MyClass.mash(Unknown Source)"} - As above, but neither
-     *   the file name nor the line  number are available.
+     *   {@code "MyClass.mash(my.module@9.0/Unknown Source)"} - As above, but
+     *   neither the file name nor the line  number are available.
      * <li>
-     *   {@code "MyClass.mash(Native Method)"} - As above, but neither
-     *   the file name nor the line  number are available, and the method
-     *   containing the execution point is known to be a native method.
+     *   {@code "MyClass.mash(my.module@9.0/Native Method)"} - As above, but
+     *   neither the file name nor the line  number are available, and the
+     *   method containing the execution point is known to be a native method.
      * </ul>
+     * If the execution point is not in a named module, {@code "my.module@9.0/"}
+     * will be omitted from the above.
+     *
      * @see    Throwable#printStackTrace()
      */
     public String toString() {
-        return getClassName() + "." + methodName +
-            (isNativeMethod() ? "(Native Method)" :
-             (fileName != null && lineNumber >= 0 ?
-              "(" + fileName + ":" + lineNumber + ")" :
-              (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
+        String mid = "";
+        if (moduleName != null) {
+            mid = moduleName;
+            if (moduleVersion != null)
+                mid += "@" + moduleVersion;
+            mid += "/";
+        }
+        return getClassName() + "." + methodName + "(" + mid +
+             (isNativeMethod() ? "Native Method)" :
+              (fileName != null && lineNumber >= 0 ?
+               fileName + ":" + lineNumber + ")" :
+                (fileName != null ?  ""+fileName+")" : "Unknown Source)")));
     }
 
     /**
@@ -184,6 +260,8 @@
      * <pre>{@code
      *     equals(a.getFileName(), b.getFileName()) &&
      *     a.getLineNumber() == b.getLineNumber()) &&
+     *     equals(a.getModuleName(), b.getModuleName()) &&
+     *     equals(a.getModuleVersion(), b.getModuleVersion()) &&
      *     equals(a.getClassName(), b.getClassName()) &&
      *     equals(a.getMethodName(), b.getMethodName())
      * }</pre>
@@ -202,6 +280,8 @@
             return false;
         StackTraceElement e = (StackTraceElement)obj;
         return e.declaringClass.equals(declaringClass) &&
+            Objects.equals(moduleName, e.moduleName) &&
+            Objects.equals(moduleVersion, e.moduleVersion) &&
             e.lineNumber == lineNumber &&
             Objects.equals(methodName, e.methodName) &&
             Objects.equals(fileName, e.fileName);
@@ -212,6 +292,8 @@
      */
     public int hashCode() {
         int result = 31*declaringClass.hashCode() + methodName.hashCode();
+        result = 31*result + Objects.hashCode(moduleName);
+        result = 31*result + Objects.hashCode(moduleVersion);
         result = 31*result + Objects.hashCode(fileName);
         result = 31*result + lineNumber;
         return result;
diff --git a/jdk/src/java.base/share/classes/java/lang/StackWalker.java b/jdk/src/java.base/share/classes/java/lang/StackWalker.java
index f628459..636762e 100644
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java
@@ -170,15 +170,8 @@
          * Gets a {@code StackTraceElement} for this stack frame.
          *
          * @return {@code StackTraceElement} for this stack frame.
-         *
-         * */
-        public default StackTraceElement toStackTraceElement() {
-            int lineNumber = isNativeMethod() ? -2
-                                              : getLineNumber().orElse(-1);
-            return new StackTraceElement(getClassName(), getMethodName(),
-                                         getFileName().orElse(null),
-                                         lineNumber);
-        }
+         */
+        public StackTraceElement toStackTraceElement();
     }
 
     /**
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 c0c7c05..92fee1a 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -24,9 +24,23 @@
  */
 package java.lang;
 
-import java.io.*;
-import java.lang.reflect.Executable;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Console;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
+import java.net.URL;
 import java.security.AccessControlContext;
 import java.util.Properties;
 import java.util.PropertyPermission;
@@ -35,6 +49,8 @@
 import java.security.PrivilegedAction;
 import java.nio.channels.Channel;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.stream.Stream;
+
 import java.util.Objects;
 import java.util.ResourceBundle;
 import java.util.function.Supplier;
@@ -51,6 +67,10 @@
 import jdk.internal.logger.LazyLoggers;
 import jdk.internal.logger.LocalizedLoggerWrapper;
 
+import jdk.internal.module.ModuleBootstrap;
+import jdk.internal.module.Modules;
+import jdk.internal.module.ServicesCatalog;
+
 /**
  * The <code>System</code> class contains several useful class fields
  * and methods. It cannot be instantiated.
@@ -65,7 +85,6 @@
  * @since   1.0
  */
 public final class System {
-
     /* register the natives via the static initializer.
      *
      * VM will invoke the initializeSystemClass method to complete
@@ -619,6 +638,24 @@
      * <code>getProperties</code> operation, it may choose to permit the
      * {@link #getProperty(String)} operation.
      *
+     * @implNote In addition to the standard system properties, the {@code
+     * java} launcher may create the Java Virtual Machine with system
+     * properties that have the following keys:
+     * <table summary="Shows property keys and associated values">
+     * <tr><th>Key</th>
+     *     <th>Description of Associated Value</th></tr>
+     * <tr><td>{@code jdk.module.path}</td>
+     *     <td>Application module path</td></tr>
+     * <tr><td>{@code jdk.upgrade.module.path}</td>
+     *     <td>The upgrade module path</td></tr>
+     * <tr><td>{@code jdk.module.main}</td>
+     *     <td>The module name of the initial/main module</td></tr>
+     * <tr><td>{@code jdk.module.main.class}</td>
+     *     <td>The main class name of the initial module</td></tr>
+     * </table>
+     * These properties may also be set by custom launchers that use the JNI
+     * invocation API to create the Java Virtual Machine.
+     *
      * @return     the system properties
      * @exception  SecurityException  if a security manager exists and its
      *             <code>checkPropertiesAccess</code> method doesn't allow access
@@ -1795,11 +1832,10 @@
         return new PrintStream(new BufferedOutputStream(fos, 128), true);
     }
 
-
     /**
      * Initialize the system class.  Called after thread initialization.
      */
-    private static void initializeSystemClass() {
+    private static void initPhase1() {
 
         // VM might invoke JNU_NewStringPlatform() to set those encoding
         // sensitive properties (user.home, user.name, boot.class.path, etc.)
@@ -1828,7 +1864,6 @@
         // certain system properties that are not intended for public access.
         VM.saveAndRemoveProperties(props);
 
-
         lineSeparator = props.getProperty("line.separator");
         VersionProps.init();
 
@@ -1862,9 +1897,81 @@
 
         // Subsystems that are invoked during initialization can invoke
         // VM.isBooted() in order to avoid doing things that should
-        // wait until the application class loader has been set up.
+        // wait until the VM is fully initialized. The initialization level
+        // is incremented from 0 to 1 here to indicate the first phase of
+        // initialization has completed.
         // IMPORTANT: Ensure that this remains the last initialization action!
-        VM.booted();
+        VM.initLevel(1);
+    }
+
+    // @see #initPhase2()
+    private static Layer bootLayer;
+
+    /*
+     * Invoked by VM.  Phase 2 module system initialization.
+     * Only classes in java.base can be loaded in this phase.
+     */
+    private static void initPhase2() {
+        // initialize the module system
+        System.bootLayer = ModuleBootstrap.boot();
+
+        // base module needs to be loose (CODETOOLS-7901619)
+        Module base = Object.class.getModule();
+        Modules.addReads(base, null);
+
+        // module system initialized
+        VM.initLevel(2);
+    }
+
+    /*
+     * Invoked by VM.  Phase 3 is the final system initialization:
+     * 1. set security manager
+     * 2. set system class loader
+     * 3. set TCCL
+     *
+     * This method must be called after the module system initialization.
+     * The security manager and system class loader may be custom class from
+     * the application classpath or modulepath.
+     */
+    private static void initPhase3() {
+        // set security manager
+        String cn = System.getProperty("java.security.manager");
+        if (cn != null) {
+            if (cn.isEmpty() || "default".equals(cn)) {
+                System.setSecurityManager(new SecurityManager());
+            } else {
+                try {
+                    Class<?> c = Class.forName(cn, false, ClassLoader.getBuiltinAppClassLoader());
+                    Constructor<?> ctor = c.getConstructor();
+                    // Must be a public subclass of SecurityManager with
+                    // a public no-arg constructor
+                    if (!SecurityManager.class.isAssignableFrom(c) ||
+                            !Modifier.isPublic(c.getModifiers()) ||
+                            !Modifier.isPublic(ctor.getModifiers())) {
+                        throw new Error("Could not create SecurityManager: " + ctor.toString());
+                    }
+                    // custom security manager implementation may be in unnamed module
+                    // or a named module but non-exported package
+                    ctor.setAccessible(true);
+                    SecurityManager sm = (SecurityManager) ctor.newInstance();
+                    System.setSecurityManager(sm);
+                } catch (Exception e) {
+                    throw new Error("Could not create SecurityManager", e);
+                }
+            }
+        }
+
+        // initializing the system class loader
+        VM.initLevel(3);
+
+        // system class loader initialized
+        ClassLoader scl = ClassLoader.initSystemClassLoader();
+
+        // set TCCL
+        Thread.currentThread().setContextClassLoader(scl);
+
+        // system is fully initialized
+        VM.initLevel(4);
     }
 
     private static void setJavaLangAccess() {
@@ -1910,6 +2017,27 @@
             public void invokeFinalize(Object o) throws Throwable {
                 o.finalize();
             }
+            public Layer getBootLayer() {
+                return bootLayer;
+            }
+            public ServicesCatalog getServicesCatalog(ClassLoader cl) {
+                return cl.getServicesCatalog();
+            }
+            public ServicesCatalog createOrGetServicesCatalog(ClassLoader cl) {
+                return cl.createOrGetServicesCatalog();
+            }
+            public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
+                return cl.findBootstrapClassOrNull(name);
+            }
+            public URL findResource(ClassLoader cl, String mn, String name) throws IOException {
+                return cl.findResource(mn, name);
+            }
+            public Stream<Package> packages(ClassLoader cl) {
+                return cl.packages();
+            }
+            public Package definePackage(ClassLoader cl, String name, Module module) {
+                return cl.definePackage(name, module);
+            }
             public String fastUUID(long lsb, long msb) {
                 return Long.fastUUID(lsb, msb);
             }
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
index 90d0d59..3d9d59f 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -788,7 +788,8 @@
         static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) {
             try {
                 Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
-                assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
+                // ## FIXME: annotation parser can't create proxy classes until module system is fully initialzed
+                // assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
                 F_SPECIES_DATA.set(null, speciesData);
             } catch (ReflectiveOperationException ex) {
                 throw newInternalError(ex);
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java
index 50e28e5..3c6b0d1 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java
@@ -33,6 +33,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Member;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -475,8 +476,9 @@
 
     /** Utility method to query whether this member is accessible from a given lookup class. */
     public boolean isAccessibleFrom(Class<?> lookupClass) {
+        int mode = (ALL_ACCESS|MethodHandles.Lookup.PACKAGE|MethodHandles.Lookup.MODULE);
         return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
-                                               lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
+                                               lookupClass, mode);
     }
 
     /** Initialize a query.   It is not resolved. */
@@ -851,7 +853,20 @@
 
     public IllegalAccessException makeAccessException(String message, Object from) {
         message = message + ": "+ toString();
-        if (from != null)  message += ", from " + from;
+        if (from != null)  {
+            if (from == MethodHandles.publicLookup()) {
+                message += ", from public Lookup";
+            } else {
+                Module m;
+                if (from instanceof MethodHandles.Lookup) {
+                    MethodHandles.Lookup lookup = (MethodHandles.Lookup)from;
+                    m = lookup.lookupClass().getModule();
+                } else {
+                    m = from.getClass().getModule();
+                }
+                message += ", from " + from + " (" + m + ")";
+            }
+        }
         return new IllegalAccessException(message);
     }
     private String message() {
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 9b4029c..ed1dccc 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
@@ -1191,14 +1191,9 @@
                             Class<T> tClass = T.class;
                             String tName = tClass.getName();
                             String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class";
-                            java.net.URLConnection uconn = tClass.getResource(tResource).openConnection();
-                            int len = uconn.getContentLength();
-                            byte[] bytes = new byte[len];
-                            try (java.io.InputStream str = uconn.getInputStream()) {
-                                int nr = str.read(bytes);
-                                if (nr != len)  throw new java.io.IOException(tResource);
+                            try (java.io.InputStream in = tClass.getResourceAsStream(tResource)) {
+                                values[0] = in.readAllBytes();
                             }
-                            values[0] = bytes;
                         } catch (java.io.IOException ex) {
                             throw new InternalError(ex);
                         }
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 7079127..9bf86d9 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
@@ -26,7 +26,13 @@
 package java.lang.invoke;
 
 import java.lang.reflect.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Objects;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.VerifyAccess;
@@ -44,6 +50,9 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
 /**
  * This class consists exclusively of static methods that operate on or return
  * method handles. They fall into several categories:
@@ -94,18 +103,16 @@
 
     /**
      * Returns a {@link Lookup lookup object} which is trusted minimally.
-     * It can only be used to create method handles to
-     * publicly accessible fields and methods.
+     * It can only be used to create method handles to public members in
+     * public classes in packages that are exported unconditionally.
      * <p>
-     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
-     * of this lookup object will be {@link java.lang.Object}.
+     * For now, the {@linkplain Lookup#lookupClass lookup class} of this lookup
+     * object is in an unnamed module.
      *
      * <p style="font-size:smaller;">
      * <em>Discussion:</em>
      * The lookup class can be changed to any other class {@code C} using an expression of the form
      * {@link Lookup#in publicLookup().in(C.class)}.
-     * Since all classes have equal access to public names,
-     * such a change would confer no new access rights.
      * A public lookup object is always subject to
      * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
      * Also, it cannot access
@@ -113,7 +120,15 @@
      * @return a lookup object which is trusted minimally
      */
     public static Lookup publicLookup() {
-        return Lookup.PUBLIC_LOOKUP;
+        // During VM startup then only classes in the java.base module can be
+        // loaded and linked. This is because java.base exports aren't setup until
+        // the module system is initialized, hence types in the unnamed module
+        // (or any named module) can't link to java/lang/Object.
+        if (!jdk.internal.misc.VM.isModuleSystemInited()) {
+            return new Lookup(Object.class, Lookup.PUBLIC);
+        } else {
+            return LookupHelper.PUBLIC_LOOKUP;
+        }
     }
 
     /**
@@ -386,7 +401,7 @@
      * to a subset of members normally accessible to the lookup class.
      * For example, the {@link MethodHandles#publicLookup publicLookup}
      * method produces a lookup object which is only allowed to access
-     * public members in public classes.
+     * public members in public classes of exported packages.
      * The caller sensitive method {@link MethodHandles#lookup lookup}
      * produces a lookup object with full capabilities relative to
      * its caller class, to emulate all supported bytecode behaviors.
@@ -558,12 +573,24 @@
          */
         public static final int PACKAGE = Modifier.STATIC;
 
-        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
+        /** A single-bit mask representing {@code module} access (default access),
+         *  which may contribute to the result of {@link #lookupModes lookupModes}.
+         *  The value is {@code 0x10}, which does not correspond meaningfully to
+         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
+         *  In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup}
+         *  with this lookup mode can access all public types in the module of the
+         *  lookup class and public types in packages exported by other modules
+         *  to the module of the lookup class.
+         *  @since 9
+         */
+        public static final int MODULE = PACKAGE << 1;
+
+        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE);
         private static final int TRUSTED   = -1;
 
         private static int fixmods(int mods) {
-            mods &= (ALL_MODES - PACKAGE);
-            return (mods != 0) ? mods : PACKAGE;
+            mods &= (ALL_MODES - PACKAGE - MODULE);
+            return (mods != 0) ? mods : (PACKAGE | MODULE);
         }
 
         /** Tells which class is performing the lookup.  It is this class against
@@ -589,11 +616,14 @@
          *  {@linkplain #PUBLIC PUBLIC (0x01)},
          *  {@linkplain #PRIVATE PRIVATE (0x02)},
          *  {@linkplain #PROTECTED PROTECTED (0x04)},
-         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
+         *  {@linkplain #PACKAGE PACKAGE (0x08)},
+         *  and {@linkplain #MODULE MODULE (0x10)}.
          *  <p>
          *  A freshly-created lookup object
          *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
-         *  has all possible bits set, since the caller class can access all its own members.
+         *  has all possible bits set, since the caller class can access all its own members,
+         *  all public types in the caller's module, and all public types in packages exported
+         *  by other modules to the caller's module.
          *  A lookup object on a new lookup class
          *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
          *  may have some mode bits set to zero.
@@ -630,6 +660,12 @@
          * However, the resulting {@code Lookup} object is guaranteed
          * to have no more access capabilities than the original.
          * In particular, access capabilities can be lost as follows:<ul>
+         * <li>If the lookup class for this {@code Lookup} is not in a named module,
+         * and the new lookup class is in a named module {@code M}, then no members in
+         * {@code M}'s non-exported packages will be accessible.
+         * <li>If the lookup for this {@code Lookup} is in a named module, and the
+         * new lookup class is in a different module {@code M}, then no members, not even
+         * public members in {@code M}'s exported packages, will be accessible.
          * <li>If the new lookup class differs from the old one,
          * protected members will not be accessible by virtue of inheritance.
          * (Protected members may continue to be accessible because of package sharing.)
@@ -652,7 +688,17 @@
                 return new Lookup(requestedLookupClass, ALL_MODES);
             if (requestedLookupClass == this.lookupClass)
                 return this;  // keep same capabilities
+
             int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
+            if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) {
+                // Allowed to teleport from an unnamed to a named module but resulting
+                // Lookup has no access to module private members
+                if (this.lookupClass.getModule().isNamed()) {
+                    newModes = 0;
+                } else {
+                    newModes &= ~MODULE;
+                }
+            }
             if ((newModes & PACKAGE) != 0
                 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
                 newModes &= ~(PACKAGE|PRIVATE);
@@ -668,6 +714,7 @@
                 // No permissions.
                 newModes = 0;
             }
+
             checkUnprivilegedlookupClass(requestedLookupClass, newModes);
             return new Lookup(requestedLookupClass, newModes);
         }
@@ -675,12 +722,6 @@
         // Make sure outer class is initialized first.
         static { IMPL_NAMES.getClass(); }
 
-        /** Version of lookup which is trusted minimally.
-         *  It can only be used to create method handles to
-         *  publicly accessible members.
-         */
-        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
-
         /** Package-private version of lookup which is trusted. */
         static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
 
@@ -708,12 +749,13 @@
          * allowed access, and is chosen as follows:
          * <ul>
          * <li>If no access is allowed, the suffix is "/noaccess".
-         * <li>If only public access is allowed, the suffix is "/public".
-         * <li>If only public and package access are allowed, the suffix is "/package".
-         * <li>If only public, package, and private access are allowed, the suffix is "/private".
+         * <li>If only public access to types in exported packages is allowed, the suffix is "/public".
+         * <li>If only public and module access are allowed, the suffix is "/module".
+         * <li>If only public, module and package access are allowed, the suffix is "/package".
+         * <li>If only public, module, package, and private access are allowed, the suffix is "/private".
          * </ul>
          * If none of the above cases apply, it is the case that full
-         * access (public, package, private, and protected) is allowed.
+         * access (public, module, package, private, and protected) is allowed.
          * In this case, no suffix is added.
          * This is true only of an object obtained originally from
          * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
@@ -735,7 +777,9 @@
                 return cname + "/noaccess";
             case PUBLIC:
                 return cname + "/public";
-            case PUBLIC|PACKAGE:
+            case PUBLIC|MODULE:
+                return cname + "/module";
+            case PUBLIC|MODULE|PACKAGE:
                 return cname + "/package";
             case ALL_MODES & ~PROTECTED:
                 return cname + "/private";
@@ -1455,7 +1499,7 @@
             Objects.requireNonNull(refc);
             Class<?> caller = lookupClassOrNull();
             if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes))
-                throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
+                throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
         }
 
         /** Check name for an illegal leading "&lt;" character. */
@@ -1584,8 +1628,6 @@
             if (Modifier.isFinal(mods) &&
                     MethodHandleNatives.refKindIsSetter(refKind))
                 throw m.makeAccessException("unexpected set of a final field", this);
-            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
-                return;  // common case
             int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
             if ((requestedModes & allowedModes) != 0) {
                 if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
@@ -1615,7 +1657,7 @@
             if (!classOK)
                 return "class is not public";
             if (Modifier.isPublic(mods))
-                return "access to public member failed";  // (how?)
+                return "access to public member failed";  // (how?, module not readable?)
             if (Modifier.isPrivate(mods))
                 return "member is private";
             if (Modifier.isProtected(mods))
@@ -1877,6 +1919,61 @@
     }
 
     /**
+     * Helper class used to lazily create PUBLIC_LOOKUP with a lookup class
+     * in an <em>unnamed module</em>.
+     *
+     * @see Lookup#publicLookup
+     */
+    private static class LookupHelper {
+        private static final String UNNAMED = "Unnamed";
+        private static final String OBJECT  = "java/lang/Object";
+
+        private static Class<?> createClass() {
+            try {
+                ClassWriter cw = new ClassWriter(0);
+                cw.visit(Opcodes.V1_8,
+                         Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
+                         UNNAMED,
+                         null,
+                         OBJECT,
+                         null);
+                cw.visitSource(UNNAMED, null);
+                cw.visitEnd();
+                byte[] bytes = cw.toByteArray();
+                ClassLoader loader = new ClassLoader(null) {
+                    @Override
+                    protected Class<?> findClass(String cn) throws ClassNotFoundException {
+                        if (cn.equals(UNNAMED))
+                            return super.defineClass(UNNAMED, bytes, 0, bytes.length);
+                        throw new ClassNotFoundException(cn);
+                    }
+                };
+                return loader.loadClass(UNNAMED);
+            } catch (Exception e) {
+                throw new InternalError(e);
+            }
+        }
+
+        private static final Class<?> PUBLIC_LOOKUP_CLASS;
+        static {
+            PrivilegedAction<Class<?>> pa = new PrivilegedAction<Class<?>>() {
+                public Class<?> run() {
+                    return createClass();
+                }
+            };
+            PUBLIC_LOOKUP_CLASS = AccessController.doPrivileged(pa);
+        }
+
+        /**
+         * Lookup that is trusted minimally. It can only be used to create
+         * method handles to publicly accessible members in exported packages.
+         *
+         * @see MethodHandles#publicLookup
+         */
+        static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC);
+    }
+
+    /**
      * Produces a method handle giving read access to elements of an array.
      * The type of the method handle will have a return type of the array's
      * element type.  Its first argument will be the array type,
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
index 9a4cecd..8c3d871 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
@@ -697,8 +697,8 @@
             case BC_SB_SIZED:
             case BC_SB_SIZED_EXACT: {
                 if (CACHE_ENABLE) {
-                    Package pkg = hostClass.getPackage();
-                    return (pkg != null ? pkg.getName().replace('.', '/') + "/" : "") + "Stubs$$StringConcat";
+                    String pkgName = hostClass.getPackageName();
+                    return (pkgName != null && !pkgName.isEmpty() ? pkgName.replace('.', '/') + "/" : "") + "Stubs$$StringConcat";
                 } else {
                     return hostClass.getName().replace('.', '/') + "$$StringConcat";
                 }
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
new file mode 100644
index 0000000..ae9a231
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
@@ -0,0 +1,431 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * The configuration that is the result of resolution or resolution with
+ * service binding.
+ *
+ * <h2><a name="resolution">Resolution</a></h2>
+ *
+ * <p> Resolution is the process of computing the transitive closure of a set
+ * of root modules over a set of observable modules by resolving the
+ * 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
+ * <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 m3 { }
+ *     module m4 { }
+ * } </pre>
+ *
+ * <p> If the module {@code m1} is resolved then the resulting configuration
+ * contains three modules ({@code m1}, {@code m2}, {@code m3}). The edges in
+ * its readability graph are: </p>
+ * <pre> {@code
+ *     m1 --> m2  (meaning m1 reads m2)
+ *     m1 --> m3
+ *     m2 --> m3
+ * } </pre>
+ *
+ * <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.
+ * </p>
+ *
+ * <p> Suppose we have the following observable modules: </p>
+ * <pre> {@code
+ *     module m1 { requires m2; requires java.xml; }
+ *     module m2 { }
+ * } </pre>
+ *
+ * <p> If module {@code m1} is resolved with the configuration for the {@link
+ * java.lang.reflect.Layer#boot() boot} layer as the parent then the resulting
+ * configuration contains two modules ({@code m1}, {@code m2}). The edges in
+ * its readability graph are:
+ * <pre> {@code
+ *     m1 --> m2
+ *     m1 --> java.xml
+ * } </pre>
+ * where module {@code java.xml} is in the parent configuration. For
+ * simplicity, this example omits the implicitly declared dependence on the
+ * {@code java.base} module.
+ *
+ * <a name="automaticmoduleresolution"></a>
+ * <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>
+
+ * <h2><a name="servicebinding">Service binding</a></h2>
+ *
+ * <p> Service binding is the process of augmenting a graph of resolved modules
+ * from the set of observable modules induced by the service-use dependence
+ * ({@code uses} and {@code provides} clauses). Any module that was not
+ * previously in the graph requires resolution to compute its transitive
+ * closure. Service binding is an iterative process in that adding a module
+ * that satisfies some service-use dependence may introduce new service-use
+ * dependences. </p>
+ *
+ * <p> Suppose we have the following observable modules: </p>
+ * <pre> {@code
+ *     module m1 { exports p; uses p.S; }
+ *     module m2 { requires m1; provides p.S with p2.S2; }
+ *     module m3 { requires m1; requires m4; provides p.S with p3.S3; }
+ *     module m4 { }
+ * } </pre>
+ *
+ * <p> If the module {@code m1} is resolved then the resulting graph of modules
+ * has one module ({@code m1}). If the graph is augmented with modules induced
+ * by the service-use dependence relation then the configuration will contain
+ * four modules ({@code m1}, {@code m2}, {@code m3}, {@code m4}). The edges in
+ * its readability graph are: </p>
+ * <pre> {@code
+ *     m2 --> m1
+ *     m3 --> m1
+ *     m3 --> m4
+ * } </pre>
+ * <p> The edges in the conceptual service-use graph are: </p>
+ * <pre> {@code
+ *     m1 --> m2  (meaning m1 uses a service that is provided by m2)
+ *     m1 --> m3
+ * } </pre>
+ *
+ * <p> If this configuration is instantiated as a {@code Layer}, and if code in
+ * module {@code m1} uses {@link java.util.ServiceLoader ServiceLoader} to
+ * iterate over implementations of {@code p.S.class}, then it will iterate over
+ * an instance of {@code p2.S2} and {@code p3.S3}. </p>
+ *
+ * <h3> Example </h3>
+ *
+ * <p> The following example uses the {@code resolveRequires} method to resolve
+ * a module named <em>myapp</em> with the configuration for the boot layer as
+ * the parent configuration. It prints the name of each resolved module and
+ * the names of the modules that each module reads. </p>
+ *
+ * <pre>{@code
+ *    ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
+ *
+ *    Configuration parent = Layer.boot().configuration();
+ *
+ *    Configuration cf = parent.resolveRequires(finder,
+ *                                              ModuleFinder.empty(),
+ *                                              Set.of("myapp"));
+ *    cf.modules().forEach(m -> {
+ *        System.out.format("%s -> %s%n",
+ *            m.name(),
+ *            m.reads().stream()
+ *                .map(ResolvedModule::name)
+ *                .collect(Collectors.joining(", ")));
+ *    });
+ * }</pre>
+ *
+ * @since 9
+ * @see java.lang.reflect.Layer
+ */
+public final class Configuration {
+
+    // @see Configuration#empty()
+    private static final Configuration EMPTY_CONFIGURATION = new Configuration();
+
+    private final Configuration parent;
+
+    private final Map<ResolvedModule, Set<ResolvedModule>> graph;
+    private final Set<ResolvedModule> modules;
+    private final Map<String, ResolvedModule> nameToModule;
+
+    private Configuration() {
+        this.parent = null;
+        this.graph = Collections.emptyMap();
+        this.modules = Collections.emptySet();
+        this.nameToModule = Collections.emptyMap();
+    }
+
+    private Configuration(Configuration parent, Resolver resolver) {
+        Map<ResolvedModule, Set<ResolvedModule>> graph = resolver.finish(this);
+
+        Map<String, ResolvedModule> nameToModule = new HashMap<>();
+        for (ResolvedModule resolvedModule : graph.keySet()) {
+            nameToModule.put(resolvedModule.name(), resolvedModule);
+        }
+
+        this.parent = parent;
+        this.graph = graph;
+        this.modules = Collections.unmodifiableSet(graph.keySet());
+        this.nameToModule = Collections.unmodifiableMap(nameToModule);
+    }
+
+
+    /**
+     * Resolves a collection of root modules, with this configuration as its
+     * parent, to create a new 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>
+     *
+     * <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>
+     *
+     * <p> Resolution and the (post-resolution) consistency checks may fail for
+     * following reasons: </p>
+     *
+     * <ul>
+     *     <li><p> A root module, or a direct or transitive dependency, is not
+     *     found. </p></li>
+     *
+     *     <li><p> An error occurs when attempting to find a module.
+     *     Possible errors include I/O errors, errors detected parsing a module
+     *     descriptor ({@code module-info.class}) or two versions of the same
+     *     module are found in the same directory. </p></li>
+     *
+     *     <li><p> A cycle is detected, say where module {@code m1} requires
+     *     module {@code m2} and {@code m2} requires {@code m1}. </p></li>
+     *
+     *     <li><p> Two or more modules in the configuration export the same
+     *     package to a module that reads both. This includes the case where a
+     *     module {@code M} containing package {@code p} reads another module
+     *     that exports {@code p} to {@code M}. </p></li>
+     *
+     *     <li><p> A module {@code M} declares that it "{@code uses p.S}" or
+     *     "{@code provides p.S with ...}" but package {@code p} is neither in
+     *     module {@code M} nor exported to {@code M} by any module that
+     *     {@code M} reads. </p></li>
+     *
+     *     <li><p> A module {@code M} declares that it
+     *     "{@code provides ... with q.T}" but package {@code q} is not in
+     *     module {@code M}. </p></li>
+     *
+     *     <li><p> Two or more modules in the configuration are specific to
+     *     different {@link ModuleDescriptor#osName() operating systems},
+     *     {@link ModuleDescriptor#osArch() architectures}, or {@link
+     *     ModuleDescriptor#osVersion() versions}. </p></li>
+     *
+     *     <li><p> Other implementation specific checks, for example referential
+     *     integrity checks to ensure that different versions of tighly coupled
+     *     modules cannot be combined in the same configuration. </p></li>
+     *
+     * </ul>
+     *
+     * @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 or in parent
+     *         configurations
+     * @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 for any of the
+     *         reasons listed
+     * @throws SecurityException
+     *         If locating a module is denied by the security manager
+     */
+    public Configuration resolveRequires(ModuleFinder before,
+                                         ModuleFinder after,
+                                         Collection<String> roots)
+    {
+        Objects.requireNonNull(before);
+        Objects.requireNonNull(after);
+        Objects.requireNonNull(roots);
+
+        Resolver resolver = new Resolver(before, this, after);
+        resolver.resolveRequires(roots);
+
+        return new Configuration(this, resolver);
+    }
+
+
+    /**
+     * Resolves a collection of root modules, with service binding, and with
+     * this configuration as its parent, to create a new configuration.
+     *
+     * <p> This method works exactly as specified by {@link #resolveRequires
+     * resolveRequires} except that the graph of resolved modules is augmented
+     * with modules induced by the service-use dependence relation. </p>
+     *
+     * <p> More specifically, the root modules are resolved as if by calling
+     * {@code resolveRequires}. The resolved modules, and all modules in the
+     * parent configurations, with {@link ModuleDescriptor#uses() service
+     * dependences} are then examined. All modules found by the given module
+     * finders that {@link ModuleDescriptor#provides() provide} an
+     * implementation of one or more of the service types are added to the
+     * module graph and then resolved as if by calling the {@code
+     * resolveRequires} method. Adding modules to the module graph may
+     * introduce new service-use dependences and so the process works
+     * iteratively until no more modules are added. </p>
+     *
+     * <p> As service binding involves resolution then it may fail with {@link
+     * ResolutionException} for exactly the same reasons specified in
+     * {@code resolveRequires}.  </p>
+     *
+     * @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 or in parent
+     *         configurations
+     * @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 for any of the
+     *         reasons listed
+     * @throws SecurityException
+     *         If locating a module is denied by the security manager
+     */
+    public Configuration resolveRequiresAndUses(ModuleFinder before,
+                                                ModuleFinder after,
+                                                Collection<String> roots)
+    {
+        Objects.requireNonNull(before);
+        Objects.requireNonNull(after);
+        Objects.requireNonNull(roots);
+
+        Resolver resolver = new Resolver(before, this, after);
+        resolver.resolveRequires(roots).resolveUses();
+
+        return new Configuration(this, resolver);
+    }
+
+
+    /**
+     * Returns the <em>empty</em> configuration. The empty configuration does
+     * not contain any modules and does not have a parent.
+     *
+     * @return The empty configuration
+     */
+    public static Configuration empty() {
+        return EMPTY_CONFIGURATION;
+    }
+
+
+    /**
+     * Returns this configuration's parent unless this is the {@linkplain #empty
+     * empty configuration}, which has no parent.
+     *
+     * @return This configuration's parent
+     */
+    public Optional<Configuration> parent() {
+        return Optional.ofNullable(parent);
+    }
+
+
+    /**
+     * Returns an immutable set of the resolved modules in this configuration.
+     *
+     * @return A possibly-empty unmodifiable set of the resolved modules
+     *         in this configuration
+     */
+    public Set<ResolvedModule> modules() {
+        return modules;
+    }
+
+
+    /**
+     * Finds a resolved module in this configuration, or if not in this
+     * configuration, the {@linkplain #parent parent} configurations.
+     *
+     * @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
+     */
+    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));
+    }
+
+
+    Set<ModuleDescriptor> descriptors() {
+        if (modules.isEmpty()) {
+            return Collections.emptySet();
+        } else {
+            return modules.stream()
+                    .map(ResolvedModule::reference)
+                    .map(ModuleReference::descriptor)
+                    .collect(Collectors.toSet());
+        }
+    }
+
+    Set<ResolvedModule> reads(ResolvedModule m) {
+        return Collections.unmodifiableSet(graph.get(m));
+    }
+
+    /**
+     * Returns a string describing this configuration.
+     *
+     * @return A string describing this configuration
+     */
+    @Override
+    public String toString() {
+        return modules().stream()
+                .map(ResolvedModule::name)
+                .collect(Collectors.joining(", "));
+    }
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Dependence.java b/jdk/src/java.base/share/classes/java/lang/module/Dependence.java
new file mode 100644
index 0000000..24538c0
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/Dependence.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.util.*;
+import java.util.stream.*;
+
+
+class Dependence {
+
+    private Dependence() { }
+
+    static <T> Stream<String> toStringStream(Set<T> s) {
+        return s.stream().map(e -> e.toString().toLowerCase());
+    }
+
+    static <M> String toString(Set<M> mods, String what) {
+        return (Stream.concat(toStringStream(mods), Stream.of(what)))
+                      .collect(Collectors.joining(" "));
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/FindException.java b/jdk/src/java.base/share/classes/java/lang/module/FindException.java
new file mode 100644
index 0000000..d76f293
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/FindException.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+/**
+ * Thrown by module finders when finding a module fails.
+ *
+ * @see ModuleFinder
+ * @since 9
+ */
+
+public class FindException extends RuntimeException {
+    private static final long serialVersionUID = -5817081036963388391L;
+
+    /**
+     * Constructs a {@code FindException} with no detail message.
+     */
+    public FindException() {
+    }
+
+    /**
+     * Constructs a {@code FindException} with the given detail
+     * message.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     */
+    public FindException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a {@code FindException} with the given cause.
+     *
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public FindException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a {@code FindException} with the given detail message
+     * and cause.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public FindException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/InvalidModuleDescriptorException.java b/jdk/src/java.base/share/classes/java/lang/module/InvalidModuleDescriptorException.java
new file mode 100644
index 0000000..981f23a
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/InvalidModuleDescriptorException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+/**
+ * Thrown when reading a module descriptor and the module descriptor is found
+ * to be malformed or otherwise cannot be interpreted as a module descriptor.
+ *
+ * @see ModuleDescriptor#read
+ * @since 9
+ */
+public class InvalidModuleDescriptorException extends RuntimeException {
+    private static final long serialVersionUID = 4863390386809347380L;
+
+    /**
+     * Constructs an {@code InvalidModuleDescriptorException} with no detail
+     * message.
+     */
+    public InvalidModuleDescriptorException() {
+    }
+
+    /**
+     * Constructs an {@code InvalidModuleDescriptorException} with the
+     * specified detail message.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     */
+    public InvalidModuleDescriptorException(String msg) {
+        super(msg);
+    }
+}
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
new file mode 100644
index 0000000..495f371
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
@@ -0,0 +1,1996 @@
+/*
+ * 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 java.lang.module;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+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.function.Supplier;
+
+import static jdk.internal.module.Checks.*;
+import static java.util.Objects.*;
+
+import jdk.internal.module.Checks;
+import jdk.internal.module.Hasher.DependencyHashes;
+
+
+/**
+ * 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>
+ *
+ * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
+ * multiple concurrent threads.</p>
+ *
+ * @since 9
+ * @see java.lang.reflect.Module
+ */
+
+public class ModuleDescriptor
+    implements Comparable<ModuleDescriptor>
+{
+
+    /**
+     * <p> A dependence upon a module </p>
+     *
+     * @see ModuleDescriptor#requires()
+     * @since 9
+     */
+
+    public final static class Requires
+        implements Comparable<Requires>
+    {
+
+        /**
+         * A modifier on a module dependence.
+         *
+         * @since 9
+         */
+        public static enum Modifier {
+
+            /**
+             * The dependence causes any module which depends on the <i>current
+             * module</i> to have an implicitly declared dependence on the module
+             * named by the {@code Requires}.
+             */
+            PUBLIC,
+
+            /**
+             * The dependence was not explicitly or implicitly declared in the
+             * source of the module declaration.
+             */
+            SYNTHETIC,
+
+            /**
+             * The dependence was implicitly declared in the source of the module
+             * declaration.
+             */
+            MANDATED;
+
+        }
+
+        private final Set<Modifier> mods;
+        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();
+            } else {
+                mods = check ? Collections.unmodifiableSet(EnumSet.copyOf(ms))
+                             : ms;
+            }
+            this.name = check ? requireModuleName(mn) : mn;
+        }
+
+        /**
+         * Returns the set of modifiers.
+         *
+         * @return A possibly-empty unmodifiable set of modifiers
+         */
+        public Set<Modifier> modifiers() {
+            return mods;
+        }
+
+        /**
+         * Return the module name.
+         *
+         * @return The module name
+         */
+        public String name() {
+            return name;
+        }
+
+        /**
+         * Compares this module dependence to another.
+         *
+         * <p> Two {@code Requires} objects are compared by comparing their
+         * module name lexicographically.  Where the module names are equal then
+         * the sets of modifiers are compared based on a value computed from the
+         * ordinal of each modifier. </p>
+         *
+         * @return A negative integer, zero, or a positive integer if this module
+         *         dependence is less than, equal to, or greater than the given
+         *         module dependence
+         */
+        @Override
+        public int compareTo(Requires that) {
+            int c = this.name().compareTo(that.name());
+            if (c != 0)
+                return c;
+            // same name, compare by modifiers
+            return Long.compare(this.modsValue(), that.modsValue());
+        }
+
+        /**
+         * Return a value for the modifiers to allow sets of modifiers to be
+         * compared.
+         */
+        private long modsValue() {
+            long value = 0;
+            for (Modifier m : mods) {
+                value += 1 << m.ordinal();
+            }
+            return value;
+        }
+
+        /**
+         * Tests this module dependence for equality with the given object.
+         *
+         * <p> If the given object is not a {@code Requires} then this method
+         * returns {@code false}. Two module dependence objects are equal if
+         * the module names are equal and set of modifiers are 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 Requires))
+                return false;
+            Requires that = (Requires)ob;
+            return (name.equals(that.name) && mods.equals(that.mods));
+        }
+
+        /**
+         * Computes a hash code for this module dependence.
+         *
+         * <p> The hash code is based upon the module name and modifiers. It
+         * satisfies the general contract of the {@link Object#hashCode
+         * Object.hashCode} method. </p>
+         *
+         * @return The hash-code value for this module dependence
+         */
+        @Override
+        public int hashCode() {
+            return name.hashCode() * 43 + mods.hashCode();
+        }
+
+        /**
+         * Returns a string describing module dependence.
+         *
+         * @return A string describing module dependence
+         */
+        @Override
+        public String toString() {
+            return Dependence.toString(mods, name);
+        }
+
+    }
+
+
+
+    /**
+     * <p> A module export, may be qualified or unqualified. </p>
+     *
+     * @see ModuleDescriptor#exports()
+     * @since 9
+     */
+
+    public final static class Exports {
+
+        private final String source;
+        private final Set<String> targets;  // empty if unqualified export
+
+        /**
+         * Constructs a qualified export.
+         */
+        private Exports(String source, Set<String> targets) {
+            this(source, targets, true);
+        }
+
+        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);
+            this.targets = targets;
+        }
+
+        /**
+         * Constructs an unqualified export.
+         */
+        private Exports(String source) {
+            this(source, true);
+        }
+        private Exports(String source, boolean check) {
+            this.source = check ? requirePackageName(source) : source;
+            this.targets = Collections.emptySet();
+        }
+
+        /**
+         * Returns {@code true} if this is a qualified export.
+         *
+         * @return {@code true} if this is a qualified export
+         */
+        public boolean isQualified() {
+            return !targets.isEmpty();
+        }
+
+        /**
+         * Returns the package name.
+         *
+         * @return The package name
+         */
+        public String source() {
+            return source;
+        }
+
+        /**
+         * For a qualified export, returns the non-empty and immutable set
+         * of the module names to which the package is exported. For an
+         * unqualified export, returns an empty set.
+         *
+         * @return The set of target module names or for an unqualified
+         *         export, an empty set
+         */
+        public Set<String> targets() {
+            return targets;
+        }
+
+        /**
+         * 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.
+         *
+         * @return The hash-code value for this module export
+         */
+        @Override
+        public int hashCode() {
+            return hash(source, targets);
+        }
+
+        /**
+         * Tests this module export for equality with the given object.
+         *
+         * <p> If the given object is not a {@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>
+         *
+         * <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 Exports))
+                return false;
+            Exports other = (Exports)ob;
+            return Objects.equals(this.source, other.source) &&
+                Objects.equals(this.targets, other.targets);
+        }
+
+        /**
+         * Returns a string describing module export.
+         *
+         * @return A string describing module export
+         */
+        @Override
+        public String toString() {
+            if (targets.isEmpty())
+                return source;
+            else
+                return source + " to " + targets;
+        }
+
+    }
+
+
+
+    /**
+     * <p> A service that a module provides one or more implementations of. </p>
+     *
+     * @see ModuleDescriptor#provides()
+     * @since 9
+     */
+
+    public final static class Provides {
+
+        private final String service;
+        private final Set<String> providers;
+
+        private Provides(String service, Set<String> providers) {
+            this(service, providers, true);
+        }
+
+        private Provides(String service, Set<String> providers, boolean check) {
+            this.service = check ? requireServiceTypeName(service) : service;
+            providers = check ? Collections.unmodifiableSet(new HashSet<>(providers))
+                              : Collections.unmodifiableSet(providers);
+            if (providers.isEmpty())
+                throw new IllegalArgumentException("Empty providers set");
+            if (check)
+                providers.forEach(Checks::requireServiceProviderName);
+            this.providers = providers;
+        }
+
+        /**
+         * Returns the fully qualified class name of the service type.
+         *
+         * @return The fully qualified class name of the service type.
+         */
+        public String service() { return service; }
+
+        /**
+         * Returns the set of the fully qualified class names of the providers.
+         *
+         * @return A non-empty and unmodifiable set of the fully qualified class
+         *         names of the providers.
+         */
+        public Set<String> providers() { return providers; }
+
+        /**
+         * Computes a hash code for this provides.
+         *
+         * <p> The hash code is based upon the service type and the set of
+         * providers. It satisfies the general contract of the {@link
+         * Object#hashCode Object.hashCode} method. </p>
+         *
+         * @return The hash-code value for this module provides
+         */
+        @Override
+        public int hashCode() {
+            return hash(service, providers);
+        }
+
+        /**
+         * Tests this provides for equality with the given object.
+         *
+         * <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>
+         *
+         * <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
+         *          {@code Provides} that is equal to this {@code Provides}
+         */
+        @Override
+        public boolean equals(Object ob) {
+            if (!(ob instanceof Provides))
+                return false;
+            Provides other = (Provides)ob;
+            return Objects.equals(this.service, other.service) &&
+                    Objects.equals(this.providers, other.providers);
+        }
+
+        /**
+         * Returns a string describing this provides.
+         *
+         * @return A string describing this provides
+         */
+        @Override
+        public String toString() {
+            return service + " with " + providers;
+        }
+
+    }
+
+
+
+    /**
+     * A module's version string.
+     *
+     * <p> A version string has three components: The version number itself, an
+     * optional pre-release version, and an optional build version.  Each
+     * component is sequence of tokens; each token is either a non-negative
+     * integer or a string.  Tokens are separated by the punctuation characters
+     * {@code '.'}, {@code '-'}, or {@code '+'}, or by transitions from a
+     * sequence of digits to a sequence of characters that are neither digits
+     * nor punctuation characters, or vice versa.
+     *
+     * <ul>
+     *
+     *   <li> The <i>version number</i> is a sequence of tokens separated by
+     *   {@code '.'} characters, terminated by the first {@code '-'} or {@code
+     *   '+'} character. </li>
+     *
+     *   <li> The <i>pre-release version</i> is a sequence of tokens separated
+     *   by {@code '.'} or {@code '-'} characters, terminated by the first
+     *   {@code '+'} character. </li>
+     *
+     *   <li> The <i>build version</i> is a sequence of tokens separated by
+     *   {@code '.'}, {@code '-'}, or {@code '+'} characters.
+     *
+     * </ul>
+     *
+     * <p> When comparing two version strings, the elements of their
+     * corresponding components are compared in pointwise fashion.  If one
+     * component is longer than the other, but otherwise equal to it, then the
+     * first component is considered the greater of the two; otherwise, if two
+     * corresponding elements are integers then they are compared as such;
+     * otherwise, at least one of the elements is a string, so the other is
+     * converted into a string if it is an integer and the two are compared
+     * lexicographically.  Trailing integer elements with the value zero are
+     * ignored.
+     *
+     * <p> Given two version strings, if their version numbers differ then the
+     * result of comparing them is the result of comparing their version
+     * numbers; otherwise, if one of them has a pre-release version but the
+     * other does not then the first is considered to precede the second,
+     * otherwise the result of comparing them is the result of comparing their
+     * pre-release versions; otherwise, the result of comparing them is the
+     * result of comparing their build versions.
+     *
+     * @see ModuleDescriptor#version()
+     * @since 9
+     */
+
+    public final static class Version
+        implements Comparable<Version>
+    {
+
+        private final String version;
+
+        // If Java had disjunctive types then we'd write List<Integer|String> here
+        //
+        private final List<Object> sequence;
+        private final List<Object> pre;
+        private final List<Object> build;
+
+        // Take a numeric token starting at position i
+        // Append it to the given list
+        // Return the index of the first character not taken
+        // Requires: s.charAt(i) is (decimal) numeric
+        //
+        private static int takeNumber(String s, int i, List<Object> acc) {
+            char c = s.charAt(i);
+            int d = (c - '0');
+            int n = s.length();
+            while (++i < n) {
+                c = s.charAt(i);
+                if (c >= '0' && c <= '9') {
+                    d = d * 10 + (c - '0');
+                    continue;
+                }
+                break;
+            }
+            acc.add(d);
+            return i;
+        }
+
+        // Take a string token starting at position i
+        // Append it to the given list
+        // Return the index of the first character not taken
+        // Requires: s.charAt(i) is not '.'
+        //
+        private static int takeString(String s, int i, List<Object> acc) {
+            int b = i;
+            int n = s.length();
+            while (++i < n) {
+                char c = s.charAt(i);
+                if (c != '.' && c != '-' && c != '+' && !(c >= '0' && c <= '9'))
+                    continue;
+                break;
+            }
+            acc.add(s.substring(b, i));
+            return i;
+        }
+
+        // Syntax: tok+ ( '-' tok+)? ( '+' tok+)?
+        // First token string is sequence, second is pre, third is build
+        // Tokens are separated by '.' or '-', or by changes between alpha & numeric
+        // Numeric tokens are compared as decimal integers
+        // Non-numeric tokens are compared lexicographically
+        // A version with a non-empty pre is less than a version with same seq but no pre
+        // Tokens in build may contain '-' and '+'
+        //
+        private Version(String v) {
+
+            if (v == null)
+                throw new IllegalArgumentException("Null version string");
+            int n = v.length();
+            if (n == 0)
+                throw new IllegalArgumentException("Empty version string");
+
+            int i = 0;
+            char c = v.charAt(i);
+            if (!(c >= '0' && c <= '9'))
+                throw new IllegalArgumentException(v
+                                                   + ": Version string does not start"
+                                                   + " with a number");
+
+            List<Object> sequence = new ArrayList<>(4);
+            List<Object> pre = new ArrayList<>(2);
+            List<Object> build = new ArrayList<>(2);
+
+            i = takeNumber(v, i, sequence);
+
+            while (i < n) {
+                c = v.charAt(i);
+                if (c == '.') {
+                    i++;
+                    continue;
+                }
+                if (c == '-' || c == '+') {
+                    i++;
+                    break;
+                }
+                if (c >= '0' && c <= '9')
+                    i = takeNumber(v, i, sequence);
+                else
+                    i = takeString(v, i, sequence);
+            }
+
+            if (c == '-' && i >= n)
+                throw new IllegalArgumentException(v + ": Empty pre-release");
+
+            while (i < n) {
+                c = v.charAt(i);
+                if (c >= '0' && c <= '9')
+                    i = takeNumber(v, i, pre);
+                else
+                    i = takeString(v, i, pre);
+                if (i >= n)
+                    break;
+                c = v.charAt(i);
+                if (c == '.' || c == '-') {
+                    i++;
+                    continue;
+                }
+                if (c == '+') {
+                    i++;
+                    break;
+                }
+            }
+
+            if (c == '+' && i >= n)
+                throw new IllegalArgumentException(v + ": Empty pre-release");
+
+            while (i < n) {
+                c = v.charAt(i);
+                if (c >= '0' && c <= '9')
+                    i = takeNumber(v, i, build);
+                else
+                    i = takeString(v, i, build);
+                if (i >= n)
+                    break;
+                c = v.charAt(i);
+                if (c == '.' || c == '-' || c == '+') {
+                    i++;
+                    continue;
+                }
+            }
+
+            this.version = v;
+            this.sequence = sequence;
+            this.pre = pre;
+            this.build = build;
+        }
+
+        /**
+         * Parses the given string as a version string.
+         *
+         * @param  v
+         *         The string to parse
+         *
+         * @return The resulting {@code Version}
+         *
+         * @throws IllegalArgumentException
+         *         If {@code v} is {@code null}, an empty string, or cannot be
+         *         parsed as a version string
+         */
+        public static Version parse(String v) {
+            return new Version(v);
+        }
+
+        @SuppressWarnings("unchecked")
+        private int cmp(Object o1, Object o2) {
+            return ((Comparable)o1).compareTo(o2);
+        }
+
+        private int compareTokens(List<Object> ts1, List<Object> ts2) {
+            int n = Math.min(ts1.size(), ts2.size());
+            for (int i = 0; i < n; i++) {
+                Object o1 = ts1.get(i);
+                Object o2 = ts2.get(i);
+                if ((o1 instanceof Integer && o2 instanceof Integer)
+                    || (o1 instanceof String && o2 instanceof String))
+                {
+                    int c = cmp(o1, o2);
+                    if (c == 0)
+                        continue;
+                    return c;
+                }
+                // Types differ, so convert number to string form
+                int c = o1.toString().compareTo(o2.toString());
+                if (c == 0)
+                    continue;
+                return c;
+            }
+            List<Object> rest = ts1.size() > ts2.size() ? ts1 : ts2;
+            int e = rest.size();
+            for (int i = n; i < e; i++) {
+                Object o = rest.get(i);
+                if (o instanceof Integer && ((Integer)o) == 0)
+                    continue;
+                return ts1.size() - ts2.size();
+            }
+            return 0;
+        }
+
+        /**
+         * Compares this module version to another module version. Module
+         * versions are compared as described in the class description.
+         *
+         * @param that
+         *        The module version to compare
+         *
+         * @return A negative integer, zero, or a positive integer as this
+         *         module version is less than, equal to, or greater than the
+         *         given module version
+         */
+        @Override
+        public int compareTo(Version that) {
+            int c = compareTokens(this.sequence, that.sequence);
+            if (c != 0) return c;
+            if (this.pre.isEmpty()) {
+                if (!that.pre.isEmpty()) return +1;
+            } else {
+                if (that.pre.isEmpty()) return -1;
+            }
+            c = compareTokens(this.pre, that.pre);
+            if (c != 0) return c;
+            return compareTokens(this.build, that.build);
+        }
+
+        /**
+         * Tests this module version for equality with the given object.
+         *
+         * <p> If the given object is not a {@code Version} then this method
+         * returns {@code false}. Two module version are equal if their
+         * corresponding components are 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
+         *          reference that is equal to this module reference
+         */
+        @Override
+        public boolean equals(Object ob) {
+            if (!(ob instanceof Version))
+                return false;
+            return compareTo((Version)ob) == 0;
+        }
+
+        /**
+         * Computes a hash code for this module version.
+         *
+         * <p> The hash code is based upon the components of the version and
+         * satisfies the general contract of the {@link Object#hashCode
+         * Object.hashCode} method. </p>
+         *
+         * @return The hash-code value for this module version
+         */
+        @Override
+        public int hashCode() {
+            return version.hashCode();
+        }
+
+        /**
+         * Returns the string from which this version was parsed.
+         *
+         * @return The string from which this version was parsed.
+         */
+        @Override
+        public String toString() {
+            return version;
+        }
+
+    }
+
+
+
+    // 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;
+
+    // Indicates if synthesised for a JAR file found on the module path
+    private final boolean automatic;
+
+    // Not generated from a module-info.java
+    private final boolean synthetic;
+
+    // "Extended" information, added post-compilation by tools
+    private final Version version;
+    private final String mainClass;
+    private final String osName;
+    private final String osArch;
+    private final String osVersion;
+    private final Set<String> conceals;
+    private final Set<String> packages;
+    private final DependencyHashes hashes;
+
+    private ModuleDescriptor(String name,
+                             boolean automatic,
+                             boolean synthetic,
+                             Map<String, Requires> requires,
+                             Set<String> uses,
+                             Map<String, Exports> exports,
+                             Map<String, Provides> provides,
+                             Version version,
+                             String mainClass,
+                             String osName,
+                             String osArch,
+                             String osVersion,
+                             Set<String> conceals,
+                             DependencyHashes hashes)
+    {
+
+        this.name = name;
+        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);
+
+        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.uses = emptyOrUnmodifiableSet(uses);
+        this.provides = emptyOrUnmodifiableMap(provides);
+
+        this.version = version;
+        this.mainClass = mainClass;
+        this.osName = osName;
+        this.osArch = osArch;
+        this.osVersion = osVersion;
+        this.hashes = hashes;
+
+        assert !exports.keySet().stream().anyMatch(conceals::contains)
+            : "Module " + name + ": Package sets overlap";
+        this.conceals = emptyOrUnmodifiableSet(conceals);
+        this.packages = computePackages(this.exports, this.conceals);
+    }
+
+    /**
+     * Clones the given module descriptor with an augmented set of packages
+     */
+    ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
+        this.name = md.name;
+        this.automatic = md.automatic;
+        this.synthetic = md.synthetic;
+
+        this.requires = md.requires;
+        this.exports = md.exports;
+        this.uses = md.uses;
+        this.provides = md.provides;
+
+        this.version = md.version;
+        this.mainClass = md.mainClass;
+        this.osName = md.osName;
+        this.osArch = md.osArch;
+        this.osVersion = md.osVersion;
+        this.hashes = null; // need to ignore
+
+        this.packages = emptyOrUnmodifiableSet(pkgs);
+        this.conceals = computeConcealedPackages(this.exports, this.packages);
+    }
+
+    /**
+     * Creates a module descriptor from its components. This method is intended
+     * for use by the jlink plugin.
+     */
+    ModuleDescriptor(String name,
+                     boolean automatic,
+                     boolean synthetic,
+                     Set<Requires> requires,
+                     Set<String> uses,
+                     Set<Exports> exports,
+                     Map<String, Provides> provides,
+                     Version version,
+                     String mainClass,
+                     String osName,
+                     String osArch,
+                     String osVersion,
+                     Set<String> conceals,
+                     Set<String> packages) {
+        this.name = name;
+        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.conceals = Collections.unmodifiableSet(conceals);
+        this.packages = Collections.unmodifiableSet(packages);
+
+        this.version = version;
+        this.mainClass = mainClass;
+        this.osName = osName;
+        this.osArch = osArch;
+        this.osVersion = osVersion;
+        this.hashes = null;
+    }
+
+    /**
+     * <p> The module name. </p>
+     *
+     * @return The module name
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * <p> Returns {@code true} if this is an automatic module. </p>
+     *
+     * <p> An automatic module is defined implicitly rather than explicitly
+     * and therefore does not have a module declaration. JAR files located on
+     * the application module path, or by the {@link ModuleFinder} returned by
+     * {@link ModuleFinder#of(java.nio.file.Path[]) ModuleFinder.of}, are
+     * treated as automatic modules if they do have not have a module
+     * declaration. </p>
+     *
+     * @return  {@code true} if this is an automatic module
+     */
+    public boolean isAutomatic() {
+        return automatic;
+    }
+
+    /**
+     * <p> Returns {@code true} if this module descriptor was not generated
+     * from an explicit module declaration ({@code module-info.java})
+     * or an implicit module declaration (an {@link #isAutomatic() automatic}
+     * module). </p>
+     *
+     * @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;
+    }
+
+    /**
+     * <p> The dependences of this module. </p>
+     *
+     * @return  A possibly-empty unmodifiable set of {@link Requires} objects
+     */
+    public Set<Requires> requires() {
+        return requires;
+    }
+
+    /**
+     * <p> The service dependences of this module. </p>
+     *
+     * @return  A possibly-empty unmodifiable set of the fully qualified class
+     *          names of the service types used
+     */
+    public Set<String> uses() {
+        return uses;
+    }
+
+    /**
+     * <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.
+     */
+    public Map<String, 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
+     */
+    public Optional<Version> version() {
+        return Optional.ofNullable(version);
+    }
+
+    /**
+     * Returns a string containing this module's name and, if present, its
+     * version.
+     *
+     * @return A string containing this module's name and, if present, its
+     *         version.
+     */
+    public String toNameAndVersion() {
+        if (version != null) {
+            return name() + "@" + version;
+        } else {
+            return name();
+        }
+    }
+
+    /**
+     * Returns the module's main class.
+     *
+     * @return The fully qualified class name of this module's main class
+     */
+    public Optional<String> mainClass() {
+        return Optional.ofNullable(mainClass);
+    }
+
+    /**
+     * Returns the operating system name if this module is operating system
+     * specific.
+     *
+     * @return The operating system name or an empty {@code Optional}
+     *         if this module is not operating system specific
+     */
+    public Optional<String> osName() {
+        return Optional.ofNullable(osName);
+    }
+
+    /**
+     * Returns the operating system architecture if this module is operating
+     * system architecture specific.
+     *
+     * @return The operating system architecture or an empty {@code Optional}
+     *         if this module is not operating system architecture specific
+     */
+    public Optional<String> osArch() {
+        return Optional.ofNullable(osArch);
+    }
+
+    /**
+     * Returns the operating system version if this module is operating
+     * system version specific.
+     *
+     * @return The operating system version or an empty {@code Optional}
+     *         if this module is not operating system version specific
+     */
+    public Optional<String> osVersion() {
+        return Optional.ofNullable(osVersion);
+    }
+
+    /**
+     * Returns the names of the packages defined in, but not exported by, this
+     * module.
+     *
+     * @return A possibly-empty unmodifiable set of the concealed packages
+     */
+    public Set<String> conceals() {
+        return 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
+     */
+    public Set<String> packages() {
+        return packages;
+    }
+
+    /**
+     * Returns the object with the hashes of the dependences.
+     */
+    Optional<DependencyHashes> hashes() {
+        return Optional.ofNullable(hashes);
+    }
+
+
+    /**
+     * A builder used for building {@link ModuleDescriptor} objects.
+     *
+     * <p> Example usage: </p>
+     *
+     * <pre>{@code
+     *     ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1")
+     *         .requires("m2")
+     *         .exports("p")
+     *         .build();
+     * }</pre>
+     *
+     * @apiNote A {@code Builder} cannot be used to create an {@link
+     * ModuleDescriptor#isAutomatic() automatic} or a {@link
+     * ModuleDescriptor#isSynthetic() synthetic} module.
+     *
+     * @since 9
+     */
+    public static final class Builder {
+
+        final String name;
+        final 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, Provides> provides = new HashMap<>();
+        Set<String> conceals = Collections.emptySet();
+        Version version;
+        String osName;
+        String osArch;
+        String osVersion;
+        String mainClass;
+        DependencyHashes hashes;
+
+        /**
+         * 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
+         */
+        public Builder(String name) {
+            this(name, false);
+        }
+
+        /* package */ Builder(String name, boolean automatic) {
+            this.name = requireModuleName(name);
+            this.automatic = automatic;
+        }
+
+        /**
+         * Adds a dependence on a module.
+         *
+         * @param  req
+         *         The dependence
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the dependence is on the module that this builder was
+         *         initialized to build
+         * @throws IllegalStateException
+         *         If the dependence on the module has already been declared
+         */
+        public Builder requires(Requires req) {
+            String mn = req.name();
+            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, req);
+            return this;
+        }
+
+        /**
+         * Adds a dependence on a module with the given (and possibly empty)
+         * set of modifiers.
+         *
+         * @param  mods
+         *         The set of modifiers
+         * @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(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;
+        }
+
+        /**
+         * Adds a dependence on a module with an empty set of modifiers.
+         *
+         * @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(String mn) {
+            return requires(EnumSet.noneOf(Requires.Modifier.class), mn);
+        }
+
+        /**
+         * 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
+         *         The export
+         *
+         * @return This builder
+         *
+         * @throws IllegalStateException
+         *         If the package is already declared as an exported or
+         *         concealed package
+         */
+        public Builder exports(Exports e) {
+            String pn = e.source();
+            ensureNotExportedOrConcealed(pn);
+            exports.put(pn, e);
+            return this;
+        }
+
+        /**
+         * Adds an export 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 an exported or
+         *         concealed package
+         */
+        public Builder exports(String pn, Set<String> targets) {
+            ensureNotExportedOrConcealed(pn);
+            exports.put(pn, new Exports(pn, targets)); // checks pn and targets
+            return this;
+        }
+
+        /**
+         * 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.
+         *
+         * @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 an exported or
+         *         concealed package
+         */
+        public Builder exports(String pn) {
+            ensureNotExportedOrConcealed(pn);
+            exports.put(pn, new Exports(pn)); // checks pn
+            return this;
+        }
+
+        // Used by ModuleInfo, after a packageFinder is invoked
+        /* package */ Set<String> exportedPackages() {
+            return exports.keySet();
+        }
+
+        /**
+         * Provides a service with one or more implementations.
+         *
+         * @param  p
+         *         The provides
+         *
+         * @return This builder
+         *
+         * @throws IllegalStateException
+         *         If the providers for the service type have already been
+         *         declared
+         */
+        public Builder provides(Provides p) {
+            String st = p.service();
+            if (provides.containsKey(st))
+                throw new IllegalStateException("Providers of service "
+                                                + st + " already declared");
+            provides.put(st, p);
+            return this;
+        }
+
+        /**
+         * Provides service {@code st} with implementations {@code pcs}.
+         *
+         * @param  st
+         *         The service type
+         * @param  pcs
+         *         The set of provider 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
+         *         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))
+                throw new IllegalStateException("Providers of service "
+                                                + st + " already declared");
+            provides.put(st, new Provides(st, pcs)); // checks st and pcs
+            return this;
+        }
+
+        /**
+         * Provides service {@code st} with implementation {@code pc}.
+         *
+         * @param  st
+         *         The service type
+         * @param  pc
+         *         The provider class name
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the service type or the provider class name is {@code
+         *         null} or is not a legal Java identifier
+         * @throws IllegalStateException
+         *         If the providers for the service type have already been
+         *         declared
+         */
+        public Builder provides(String st, String pc) {
+            return provides(st, Collections.singleton(pc));
+        }
+
+        /**
+         * Adds a set of (possible empty) concealed packages.
+         *
+         * @param  pns
+         *         The set of package names of the concealed packages
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         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
+         */
+        public Builder conceals(Set<String> pns) {
+            pns.forEach(this::conceals);
+            return this;
+        }
+
+        /**
+         * Adds a concealed 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 concealed or exported
+         *         package
+         */
+        public Builder conceals(String pn) {
+            Checks.requirePackageName(pn);
+            ensureNotExportedOrConcealed(pn);
+            if (conceals.isEmpty())
+                conceals = new HashSet<>();
+            conceals.add(pn);
+            return this;
+        }
+
+        /**
+         * Sets the module version.
+         *
+         * @param  v
+         *         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;
+        }
+
+        /**
+         * Sets the module version.
+         *
+         * @param  v
+         *         The version string to parse
+         *
+         * @return This builder
+         *
+         * @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;
+        }
+
+        /**
+         * Sets the module main class.
+         *
+         * @param  mc
+         *         The module main class
+         *
+         * @return This builder
+         *
+         * @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;
+        }
+
+        /**
+         * Sets the operating system name.
+         *
+         * @param  name
+         *         The operating system name
+         *
+         * @return This builder
+         *
+         * @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;
+            return this;
+        }
+
+        /**
+         * Sets the operating system architecture.
+         *
+         * @param  arch
+         *         The operating system architecture
+         *
+         * @return This builder
+         *
+         * @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;
+            return this;
+        }
+
+        /**
+         * Sets the operating system version.
+         *
+         * @param  version
+         *         The operating system version
+         *
+         * @return This builder
+         *
+         * @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;
+            return this;
+        }
+
+        /* package */ Builder hashes(DependencyHashes hashes) {
+            this.hashes = hashes;
+            return this;
+        }
+
+
+        /* package */ Builder synthetic(boolean v) {
+            this.synthetic = v;
+            return this;
+        }
+
+        /**
+         * Builds and returns a {@code ModuleDescriptor} from its components.
+         *
+         * @return The module descriptor
+         */
+        public ModuleDescriptor build() {
+            assert name != null;
+
+            return new ModuleDescriptor(name,
+                                        automatic,
+                                        synthetic,
+                                        requires,
+                                        uses,
+                                        exports,
+                                        provides,
+                                        version,
+                                        mainClass,
+                                        osName,
+                                        osArch,
+                                        osVersion,
+                                        conceals,
+                                        hashes);
+        }
+
+    }
+
+
+    /**
+     * Compares this module descriptor to another.
+     *
+     * <p> Two {@code ModuleDescriptor} objects are compared by comparing their
+     * module name lexicographically.  Where the module names are equal then
+     * the versions, if present, are compared. </p>
+     *
+     * @apiNote For now, the natural ordering is not consistent with equals.
+     * If two module descriptors have equal module names, equal versions if
+     * present, but their corresponding components are not equal, then they
+     * will be considered equal by this method.
+     *
+     * @param  that
+     *         The object to which this module descriptor is to be compared
+     *
+     * @return A negative integer, zero, or a positive integer if this module
+     *         descriptor is less than, equal to, or greater than the given
+     *         module descriptor
+     */
+    @Override
+    public int compareTo(ModuleDescriptor that) {
+        int c = this.name().compareTo(that.name());
+        if (c != 0) return c;
+        if (version == null) {
+            if (that.version == null)
+                return 0;
+            return -1;
+        }
+        if (that.version == null)
+            return +1;
+        return version.compareTo(that.version);
+    }
+
+    /**
+     * Tests this module descriptor for equality with the given object.
+     *
+     * <p> If the given object is not a {@code ModuleDescriptor} then this
+     * method returns {@code false}. Two module descriptors are equal if each
+     * of their corresponding components 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
+     *          descriptor that is equal to this module descriptor
+     */
+    @Override
+    public boolean equals(Object ob) {
+        if (ob == this)
+            return true;
+        if (!(ob instanceof ModuleDescriptor))
+            return false;
+        ModuleDescriptor that = (ModuleDescriptor)ob;
+        return (name.equals(that.name)
+                && automatic == that.automatic
+                && synthetic == that.synthetic
+                && requires.equals(that.requires)
+                && uses.equals(that.uses)
+                && exports.equals(that.exports)
+                && provides.equals(that.provides)
+                && Objects.equals(version, that.version)
+                && Objects.equals(mainClass, that.mainClass)
+                && Objects.equals(osName, that.osName)
+                && Objects.equals(osArch, that.osArch)
+                && Objects.equals(osVersion, that.osVersion)
+                && Objects.equals(conceals, that.conceals)
+                && Objects.equals(hashes, that.hashes));
+    }
+
+    private transient int hash;  // cached hash code
+
+    /**
+     * Computes a hash code for this module descriptor.
+     *
+     * <p> The hash code is based upon the components of the module descriptor,
+     * and satisfies the general contract of the {@link Object#hashCode
+     * Object.hashCode} method. </p>
+     *
+     * @return The hash-code value for this module descriptor
+     */
+    @Override
+    public int hashCode() {
+        int hc = hash;
+        if (hc == 0) {
+            hc = name.hashCode();
+            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 + provides.hashCode();
+            hc = hc * 43 + Objects.hashCode(version);
+            hc = hc * 43 + Objects.hashCode(mainClass);
+            hc = hc * 43 + Objects.hashCode(osName);
+            hc = hc * 43 + Objects.hashCode(osArch);
+            hc = hc * 43 + Objects.hashCode(osVersion);
+            hc = hc * 43 + Objects.hashCode(conceals);
+            hc = hc * 43 + Objects.hashCode(hashes);
+            if (hc != 0) hash = hc;
+        }
+        return hc;
+    }
+
+    /**
+     * Returns a string describing this descriptor.
+     *
+     * @return A string describing this descriptor
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        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 (!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(" }");
+        return sb.toString();
+    }
+
+    /**
+     * 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>
+     *
+     * <p> If there are bytes following the module descriptor then it is
+     * implementation specific as to whether those bytes are read, ignored,
+     * or reported as an {@code InvalidModuleDescriptorException}. If this
+     * method fails with an {@code InvalidModuleDescriptorException} or {@code
+     * IOException} then it may do so after some, but not all, bytes have
+     * been read from the input stream. It is strongly recommended that the
+     * stream be promptly closed and discarded if an exception occurs. </p>
+     *
+     * @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.
+     *
+     * @param  in
+     *         The input stream
+     * @param  packageFinder
+     *         A supplier that can produce a set of package names
+     *
+     * @return The module descriptor
+     *
+     * @throws InvalidModuleDescriptorException
+     *         If an invalid module descriptor is detected
+     * @throws IOException
+     *         If an I/O error occurs reading from the input stream or {@code
+     *         UncheckedIOException} is thrown by the package finder
+     */
+    public static ModuleDescriptor read(InputStream in,
+                                        Supplier<Set<String>> packageFinder)
+        throws IOException
+    {
+        return ModuleInfo.read(in, requireNonNull(packageFinder));
+    }
+
+    /**
+     * Reads the binary form of a module declaration from an input stream
+     * as a module descriptor.
+     *
+     * @param  in
+     *         The input stream
+     *
+     * @return The module descriptor
+     *
+     * @throws InvalidModuleDescriptorException
+     *         If an invalid module descriptor is detected
+     * @throws IOException
+     *         If an I/O error occurs reading from the input stream
+     */
+    public static ModuleDescriptor read(InputStream in) throws IOException {
+        return ModuleInfo.read(in, null);
+    }
+
+    /**
+     * Reads the binary form of a module declaration from a byte buffer
+     * 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>
+     *
+     * <p> The module descriptor is read from the buffer stating at index
+     * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
+     * position} when this method is invoked. Upon return the buffer's position
+     * will be equal to {@code p + n} where {@code n} is the number of bytes
+     * read from the buffer. </p>
+     *
+     * <p> If there are bytes following the module descriptor then it is
+     * implementation specific as to whether those bytes are read, ignored,
+     * or reported as an {@code InvalidModuleDescriptorException}. If this
+     * method fails with an {@code InvalidModuleDescriptorException} then it
+     * may do so after some, but not all, bytes have been read. </p>
+     *
+     * @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.
+     *
+     * @param  bb
+     *         The byte buffer
+     * @param  packageFinder
+     *         A supplier that can produce a set of package names
+     *
+     * @return The module descriptor
+     *
+     * @throws InvalidModuleDescriptorException
+     *         If an invalid module descriptor is detected
+     */
+    public static ModuleDescriptor read(ByteBuffer bb,
+                                        Supplier<Set<String>> packageFinder)
+    {
+        return ModuleInfo.read(bb, requireNonNull(packageFinder));
+    }
+
+    /**
+     * Reads the binary form of a module declaration from a byte buffer
+     * as a module descriptor.
+     *
+     * @param  bb
+     *         The byte buffer
+     *
+     * @return The module descriptor
+     *
+     * @throws InvalidModuleDescriptorException
+     *         If an invalid module descriptor is detected
+     */
+    public static ModuleDescriptor read(ByteBuffer bb) {
+        return ModuleInfo.read(bb, null);
+    }
+
+
+    /**
+     * Computes the set of packages from exports and concealed packages.
+     * It returns the concealed packages set if there is no exported package.
+     */
+    private static Set<String> computePackages(Set<Exports> exports,
+                                               Set<String> conceals)
+    {
+        if (exports.isEmpty())
+            return conceals;
+
+        Set<String> pkgs = new HashSet<>(conceals);
+        exports.stream().map(Exports::source).forEach(pkgs::add);
+        return emptyOrUnmodifiableSet(pkgs);
+    }
+
+    /**
+     * Computes the set of concealed packages from exports and all packages.
+     * It returns the packages set if there are no exported packages.
+     */
+    private static Set<String> computeConcealedPackages(Set<Exports> exports,
+                                                        Set<String> pkgs)
+    {
+        if (exports.isEmpty())
+            return pkgs;
+
+        Set<String> conceals = new HashSet<>(pkgs);
+        exports.stream().map(Exports::source).forEach(conceals::remove);
+        return emptyOrUnmodifiableSet(conceals);
+    }
+
+    private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
+        if (map.isEmpty()) {
+            return Collections.emptyMap();
+        } else if (map.size() == 1) {
+            Map.Entry<K, V> entry = map.entrySet().iterator().next();
+            return Collections.singletonMap(entry.getKey(), entry.getValue());
+        } else {
+            return Collections.unmodifiableMap(map);
+        }
+    }
+
+    private static <T> Set<T> emptyOrUnmodifiableSet(Set<T> set) {
+        if (set.isEmpty()) {
+            return Collections.emptySet();
+        } else if (set.size() == 1) {
+            return Collections.singleton(set.iterator().next());
+        } else {
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    static {
+        /**
+         * Setup the shared secret to allow code in other packages create
+         * ModuleDescriptor and associated objects directly.
+         */
+        jdk.internal.misc.SharedSecrets
+            .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
+                @Override
+                public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
+                    return new Requires(ms, mn, false);
+                }
+
+                @Override
+                public Exports newExports(String source, Set<String> targets) {
+                    return new Exports(source, targets, false);
+                }
+
+                @Override
+                public Exports newExports(String source) {
+                    return new Exports(source, false);
+                }
+
+                @Override
+                public Provides newProvides(String service, Set<String> providers) {
+                    return new Provides(service, providers, false);
+                }
+
+                @Override
+                public Version newVersion(String v) {
+                    return new Version(v);
+                }
+
+                @Override
+                public ModuleDescriptor newModuleDescriptor(ModuleDescriptor md,
+                                                            Set<String> pkgs) {
+                    return new ModuleDescriptor(md, pkgs);
+                }
+
+                @Override
+                public ModuleDescriptor newModuleDescriptor(String name,
+                                                            boolean automatic,
+                                                            boolean synthetic,
+                                                            Set<Requires> requires,
+                                                            Set<String> uses, Set<Exports> exports,
+                                                            Map<String, Provides> provides,
+                                                            Version version,
+                                                            String mainClass,
+                                                            String osName,
+                                                            String osArch,
+                                                            String osVersion,
+                                                            Set<String> conceals,
+                                                            Set<String> packages) {
+                    return new ModuleDescriptor(name,
+                                                automatic,
+                                                synthetic,
+                                                requires,
+                                                uses,
+                                                exports,
+                                                provides,
+                                                version,
+                                                mainClass,
+                                                osName,
+                                                osArch,
+                                                osVersion,
+                                                conceals,
+                                                packages);
+                }
+            });
+    }
+
+}
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
new file mode 100644
index 0000000..83d8fc5
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
@@ -0,0 +1,362 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A finder of modules. A {@code ModuleFinder} is used to find modules during
+ * <a href="Configuration.html#resolution">resolution</a> or
+ * <a href="Configuration.html#servicebinding">service binding</a>.
+ *
+ * <p> A {@code ModuleFinder} can only find one module with a given name. A
+ * {@code ModuleFinder} that finds modules in a sequence of directories, for
+ * example, will locate the first occurrence of a module of a given name and
+ * will ignore other modules of that name that appear in directories later in
+ * the sequence. </p>
+ *
+ * <p> Example usage: </p>
+ *
+ * <pre>{@code
+ *     Path dir1, dir2, dir3;
+ *
+ *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
+ *
+ *     Optional<ModuleReference> omref = finder.find("jdk.foo");
+ *     if (omref.isPresent()) { ... }
+ *
+ * }</pre>
+ *
+ * <p> The {@link #find(String) find} and {@link #findAll() findAll} methods
+ * defined here can fail for several reasons. These include include I/O errors,
+ * errors detected parsing a module descriptor ({@code module-info.class}), or
+ * in the case of {@code ModuleFinder} returned by {@link #of ModuleFinder.of},
+ * that two or more modules with the same name are found in a directory.
+ * When an error is detected then these methods throw {@link FindException
+ * FindException} with an appropriate {@link Throwable#getCause cause}.
+ * The behavior of a {@code ModuleFinder} after a {@code FindException} is
+ * thrown is undefined. For example, invoking {@code find} after an exception
+ * is thrown may or may not scan the same modules that lead to the exception.
+ * It is recommended that a module finder be discarded after an exception is
+ * thrown. </p>
+ *
+ * <p> A {@code ModuleFinder} is not required to be thread safe. </p>
+ *
+ * @since 9
+ */
+
+public interface ModuleFinder {
+
+    /**
+     * Finds a reference to a module of a given name.
+     *
+     * <p> A {@code ModuleFinder} provides a consistent view of the
+     * modules that it locates. If {@code find} is invoked several times to
+     * locate the same module (by name) then it will return the same result
+     * each time. If a module is located then it is guaranteed to be a member
+     * of the set of modules returned by the {@link #findAll() findAll}
+     * method. </p>
+     *
+     * @param  name
+     *         The name of the module to find
+     *
+     * @return A reference to a module with the given name or an empty
+     *         {@code Optional} if not found
+     *
+     * @throws FindException
+     *         If an error occurs finding the module
+     *
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    Optional<ModuleReference> find(String name);
+
+    /**
+     * Returns the set of all module references that this finder can locate.
+     *
+     * <p> A {@code ModuleFinder} provides a consistent view of the modules
+     * that it locates. If {@link #findAll() findAll} is invoked several times
+     * then it will return the same (equals) result each time. For each {@code
+     * ModuleReference} element in the returned set then it is guaranteed that
+     * {@link #find find} will locate the {@code ModuleReference} if invoked
+     * to find that module. </p>
+     *
+     * @apiNote This is important to have for methods such as {@link
+     * Configuration#resolveRequiresAndUses resolveRequiresAndUses} that need
+     * to scan the module path to find modules that provide a specific service.
+     *
+     * @return The set of all module references that this finder locates
+     *
+     * @throws FindException
+     *         If an error occurs finding all modules
+     *
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    Set<ModuleReference> findAll();
+
+    /**
+     * Returns a module finder that locates the <em>system modules</em>. The
+     * system modules are typically linked into the Java run-time image.
+     * The module finder will always find {@code java.base}.
+     *
+     * <p> If there is a security manager set then its {@link
+     * SecurityManager#checkPermission(Permission) checkPermission} method is
+     * invoked to check that the caller has been granted {@link FilePermission}
+     * to recursively read the directory that is the value of the system
+     * property {@code java.home}. </p>
+     *
+     * @return A {@code ModuleFinder} that locates the system modules
+     *
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    static ModuleFinder ofSystem() {
+        String home;
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            PrivilegedAction<String> pa = () -> System.getProperty("java.home");
+            home = AccessController.doPrivileged(pa);
+            Permission p = new FilePermission(home + File.separator + "-", "read");
+            sm.checkPermission(p);
+        } else {
+            home = System.getProperty("java.home");
+        }
+
+        Path modules = Paths.get(home, "lib", "modules");
+        if (Files.isRegularFile(modules)) {
+            return new SystemModuleFinder();
+        } else {
+            Path mlib = Paths.get(home, "modules");
+            if (Files.isDirectory(mlib)) {
+                return of(mlib);
+            } else {
+                throw new InternalError("Unable to detect the run-time image");
+            }
+        }
+    }
+
+    /**
+     * Returns a module finder that locates modules on the file system by
+     * searching a sequence of directories and/or packaged modules.
+     *
+     * Each element in the given array is one of:
+     * <ol>
+     *     <li><p> A path to a directory of modules.</p></li>
+     *     <li><p> A path to the <em>top-level</em> directory of an
+     *         <em>exploded module</em>. </p></li>
+     *     <li><p> A path to a <em>packaged module</em>. </p></li>
+     * </ol>
+     *
+     * The module finder locates modules by searching each directory, exploded
+     * module, or packaged module in array index order. It finds the first
+     * occurrence of a module with a given name and ignores other modules of
+     * that name that appear later in the sequence.
+     *
+     * <p> If an element is a path to a directory of modules then each entry in
+     * the directory is a packaged module or the top-level directory of an
+     * exploded module. The module finder's {@link #find(String) find} or
+     * {@link #findAll() findAll} methods throw {@link FindException} if a
+     * directory containing more than one module with the same name is
+     * encountered. </p>
+     *
+     * <p> If an element in the array is a path to a directory, and that
+     * directory contains a file named {@code module-info.class}, then the
+     * directory is treated as an exploded module rather than a directory of
+     * modules. </p>
+     *
+     * <p> The module finder returned by this method supports modules that are
+     * packaged as JAR files. A JAR file with a {@code module-info.class} in
+     * the top-level directory of the JAR file is a modular JAR and is an
+     * <em>explicit module</em>. A JAR file that does not have a {@code
+     * module-info.class} in the top-level directory is an {@link
+     * ModuleDescriptor#isAutomatic automatic} module. The {@link
+     * ModuleDescriptor} for an automatic module is created as follows:
+     *
+     * <ul>
+     *
+     *     <li><p> The module {@link ModuleDescriptor#name() name}, and {@link
+     *     ModuleDescriptor#version() version} if applicable, is derived from
+     *     the file name of the JAR file as follows: </p>
+     *
+     *     <ul>
+     *
+     *         <li><p> The {@code .jar} suffix is removed. </p></li>
+     *
+     *         <li><p> If the name matches the regular expression {@code
+     *         "-(\\d+(\\.|$))"} then the module name will be derived from the
+     *         subsequence proceeding the hyphen of the first occurrence. The
+     *         subsequence after the hyphen is parsed as a {@link
+     *         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> 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
+     *         named {@code foo-1.2.3-SNAPSHOT.jar} will derive a module name
+     *         {@code foo} and {@code 1.2.3-SNAPSHOT} as the version. </p></li>
+     *
+     *     </ul></li>
+     *
+     *     <li><p> It {@link ModuleDescriptor#requires() requires} {@code
+     *     java.base}. </p></li>
+     *
+     *     <li><p> All entries in the JAR file with names ending with {@code
+     *     .class} are assumed to be class files where the name corresponds
+     *     to the fully qualified name of the class. The packages of all
+     *     classes are {@link ModuleDescriptor#exports() exported}. </p></li>
+     *
+     *     <li><p> The contents of all entries starting with {@code
+     *     META-INF/services/} are assumed to be service configuration files
+     *     (see {@link java.util.ServiceLoader}). The name of the file
+     *     (that follows {@code META-INF/services/}) is assumed to be the
+     *     fully-qualified binary name of a service type. The entries in the
+     *     file are assumed to be the fully-qualified binary names of
+     *     provider classes. </p></li>
+     *
+     *     <li><p> If the JAR file has a {@code Main-Class} attribute in its
+     *     main manifest then its value is the {@link
+     *     ModuleDescriptor#mainClass() main class}. </p></li>
+     *
+     * </ul>
+     *
+     * <p> In addition to JAR files, an implementation may also support modules
+     * that are packaged in other implementation specific module formats. As
+     * with automatic modules, the contents of a packaged or exploded module
+     * may need to be <em>scanned</em> in order to determine the packages in
+     * the module. If a {@code .class} file that corresponds to a class in an
+     * unnamed package is encountered then {@code FindException} is thrown. </p>
+     *
+     * <p> Finders created by this method are lazy and do not eagerly check
+     * that the given file paths are directories or packaged modules.
+     * Consequently, the {@code find} or {@code findAll} methods will only
+     * fail if invoking these methods results in searching a directory or
+     * packaged module and an error is encountered. Paths to files that do not
+     * exist are ignored. </p>
+     *
+     * @param entries
+     *        A possibly-empty array of paths to directories of modules
+     *        or paths to packaged or exploded modules
+     *
+     * @return A {@code ModuleFinder} that locates modules on the file system
+     */
+    static ModuleFinder of(Path... entries) {
+        return new ModulePath(entries);
+    }
+
+    /**
+     * Returns a module finder that is the equivalent to composing two
+     * module finders. The resulting finder will locate modules references
+     * using {@code first}; if not found then it will attempt to locate module
+     * references using {@code second}.
+     *
+     * <p> The {@link #findAll() findAll} method of the resulting module finder
+     * will locate all modules located by the first module finder. It will
+     * also locate all modules located by the second module finder that are not
+     * located by the first module finder. </p>
+     *
+     * @apiNote This method will eventually be changed to take a sequence of
+     *          module finders.
+     *
+     * @param first
+     *        The first module finder
+     * @param second
+     *        The second module finder
+     *
+     * @return A {@code ModuleFinder} that composes two module finders
+     */
+    static ModuleFinder compose(ModuleFinder first, ModuleFinder second) {
+        Objects.requireNonNull(first);
+        Objects.requireNonNull(second);
+
+        return new ModuleFinder() {
+            Set<ModuleReference> allModules;
+
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                Optional<ModuleReference> om = first.find(name);
+                if (!om.isPresent())
+                    om = second.find(name);
+                return om;
+            }
+            @Override
+            public Set<ModuleReference> findAll() {
+                if (allModules == null) {
+                    allModules = Stream.concat(first.findAll().stream(),
+                                               second.findAll().stream())
+                                       .map(a -> a.descriptor().name())
+                                       .distinct()
+                                       .map(this::find)
+                                       .map(Optional::get)
+                                       .collect(Collectors.toSet());
+                }
+                return allModules;
+            }
+        };
+    }
+
+    /**
+     * Returns an empty module finder.  The empty finder does not find any
+     * modules.
+     *
+     * @apiNote This is useful when using methods such as {@link
+     * Configuration#resolveRequires resolveRequires} where two finders are
+     * specified. An alternative is {@code ModuleFinder.of()}.
+     *
+     * @return A {@code ModuleFinder} that does not find any modules
+     */
+    static ModuleFinder empty() {
+        // an alternative implementation of ModuleFinder.of()
+        return new ModuleFinder() {
+            @Override public Optional<ModuleReference> find(String name) {
+                Objects.requireNonNull(name);
+                return Optional.empty();
+            }
+            @Override public Set<ModuleReference> findAll() {
+                return Collections.emptySet();
+            }
+        };
+    }
+
+}
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
new file mode 100644
index 0000000..f9e0bfa
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import jdk.internal.module.Hasher.DependencyHashes;
+
+import static jdk.internal.module.ClassFileConstants.*;
+
+
+/**
+ * Read module information from a {@code module-info} class file.
+ *
+ * @implNote The rationale for the hand-coded reader is startup performance
+ * and fine control over the throwing of InvalidModuleDescriptorException.
+ */
+
+final class ModuleInfo {
+
+    // supplies the set of packages when ConcealedPackages not present
+    private final Supplier<Set<String>> packageFinder;
+
+    // indicates if the Hashes 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;
+    }
+
+    private ModuleInfo(Supplier<Set<String>> pf) {
+        this(pf, true);
+    }
+
+    /**
+     * Reads a {@code module-info.class} from the given input stream.
+     *
+     * @throws InvalidModuleDescriptorException
+     * @throws IOException
+     */
+    public static ModuleDescriptor read(InputStream in,
+                                        Supplier<Set<String>> pf)
+        throws IOException
+    {
+        try {
+            return new ModuleInfo(pf).doRead(new DataInputStream(in));
+        } catch (IllegalArgumentException iae) {
+            // IllegalArgumentException means a malformed class
+            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (EOFException x) {
+            throw truncatedModuleDescriptor();
+        }
+    }
+
+    /**
+     * Reads a {@code module-info.class} from the given byte buffer.
+     *
+     * @throws InvalidModuleDescriptorException
+     * @throws UncheckedIOException
+     */
+    public static ModuleDescriptor read(ByteBuffer bb,
+                                        Supplier<Set<String>> pf)
+    {
+        try {
+            return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
+        } catch (IllegalArgumentException iae) {
+            // IllegalArgumentException means a malformed class
+            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (EOFException x) {
+            throw truncatedModuleDescriptor();
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    /**
+     * Reads a {@code module-info.class} from the given byte buffer
+     * but ignore the {@code Hashes} attribute.
+     *
+     * @throws InvalidModuleDescriptorException
+     * @throws UncheckedIOException
+     */
+    static ModuleDescriptor readIgnoringHashes(ByteBuffer bb,
+                                               Supplier<Set<String>> pf)
+    {
+        try {
+            return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
+        } catch (IllegalArgumentException iae) {
+            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (EOFException x) {
+            throw truncatedModuleDescriptor();
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    /**
+     * Reads the input as a module-info class file.
+     *
+     * @throws IOException
+     * @throws InvalidModuleDescriptorException
+     * @throws IllegalArgumentException if thrown by the ModuleDescriptor.Builder
+     *         because an identifier is not a legal Java identifier, duplicate
+     *         exports, and many other reasons
+     */
+    private ModuleDescriptor doRead(DataInput in) throws IOException {
+
+        int magic = in.readInt();
+        if (magic != 0xCAFEBABE)
+            throw invalidModuleDescriptor("Bad magic number");
+
+        int minor_version = in.readUnsignedShort();
+        int major_version = in.readUnsignedShort();
+        if (major_version < 53) {
+            // throw invalidModuleDescriptor"Must be >= 53.0");
+        }
+
+        ConstantPool cpool = new ConstantPool(in);
+
+        int access_flags = in.readUnsignedShort();
+        if (access_flags != ACC_MODULE)
+            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);
+
+        int super_class = in.readUnsignedShort();
+        if (super_class > 0)
+            throw invalidModuleDescriptor("bad #super_class");
+
+        int interfaces_count = in.readUnsignedShort();
+        if (interfaces_count > 0)
+            throw invalidModuleDescriptor("Bad #interfaces");
+
+        int fields_count = in.readUnsignedShort();
+        if (fields_count > 0)
+            throw invalidModuleDescriptor("Bad #fields");
+
+        int methods_count = in.readUnsignedShort();
+        if (methods_count > 0)
+            throw invalidModuleDescriptor("Bad #methods");
+
+        int attributes_count = in.readUnsignedShort();
+
+        // the names of the attributes found in the class file
+        Set<String> attributes = new HashSet<>();
+
+        for (int i = 0; i < attributes_count ; i++) {
+            int name_index = in.readUnsignedShort();
+            String attribute_name = cpool.getUtf8(name_index);
+            int length = in.readInt();
+
+            boolean added = attributes.add(attribute_name);
+            if (!added && isAttributeAtMostOnce(attribute_name)) {
+                throw invalidModuleDescriptor("More than one "
+                                              + attribute_name + " attribute");
+            }
+
+            switch (attribute_name) {
+
+                case MODULE :
+                    readModuleAttribute(mn, in, cpool);
+                    break;
+
+                case CONCEALED_PACKAGES :
+                    readConcealedPackagesAttribute(in, cpool);
+                    break;
+
+                case VERSION :
+                    readVersionAttribute(in, cpool);
+                    break;
+
+                case MAIN_CLASS :
+                    readMainClassAttribute(in, cpool);
+                    break;
+
+                case TARGET_PLATFORM :
+                    readTargetPlatformAttribute(in, cpool);
+                    break;
+
+                case HASHES :
+                    if (parseHashes) {
+                        readHashesAttribute(in, cpool);
+                    } else {
+                        in.skipBytes(length);
+                    }
+                    break;
+
+                default:
+                    if (isAttributeDisallowed(attribute_name)) {
+                        throw invalidModuleDescriptor(attribute_name
+                                                      + " attribute not allowed");
+                    } else {
+                        in.skipBytes(length);
+                    }
+
+            }
+        }
+
+        // the Module attribute is required
+        if (!attributes.contains(MODULE)) {
+            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;
+            try {
+                pkgs = new HashSet<>(packageFinder.get());
+            } catch (UncheckedIOException x) {
+                throw x.getCause();
+            }
+            pkgs.removeAll(builder.exportedPackages());
+            builder.conceals(pkgs);
+        }
+
+        // Was the Synthetic attribute present?
+        if (attributes.contains(SYNTHETIC))
+            builder.synthetic(true);
+
+        return builder.build();
+    }
+
+    /**
+     * Reads the Module attribute.
+     */
+    private void readModuleAttribute(String mn, DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int requires_count = in.readUnsignedShort();
+        if (requires_count == 0 && !mn.equals("java.base")) {
+            throw invalidModuleDescriptor("The requires table must have"
+                                          + " at least one entry");
+        }
+        for (int i=0; i<requires_count; i++) {
+            int index = in.readUnsignedShort();
+            int flags = in.readUnsignedShort();
+            String dn = cpool.getUtf8(index);
+            Set<Modifier> mods;
+            if (flags == 0) {
+                mods = Collections.emptySet();
+            } else {
+                mods = new HashSet<>();
+                if ((flags & ACC_PUBLIC) != 0)
+                    mods.add(Modifier.PUBLIC);
+                if ((flags & ACC_SYNTHETIC) != 0)
+                    mods.add(Modifier.SYNTHETIC);
+                if ((flags & ACC_MANDATED) != 0)
+                    mods.add(Modifier.MANDATED);
+            }
+            builder.requires(mods, dn);
+        }
+
+        int exports_count = in.readUnsignedShort();
+        if (exports_count > 0) {
+            for (int i=0; i<exports_count; i++) {
+                int index = in.readUnsignedShort();
+                String pkg = cpool.getUtf8(index).replace('/', '.');
+                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));
+                    }
+                    builder.exports(pkg, targets);
+                } else {
+                    builder.exports(pkg);
+                }
+            }
+        }
+
+        int uses_count = in.readUnsignedShort();
+        if (uses_count > 0) {
+            for (int i=0; i<uses_count; i++) {
+                int index = in.readUnsignedShort();
+                String sn = cpool.getClassName(index).replace('/', '.');
+                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 HashSet<>();
+                    pm.put(sn, providers);
+                }
+                providers.add(cn);
+            }
+            for (Map.Entry<String, Set<String>> e : pm.entrySet()) {
+                builder.provides(e.getKey(), e.getValue());
+            }
+        }
+    }
+
+    /**
+     * Reads the ConcealedPackages attribute
+     */
+    private void readConcealedPackagesAttribute(DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int package_count = in.readUnsignedShort();
+        for (int i=0; i<package_count; i++) {
+            int index = in.readUnsignedShort();
+            String pn = cpool.getUtf8(index).replace('/', '.');
+            builder.conceals(pn);
+        }
+    }
+
+    /**
+     * Reads the Version attribute
+     */
+    private void readVersionAttribute(DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int index = in.readUnsignedShort();
+        builder.version(cpool.getUtf8(index));
+    }
+
+    /**
+     * Reads the MainClass attribute
+     */
+    private void readMainClassAttribute(DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int index = in.readUnsignedShort();
+        builder.mainClass(cpool.getClassName(index).replace('/', '.'));
+    }
+
+    /**
+     * Reads the TargetPlatform attribute
+     */
+    private void readTargetPlatformAttribute(DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int name_index = in.readUnsignedShort();
+        if (name_index != 0)
+            builder.osName(cpool.getUtf8(name_index));
+
+        int arch_index = in.readUnsignedShort();
+        if (arch_index != 0)
+            builder.osArch(cpool.getUtf8(arch_index));
+
+        int version_index = in.readUnsignedShort();
+        if (version_index != 0)
+            builder.osVersion(cpool.getUtf8(version_index));
+    }
+
+
+    /**
+     * 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.
+     */
+    private void readHashesAttribute(DataInput in, ConstantPool cpool)
+        throws IOException
+    {
+        int index = in.readUnsignedShort();
+        String algorithm = cpool.getUtf8(index);
+
+        int hash_count = in.readUnsignedShort();
+
+        Map<String, String> 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);
+        }
+
+        builder.hashes(new DependencyHashes(algorithm, map));
+    }
+
+
+    /**
+     * Returns true if the given attribute can be present at most once
+     * in the class file. Returns false otherwise.
+     */
+    private static boolean isAttributeAtMostOnce(String name) {
+
+        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))
+            return true;
+
+        return false;
+    }
+
+    /**
+     * 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.
+     */
+    private static boolean isAttributeDisallowed(String name) {
+        Set<String> notAllowed = predefinedNotAllowed;
+        if (notAllowed == null) {
+            notAllowed = Set.of(
+                    "ConstantValue",
+                    "Code",
+                    "StackMapTable",
+                    "Exceptions",
+                    "EnclosingMethod",
+                    "Signature",
+                    "LineNumberTable",
+                    "LocalVariableTable",
+                    "LocalVariableTypeTable",
+                    "RuntimeVisibleAnnotations",
+                    "RuntimeInvisibleAnnotations",
+                    "RuntimeVisibleParameterAnnotations",
+                    "RuntimeInvisibleParameterAnnotations",
+                    "RuntimeVisibleTypeAnnotations",
+                    "RuntimeInvisibleTypeAnnotations",
+                    "AnnotationDefault",
+                    "BootstrapMethods",
+                    "MethodParameters");
+            predefinedNotAllowed = notAllowed;
+        }
+        return notAllowed.contains(name);
+    }
+
+    // lazily created set the pre-defined attributes that are not allowed
+    private static volatile Set<String> predefinedNotAllowed;
+
+
+
+    /**
+     * The constant pool in a class file.
+     */
+    private static class ConstantPool {
+        static final int CONSTANT_Utf8 = 1;
+        static final int CONSTANT_Integer = 3;
+        static final int CONSTANT_Float = 4;
+        static final int CONSTANT_Long = 5;
+        static final int CONSTANT_Double = 6;
+        static final int CONSTANT_Class = 7;
+        static final int CONSTANT_String = 8;
+        static final int CONSTANT_Fieldref = 9;
+        static final int CONSTANT_Methodref = 10;
+        static final int CONSTANT_InterfaceMethodref = 11;
+        static final int CONSTANT_NameAndType = 12;
+        static final int CONSTANT_MethodHandle = 15;
+        static final int CONSTANT_MethodType = 16;
+        static final int CONSTANT_InvokeDynamic = 18;
+
+        private static class Entry {
+            protected Entry(int tag) {
+                this.tag = tag;
+            }
+            final int tag;
+        }
+
+        private static class IndexEntry extends Entry {
+            IndexEntry(int tag, int index) {
+                super(tag);
+                this.index = index;
+            }
+            final int index;
+        }
+
+        private static class Index2Entry extends Entry {
+            Index2Entry(int tag, int index1, int index2) {
+                super(tag);
+                this.index1 = index1;
+                this.index2 = index2;
+            }
+            final int index1,  index2;
+        }
+
+        private static class ValueEntry extends Entry {
+            ValueEntry(int tag, Object value) {
+                super(tag);
+                this.value = value;
+            }
+            final Object value;
+        }
+
+        final Entry[] pool;
+
+        ConstantPool(DataInput in) throws IOException {
+            int count = in.readUnsignedShort();
+            pool = new Entry[count];
+
+            for (int i = 1; i < count; i++) {
+                int tag = in.readUnsignedByte();
+                switch (tag) {
+
+                    case CONSTANT_Utf8:
+                        String svalue = in.readUTF();
+                        pool[i] = new ValueEntry(tag, svalue);
+                        break;
+
+                    case CONSTANT_Class:
+                    case CONSTANT_String:
+                        int index = in.readUnsignedShort();
+                        pool[i] = new IndexEntry(tag, index);
+                        break;
+
+                    case CONSTANT_Double:
+                        double dvalue = in.readDouble();
+                        pool[i] = new ValueEntry(tag, dvalue);
+                        i++;
+                        break;
+
+                    case CONSTANT_Fieldref:
+                    case CONSTANT_InterfaceMethodref:
+                    case CONSTANT_Methodref:
+                    case CONSTANT_InvokeDynamic:
+                    case CONSTANT_NameAndType:
+                        int index1 = in.readUnsignedShort();
+                        int index2 = in.readUnsignedShort();
+                        pool[i] = new Index2Entry(tag, index1, index2);
+                        break;
+
+                    case CONSTANT_MethodHandle:
+                        int refKind = in.readUnsignedByte();
+                        index = in.readUnsignedShort();
+                        pool[i] = new Index2Entry(tag, refKind, index);
+                        break;
+
+                    case CONSTANT_MethodType:
+                        index = in.readUnsignedShort();
+                        pool[i] = new IndexEntry(tag, index);
+                        break;
+
+                    case CONSTANT_Float:
+                        float fvalue = in.readFloat();
+                        pool[i] = new ValueEntry(tag, fvalue);
+                        break;
+
+                    case CONSTANT_Integer:
+                        int ivalue = in.readInt();
+                        pool[i] = new ValueEntry(tag, ivalue);
+                        break;
+
+                    case CONSTANT_Long:
+                        long lvalue = in.readLong();
+                        pool[i] = new ValueEntry(tag, lvalue);
+                        i++;
+                        break;
+
+                    default:
+                        throw invalidModuleDescriptor("Bad constant pool entry: "
+                                                      + i);
+                }
+            }
+        }
+
+        String getClassName(int index) {
+            checkIndex(index);
+            Entry e = pool[index];
+            if (e.tag != CONSTANT_Class) {
+                throw invalidModuleDescriptor("CONSTANT_Class expected at entry: "
+                                              + index);
+            }
+            return getUtf8(((IndexEntry) e).index);
+        }
+
+        String getUtf8(int index) {
+            checkIndex(index);
+            Entry e = pool[index];
+            if (e.tag != CONSTANT_Utf8) {
+                throw invalidModuleDescriptor("CONSTANT_Utf8 expected at entry: "
+                                              + index);
+            }
+            return (String) (((ValueEntry) e).value);
+        }
+
+        void checkIndex(int index) {
+            if (index < 1 || index >= pool.length)
+                throw invalidModuleDescriptor("Index into constant pool out of range");
+        }
+    }
+
+    /**
+     * A DataInput implementation that reads from a ByteBuffer.
+     */
+    private static class DataInputWrapper implements DataInput {
+        private final ByteBuffer bb;
+
+        DataInputWrapper(ByteBuffer bb) {
+            this.bb = bb;
+        }
+
+        @Override
+        public void readFully(byte b[]) throws IOException {
+            readFully(b, 0, b.length);
+        }
+
+        @Override
+        public void readFully(byte b[], int off, int len) throws IOException {
+            try {
+                bb.get(b, off, len);
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public int skipBytes(int n) {
+            int skip = Math.min(n, bb.remaining());
+            bb.position(bb.position() + skip);
+            return skip;
+        }
+
+        @Override
+        public boolean readBoolean() throws IOException {
+            try {
+                int ch = bb.get();
+                return (ch != 0);
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public byte readByte() throws IOException {
+            try {
+                return bb.get();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public int readUnsignedByte() throws IOException {
+            try {
+                return ((int) bb.get()) & 0xff;
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public short readShort() throws IOException {
+            try {
+                return bb.getShort();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public int readUnsignedShort() throws IOException {
+            try {
+                return ((int) bb.getShort()) & 0xffff;
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public char readChar() throws IOException {
+            try {
+                return bb.getChar();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public int readInt() throws IOException {
+            try {
+                return bb.getInt();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public long readLong() throws IOException {
+            try {
+                return bb.getLong();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public float readFloat() throws IOException {
+            try {
+                return bb.getFloat();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public double readDouble() throws IOException {
+            try {
+                return bb.getDouble();
+            } catch (BufferUnderflowException e) {
+                throw new EOFException();
+            }
+        }
+
+        @Override
+        public String readLine() {
+            throw new RuntimeException("not implemented");
+        }
+
+        @Override
+        public String readUTF() throws IOException {
+            // ### Need to measure the performance and feasibility of using
+            // the UTF-8 decoder instead.
+            return DataInputStream.readUTF(this);
+        }
+    }
+
+    /**
+     * Returns an InvalidModuleDescriptorException with the given detail
+     * message
+     */
+    private static InvalidModuleDescriptorException
+    invalidModuleDescriptor(String msg) {
+        return new InvalidModuleDescriptorException(msg);
+    }
+
+    /**
+     * Returns an InvalidModuleDescriptorException with a detail message to
+     * indicate that the class file is truncated.
+     */
+    private static InvalidModuleDescriptorException truncatedModuleDescriptor() {
+        return invalidModuleDescriptor("Truncated module-info.class");
+    }
+
+}
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
new file mode 100644
index 0000000..fbd1b47
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
@@ -0,0 +1,590 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import jdk.internal.module.Checks;
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.perf.PerfCounter;
+
+
+/**
+ * A {@code ModuleFinder} that locates modules on the file system by searching
+ * a sequence of directories or packaged modules.
+ *
+ * The {@code ModuleFinder} can be configured to work in either the run-time
+ * or link-time phases. In both cases it locates modular JAR and exploded
+ * modules. When configured for link-time then it additionally locates
+ * modules in JMOD files.
+ */
+
+class ModulePath implements ConfigurableModuleFinder {
+    private static final String MODULE_INFO = "module-info.class";
+
+    // the entries on this module path
+    private final Path[] entries;
+    private int next;
+
+    // true if in the link phase
+    private boolean isLinkPhase;
+
+    // map of module name to module reference map for modules already located
+    private final Map<String, ModuleReference> cachedModules = new HashMap<>();
+
+    ModulePath(Path... entries) {
+        this.entries = entries.clone();
+        for (Path entry : this.entries) {
+            Objects.requireNonNull(entry);
+        }
+    }
+
+    @Override
+    public void configurePhase(Phase phase) {
+        isLinkPhase = (phase == Phase.LINK_TIME);
+    }
+
+    @Override
+    public Optional<ModuleReference> find(String name) {
+        Objects.requireNonNull(name);
+
+        // try cached modules
+        ModuleReference m = cachedModules.get(name);
+        if (m != null)
+            return Optional.of(m);
+
+        // the module may not have been encountered yet
+        while (hasNextEntry()) {
+            scanNextEntry();
+            m = cachedModules.get(name);
+            if (m != null)
+                return Optional.of(m);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Set<ModuleReference> findAll() {
+        // need to ensure that all entries have been scanned
+        while (hasNextEntry()) {
+            scanNextEntry();
+        }
+        return cachedModules.values().stream().collect(Collectors.toSet());
+    }
+
+    /**
+     * Returns {@code true} if there are additional entries to scan
+     */
+    private boolean hasNextEntry() {
+        return next < entries.length;
+    }
+
+    /**
+     * Scans the next entry on the module path. A no-op if all entries have
+     * already been scanned.
+     *
+     * @throws FindException if an error occurs scanning the next entry
+     */
+    private void scanNextEntry() {
+        if (hasNextEntry()) {
+
+            long t0 = System.nanoTime();
+
+            Path entry = entries[next];
+            Map<String, ModuleReference> modules = scan(entry);
+            next++;
+
+            // update cache, ignoring duplicates
+            int initialSize = cachedModules.size();
+            for (Map.Entry<String, ModuleReference> e : modules.entrySet()) {
+                cachedModules.putIfAbsent(e.getKey(), e.getValue());
+            }
+
+            // update counters
+            int added = cachedModules.size() - initialSize;
+            moduleCount.add(added);
+
+            scanTime.addElapsedTimeFrom(t0);
+        }
+    }
+
+
+    /**
+     * Scan the given module path entry. If the entry is a directory then it is
+     * a directory of modules or an exploded module. If the entry is a regular
+     * file then it is assumed to be a packaged module.
+     *
+     * @throws FindException if an error occurs scanning the entry
+     */
+    private Map<String, ModuleReference> scan(Path entry) {
+
+        BasicFileAttributes attrs;
+        try {
+            attrs = Files.readAttributes(entry, BasicFileAttributes.class);
+        } catch (NoSuchFileException e) {
+            return Collections.emptyMap();
+        } catch (IOException ioe) {
+            throw new FindException(ioe);
+        }
+
+        try {
+
+            if (attrs.isDirectory()) {
+                Path mi = entry.resolve(MODULE_INFO);
+                if (!Files.exists(mi)) {
+                    // does not exist or unable to determine so assume a
+                    // directory of modules
+                    return scanDirectory(entry);
+                }
+            }
+
+            if (attrs.isRegularFile() || attrs.isDirectory()) {
+                // packaged or exploded module
+                ModuleReference mref = readModule(entry, attrs);
+                if (mref != null) {
+                    String name = mref.descriptor().name();
+                    return Collections.singletonMap(name, mref);
+                }
+            }
+
+            // not recognized
+            throw new FindException("Unrecognized module: " + entry);
+
+        } catch (IOException ioe) {
+            throw new FindException(ioe);
+        }
+    }
+
+
+    /**
+     * Scans the given directory for packaged or exploded modules.
+     *
+     * @return a map of module name to ModuleReference for the modules found
+     *         in the directory
+     *
+     * @throws IOException if an I/O error occurs
+     * @throws FindException if an error occurs scanning the entry or the
+     *         directory contains two or more modules with the same name
+     */
+    private Map<String, ModuleReference> scanDirectory(Path dir)
+        throws IOException
+    {
+        // The map of name -> mref of modules found in this directory.
+        Map<String, ModuleReference> nameToReference = new HashMap<>();
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
+            for (Path entry : stream) {
+                BasicFileAttributes attrs;
+                try {
+                    attrs = Files.readAttributes(entry, BasicFileAttributes.class);
+                } catch (NoSuchFileException ignore) {
+                    // file has been removed or moved, ignore for now
+                    continue;
+                }
+
+                ModuleReference mref = readModule(entry, attrs);
+
+                // module found
+                if (mref != null) {
+
+                    // can have at most one version of a module in the directory
+                    String name = mref.descriptor().name();
+                    if (nameToReference.put(name, mref) != null) {
+                        throw new FindException("Two versions of module "
+                                + name + " found in " + dir);
+                    }
+
+                }
+
+            }
+        }
+
+        return nameToReference;
+    }
+
+
+    /**
+     * Locates a packaged or exploded module, returning a {@code ModuleReference}
+     * to the module. Returns {@code null} if the module is not recognized
+     * as a packaged or exploded module.
+     *
+     * @throws IOException if an I/O error occurs
+     * @throws FindException if an error occurs parsing the module descriptor
+     */
+    private ModuleReference readModule(Path entry, BasicFileAttributes attrs)
+        throws IOException
+    {
+        try {
+
+            ModuleReference mref = null;
+            if (attrs.isDirectory()) {
+                mref = readExplodedModule(entry);
+            } if (attrs.isRegularFile()) {
+                if (entry.toString().endsWith(".jar")) {
+                    mref = readJar(entry);
+                } else if (isLinkPhase && entry.toString().endsWith(".jmod")) {
+                    mref = readJMod(entry);
+                }
+            }
+            return mref;
+
+        } catch (InvalidModuleDescriptorException e) {
+            throw new FindException("Error reading module: " + entry, e);
+        }
+    }
+
+
+    // -- jmod files --
+
+    private Set<String> jmodPackages(ZipFile zf) {
+        return zf.stream()
+            .filter(e -> e.getName().startsWith("classes/") &&
+                    e.getName().endsWith(".class"))
+            .map(e -> toPackageName(e))
+            .filter(pkg -> pkg.length() > 0) // module-info
+            .distinct()
+            .collect(Collectors.toSet());
+    }
+
+    /**
+     * Returns a {@code ModuleReference} to a module in jmod file on the
+     * file system.
+     */
+    private ModuleReference readJMod(Path file) throws IOException {
+        try (ZipFile zf = new ZipFile(file.toString())) {
+            ZipEntry ze = zf.getEntry("classes/" + MODULE_INFO);
+            if (ze == null) {
+                throw new IOException(MODULE_INFO + " is missing: " + file);
+            }
+            ModuleDescriptor md;
+            try (InputStream in = zf.getInputStream(ze)) {
+                md = ModuleDescriptor.read(in, () -> jmodPackages(zf));
+            }
+            return ModuleReferences.newJModModule(md, file);
+        }
+    }
+
+
+    // -- JAR files --
+
+    private static final String SERVICES_PREFIX = "META-INF/services/";
+
+    /**
+     * Returns a container with the service type corresponding to the name of
+     * a services configuration file.
+     *
+     * For example, if called with "META-INF/services/p.S" then this method
+     * returns a container with the value "p.S".
+     */
+    private Optional<String> toServiceName(String cf) {
+        assert cf.startsWith(SERVICES_PREFIX);
+        int index = cf.lastIndexOf("/") + 1;
+        if (index < cf.length()) {
+            String prefix = cf.substring(0, index);
+            if (prefix.equals(SERVICES_PREFIX)) {
+                String sn = cf.substring(index);
+                if (Checks.isJavaIdentifier(sn))
+                    return Optional.of(sn);
+            }
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Reads the next line from the given reader and trims it of comments and
+     * leading/trailing white space.
+     *
+     * Returns null if the reader is at EOF.
+     */
+    private String nextLine(BufferedReader reader) throws IOException {
+        String ln = reader.readLine();
+        if (ln != null) {
+            int ci = ln.indexOf('#');
+            if (ci >= 0)
+                ln = ln.substring(0, ci);
+            ln = ln.trim();
+        }
+        return ln;
+    }
+
+    /**
+     * Treat the given JAR file as a module as follows:
+     *
+     * 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
+     * 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
+     *    is mapped to the module descriptor mainClass
+     *
+     * @apiNote This needs to move to somewhere where it can be used by tools,
+     * maybe even a standard API if automatic modules are a Java SE feature.
+     */
+    private ModuleDescriptor deriveModuleDescriptor(JarFile jf)
+        throws IOException
+    {
+        // Derive module name and version from JAR file name
+
+        String fn = jf.getName();
+        int i = fn.lastIndexOf(File.separator);
+        if (i != -1)
+            fn = fn.substring(i+1);
+
+        // drop .jar
+        String mn = fn.substring(0, fn.length()-4);
+        String vs = null;
+
+        // find first occurrence of -${NUMBER}. or -${NUMBER}$
+        Matcher matcher = Pattern.compile("-(\\d+(\\.|$))").matcher(mn);
+        if (matcher.find()) {
+            int start = matcher.start();
+
+            // attempt to parse the tail as a version string
+            try {
+                String tail = mn.substring(start+1);
+                ModuleDescriptor.Version.parse(tail);
+                vs = tail;
+            } catch (IllegalArgumentException ignore) { }
+
+            mn = mn.substring(0, start);
+        }
+
+        // finally clean up the module name
+        mn =  mn.replaceAll("[^A-Za-z0-9]", ".")  // replace non-alphanumeric
+                .replaceAll("(\\.)(\\1)+", ".")   // collapse repeating dots
+                .replaceAll("^\\.", "")           // drop leading dots
+                .replaceAll("\\.$", "");          // drop trailing dots
+
+
+        // Builder throws IAE if module name is empty or invalid
+        ModuleDescriptor.Builder builder
+            = new ModuleDescriptor.Builder(mn, true)
+                .requires(Requires.Modifier.MANDATED, "java.base");
+        if (vs != null)
+            builder.version(vs);
+
+        // scan the entries in the JAR file to locate the .class and service
+        // configuration file
+        Stream<String> stream = jf.stream()
+            .map(e -> e.getName())
+            .filter(e -> (e.endsWith(".class") || e.startsWith(SERVICES_PREFIX)))
+            .distinct();
+        Map<Boolean, Set<String>> map
+            = stream.collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
+                             Collectors.toSet()));
+        Set<String> classFiles = map.get(Boolean.TRUE);
+        Set<String> configFiles = map.get(Boolean.FALSE);
+
+        // all packages are exported
+        classFiles.stream()
+            .map(c -> toPackageName(c))
+            .distinct()
+            .forEach(p -> builder.exports(p));
+
+        // map names of service configuration files to service names
+        Set<String> serviceNames = configFiles.stream()
+            .map(this::toServiceName)
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .collect(Collectors.toSet());
+
+        // parse each service configuration file
+        for (String sn : serviceNames) {
+            JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
+            Set<String> providerClasses = new HashSet<>();
+            try (InputStream in = jf.getInputStream(entry)) {
+                BufferedReader reader
+                    = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+                String cn;
+                while ((cn = nextLine(reader)) != null) {
+                    if (Checks.isJavaIdentifier(cn)) {
+                        providerClasses.add(cn);
+                    }
+                }
+            }
+            if (!providerClasses.isEmpty())
+                builder.provides(sn, providerClasses);
+        }
+
+        // Main-Class attribute if it exists
+        Manifest man = jf.getManifest();
+        if (man != null) {
+            Attributes attrs = man.getMainAttributes();
+            String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
+            if (mainClass != null)
+                builder.mainClass(mainClass);
+        }
+
+        return builder.build();
+    }
+
+    private Set<String> jarPackages(JarFile jf) {
+        return jf.stream()
+            .filter(e -> e.getName().endsWith(".class"))
+            .map(e -> toPackageName(e))
+            .filter(pkg -> pkg.length() > 0)   // module-info
+            .distinct()
+            .collect(Collectors.toSet());
+    }
+
+    /**
+     * Returns a {@code ModuleReference} to a module in modular JAR file on
+     * the file system.
+     */
+    private ModuleReference readJar(Path file) throws IOException {
+        try (JarFile jf = new JarFile(file.toString())) {
+
+            ModuleDescriptor md;
+            JarEntry entry = jf.getJarEntry(MODULE_INFO);
+            if (entry == null) {
+
+                // no module-info.class so treat it as automatic module
+                try {
+                    md = deriveModuleDescriptor(jf);
+                } catch (IllegalArgumentException iae) {
+                    throw new FindException(
+                        "Unable to derive module descriptor for: "
+                        + jf.getName(), iae);
+                }
+
+            } else {
+                md = ModuleDescriptor.read(jf.getInputStream(entry),
+                                           () -> jarPackages(jf));
+            }
+
+            return ModuleReferences.newJarModule(md, file);
+        }
+    }
+
+
+    // -- exploded directories --
+
+    private Set<String> explodedPackages(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
+                .distinct()
+                .collect(Collectors.toSet());
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
+        }
+    }
+
+    /**
+     * Returns a {@code ModuleReference} to an exploded module on the file
+     * system or {@code null} if {@code module-info.class} not found.
+     */
+    private ModuleReference readExplodedModule(Path dir) throws IOException {
+        Path mi = dir.resolve(MODULE_INFO);
+        ModuleDescriptor md;
+        try (InputStream in = Files.newInputStream(mi)) {
+            md = ModuleDescriptor.read(new BufferedInputStream(in),
+                                       () -> explodedPackages(dir));
+        } catch (NoSuchFileException e) {
+            // for now
+            return null;
+        }
+        return ModuleReferences.newExplodedModule(md, dir);
+    }
+
+
+    //
+
+    // p/q/T.class => p.q
+    private String toPackageName(String cn) {
+        assert cn.endsWith(".class");
+        int start = 0;
+        int index = cn.lastIndexOf("/");
+        if (index > start) {
+            return cn.substring(start, index).replace('/', '.');
+        } else {
+            return "";
+        }
+    }
+
+    private String toPackageName(ZipEntry entry) {
+        String name = entry.getName();
+        assert name.endsWith(".class");
+        // jmod classes in classes/, jar in /
+        int start = name.startsWith("classes/") ? 8 : 0;
+        int index = name.lastIndexOf("/");
+        if (index > start) {
+            return name.substring(start, index).replace('/', '.');
+        } else {
+            return "";
+        }
+    }
+
+    private 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, '.');
+        } else {
+            return "";
+        }
+    }
+
+    private static final PerfCounter scanTime
+        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.scanTime");
+    private static final PerfCounter moduleCount
+        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.modules");
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java
new file mode 100644
index 0000000..140886d8
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+
+/**
+ * Provides access to the content of a module.
+ *
+ * <p> A module reader is intended for cases where access to the resources in a
+ * module is required, regardless of whether the module has been loaded.
+ * A framework that scans a collection of packaged modules on the file system,
+ * for example, may use a module reader to access a specific resource in each
+ * module. A module reader is also intended to be used by {@code ClassLoader}
+ * implementations that load classes and resources from modules. </p>
+ *
+ * <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
+ * creation and is closed by invoking the {@link #close close} method.  Failure
+ * to close a module reader may result in a resource leak.  The {@code
+ * try-with-resources} statement provides a useful construct to ensure that
+ * module readers are closed. </p>
+ *
+ * <p> A {@code ModuleReader} implementation may require permissions to access
+ * resources in the module. Consequently the {@link #find find}, {@link #open
+ * open} and {@link #read read} methods may throw {@code SecurityException} if
+ * access is denied by the security manager. </p>
+ *
+ * @see ModuleReference
+ * @since 9
+ */
+
+public interface ModuleReader extends Closeable {
+
+    /**
+     * Finds a resource, returning a URI to the resource in the module.
+     *
+     * @param  name
+     *         The name of the resource to open for reading
+     *
+     * @return A URI to the resource; an empty {@code Optional} if the resource
+     *         is not found or a URI cannot be constructed to locate the
+     *         resource
+     *
+     * @throws IOException
+     *         If an I/O error occurs or the module reader is closed
+     * @throws SecurityException
+     *         If denied by the security manager
+     *
+     * @see ClassLoader#getResource(String)
+     */
+    Optional<URI> find(String name) throws IOException;
+
+    /**
+     * Opens a resource, returning an input stream to read the resource in
+     * the module.
+     *
+     * @implSpec The default implementation invokes the {@link #find(String)
+     * find} method to get a URI to the resource. If found, then it attempts
+     * to construct a {@link java.net.URL URL} and open a connection to the
+     * resource.
+     *
+     * @param  name
+     *         The name of the resource to open for reading
+     *
+     * @return An input stream to read the resource or an empty
+     *         {@code Optional} if not found
+     *
+     * @throws IOException
+     *         If an I/O error occurs or the module reader is closed
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    default Optional<InputStream> open(String name) throws IOException {
+        Optional<URI> ouri = find(name);
+        if (ouri.isPresent()) {
+            return Optional.of(ouri.get().toURL().openStream());
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Reads a resource, returning a byte buffer with the contents of the
+     * resource.
+     *
+     * The element at the returned buffer's position is the first byte of the
+     * resource, the element at the buffer's limit is the last byte of the
+     * resource. Once consumed, the {@link #release(ByteBuffer) release} method
+     * must be invoked. Failure to invoke the {@code release} method may result
+     * in a resource leak.
+     *
+     * @apiNote This method is intended for high-performance class loading. It
+     * is not capable (or intended) to read arbitrary large resources that
+     * could potentially be 2GB or larger. The rational for using this method
+     * in conjunction with the {@code release} method is to allow module reader
+     * implementations manage buffers in an efficient manner.
+     *
+     * @implSpec The default implementation invokes the {@link #open(String)
+     * open} method and reads all bytes from the input stream into a byte
+     * buffer.
+     *
+     * @param  name
+     *         The name of the resource to read
+     *
+     * @return A byte buffer containing the contents of the resource or an
+     *         empty {@code Optional} if not found
+     *
+     * @throws IOException
+     *         If an I/O error occurs or the module reader is closed
+     * @throws SecurityException
+     *         If denied by the security manager
+     *
+     * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain)
+     */
+    default Optional<ByteBuffer> read(String name) throws IOException {
+        Optional<InputStream> in = open(name);
+        if (in.isPresent()) {
+            byte[] bytes = in.get().readAllBytes();
+            return Optional.of(ByteBuffer.wrap(bytes));
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Release a byte buffer. This method should be invoked after consuming
+     * the contents of the buffer returned by the {@code read} method.
+     * The behavior of this method when invoked to release a buffer that has
+     * already been released, or the behavior when invoked to release a buffer
+     * after a {@code ModuleReader} is closed is implementation specific and
+     * therefore not specified.
+     *
+     * @param  bb
+     *         The byte buffer to release
+     *
+     * @implSpec The default implementation does nothing.
+     */
+    default void release(ByteBuffer bb) { }
+
+    /**
+     * Closes the module reader. Once closed then subsequent calls to locate or
+     * read a resource will fail by returning {@code Optional.empty()} or
+     * throwing {@code IOException}.
+     *
+     * <p> A module reader is not required to be asynchronously closeable. If a
+     * thread is reading a resource and another thread invokes the close method,
+     * then the second thread may block until the read operation is complete.
+     *
+     * <p> The behavior of {@code InputStream}s obtained using the {@link
+     * #open(String) open} method and used after the module reader is closed
+     * is implementation specific and therefore not specified.
+     */
+    @Override
+    void close() throws IOException;
+
+}
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
new file mode 100644
index 0000000..781e7d3
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+import jdk.internal.module.Hasher.HashSupplier;
+
+
+/**
+ * A reference to a module's content.
+ *
+ * <p> A module reference contains the module's descriptor and its location, if
+ * known.  It also has the ability to create a {@link ModuleReader} in order to
+ * access the module's content, which may be inside the Java run-time system
+ * itself or in an artifact such as a modular JAR file.
+ *
+ * @see ModuleFinder
+ * @see ModuleReader
+ * @since 9
+ */
+
+public final class ModuleReference {
+
+    private final ModuleDescriptor descriptor;
+    private final URI location;
+    private final Supplier<ModuleReader> readerSupplier;
+
+    // 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;
+
+    /**
+     * Constructs a new instance of this class.
+     */
+    ModuleReference(ModuleDescriptor descriptor,
+                    URI location,
+                    Supplier<ModuleReader> readerSupplier,
+                    HashSupplier hasher)
+    {
+        this.descriptor = Objects.requireNonNull(descriptor);
+        this.location = location;
+        this.readerSupplier = Objects.requireNonNull(readerSupplier);
+        this.hasher = hasher;
+    }
+
+
+    /**
+     * Constructs a new instance of this class.
+     *
+     * <p> The {@code readSupplier} parameter is the supplier of the {@link
+     * ModuleReader} that may be used to read the module content. Its {@link
+     * Supplier#get() get()} method throws {@link UncheckedIOException} if an
+     * I/O error occurs opening the module content. The {@code get()} method
+     * throws {@link SecurityException} if opening the module is denied by the
+     * security manager.
+     *
+     * @param descriptor
+     *        The module descriptor
+     * @param location
+     *        The module location or {@code null} if not known
+     * @param readerSupplier
+     *        The {@code Supplier} of the {@code ModuleReader}
+     */
+    public ModuleReference(ModuleDescriptor descriptor,
+                           URI location,
+                           Supplier<ModuleReader> readerSupplier)
+    {
+        this(descriptor, location, readerSupplier, null);
+    }
+
+
+    /**
+     * Returns the module descriptor.
+     *
+     * @return The module descriptor
+     */
+    public ModuleDescriptor descriptor() {
+        return descriptor;
+    }
+
+
+    /**
+     * Returns the location of this module's content, if known.
+     *
+     * <p> This URI, when present, is used as the {@linkplain
+     * java.security.CodeSource#getLocation location} value of a {@link
+     * java.security.CodeSource CodeSource} so that a module's classes can be
+     * granted specific permissions when loaded by a {@link
+     * java.security.SecureClassLoader SecureClassLoader}.
+     *
+     * @return The location or an empty {@code Optional} if not known
+     */
+    public Optional<URI> location() {
+        return Optional.ofNullable(location);
+    }
+
+
+    /**
+     * Opens the module content for reading.
+     *
+     * <p> This method opens the module content by invoking the {@link
+     * Supplier#get() get()} method of the {@code readSupplier} specified at
+     * construction time. </p>
+     *
+     * @return A {@code ModuleReader} to read the module
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    public ModuleReader open() throws IOException {
+        try {
+            return readerSupplier.get();
+        } catch (UncheckedIOException e) {
+            throw e.getCause();
+        }
+
+    }
+
+
+    /**
+     * Computes the hash of this module, returning it as a hex string.
+     * 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;
+        if (result != null)
+            return result;
+        if (hasher == null)
+            return null;
+        cachedHash = result = hasher.generate(algorithm);
+        return result;
+    }
+
+    private int hash;
+
+    /**
+     * Computes a hash code for this module reference.
+     *
+     * <p> The hash code is based upon the components of the reference, and
+     * satisfies the general contract of the {@link Object#hashCode
+     * Object.hashCode} method. </p>
+     *
+     * @return The hash-code value for this module reference
+     */
+    @Override
+    public int hashCode() {
+        int hc = hash;
+        if (hc == 0) {
+            hc = Objects.hash(descriptor, location, readerSupplier, hasher);
+            if (hc != 0) hash = hc;
+        }
+        return hc;
+    }
+
+    /**
+     * Tests this module reference for equality with the given object.
+     *
+     * <p> If the given object is not a {@code ModuleReference} then this
+     * method returns {@code false}. Two module references are equal if their
+     * module descriptors are equal, their locations are equal or both unknown,
+     * and were created with equal supplier objects to access the module
+     * content. </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
+     *          reference that is equal to this module reference
+     */
+    @Override
+    public boolean equals(Object ob) {
+        if (!(ob instanceof ModuleReference))
+            return false;
+        ModuleReference that = (ModuleReference)ob;
+
+        return Objects.equals(this.descriptor, that.descriptor)
+                && Objects.equals(this.location, that.location)
+                && Objects.equals(this.readerSupplier, that.readerSupplier)
+                && Objects.equals(this.hasher, that.hasher);
+    }
+
+    /**
+     * Returns a string describing this module reference.
+     *
+     * @return A string describing this module reference
+     */
+    @Override
+    public String toString() {
+        return ("[module " + descriptor().name()
+                + ", location=" + location + "]");
+    }
+
+}
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
new file mode 100644
index 0000000..05448e2
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.File;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Supplier;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.Hasher;
+import jdk.internal.module.Hasher.HashSupplier;
+import jdk.internal.module.ModulePatcher;
+import sun.net.www.ParseUtil;
+
+
+/**
+ * A factory for creating ModuleReference implementations where the modules are
+ * packaged as modular JAR file, JMOD files or where the modules are exploded
+ * on the file system.
+ */
+
+class ModuleReferences {
+
+    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+    private ModuleReferences() { }
+
+    /**
+     * Creates a ModuleReference to a module or to patched module when
+     * creating modules for the boot Layer and -Xpatch is specified.
+     */
+    private static ModuleReference newModule(ModuleDescriptor md,
+                                             URI uri,
+                                             Supplier<ModuleReader> supplier,
+                                             HashSupplier hasher) {
+
+        ModuleReference mref = new ModuleReference(md, uri, supplier, hasher);
+
+        if (JLA.getBootLayer() == null)
+            mref = ModulePatcher.interposeIfNeeded(mref);
+
+        return mref;
+    }
+
+    /**
+     * Creates a ModuleReference to a module packaged as a modular JAR.
+     */
+    static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
+        URI uri = file.toUri();
+        Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
+        HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
+        return newModule(md, uri, supplier, hasher);
+    }
+
+    /**
+     * Creates a ModuleReference to a module packaged as a JMOD.
+     */
+    static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
+        URI uri = file.toUri();
+        Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
+        HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm);
+        return newModule(md, file.toUri(), supplier, hasher);
+    }
+
+    /**
+     * Creates a ModuleReference to an exploded module.
+     */
+    static ModuleReference newExplodedModule(ModuleDescriptor md, Path dir) {
+        Supplier<ModuleReader> supplier = () -> new ExplodedModuleReader(dir);
+        return newModule(md, dir.toUri(), supplier, null);
+    }
+
+
+    /**
+     * A base module reader that encapsulates machinery required to close the
+     * module reader safely.
+     */
+    static abstract class SafeCloseModuleReader implements ModuleReader {
+
+        // RW lock to support safe close
+        private final ReadWriteLock lock = new ReentrantReadWriteLock();
+        private final Lock readLock = lock.readLock();
+        private final Lock writeLock = lock.writeLock();
+        private volatile boolean closed;
+
+        SafeCloseModuleReader() { }
+
+        /**
+         * Returns a URL to  resource. This method is invoked by the find
+         * method to do the actual work of finding the resource.
+         */
+        abstract Optional<URI> implFind(String name) throws IOException;
+
+        /**
+         * Returns an input stream for reading a resource. This method is
+         * invoked by the open method to do the actual work of opening
+         * an input stream to the resource.
+         */
+        abstract Optional<InputStream> implOpen(String name) throws IOException;
+
+        /**
+         * Closes the module reader. This method is invoked by close to do the
+         * actual work of closing the module reader.
+         */
+        abstract void implClose() throws IOException;
+
+        @Override
+        public final Optional<URI> find(String name) throws IOException {
+            readLock.lock();
+            try {
+                if (!closed) {
+                    return implFind(name);
+                } else {
+                    throw new IOException("ModuleReader is closed");
+                }
+            } finally {
+                readLock.unlock();
+            }
+        }
+
+
+        @Override
+        public final Optional<InputStream> open(String name) throws IOException {
+            readLock.lock();
+            try {
+                if (!closed) {
+                    return implOpen(name);
+                } else {
+                    throw new IOException("ModuleReader is closed");
+                }
+            } finally {
+                readLock.unlock();
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            writeLock.lock();
+            try {
+                if (!closed) {
+                    closed = true;
+                    implClose();
+                }
+            } finally {
+                writeLock.unlock();
+            }
+        }
+    }
+
+
+    /**
+     * A ModuleReader for a modular JAR file.
+     */
+    static class JarModuleReader extends SafeCloseModuleReader {
+        private final JarFile jf;
+        private final URI uri;
+
+        static JarFile newJarFile(Path path) {
+            try {
+                return new JarFile(path.toFile());
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            }
+        }
+
+        JarModuleReader(Path path, URI uri) {
+            this.jf = newJarFile(path);
+            this.uri = uri;
+        }
+
+        private JarEntry getEntry(String name) {
+            return jf.getJarEntry(Objects.requireNonNull(name));
+        }
+
+        @Override
+        Optional<URI> implFind(String name) throws IOException {
+            JarEntry je = getEntry(name);
+            if (je != null) {
+                String encodedPath = ParseUtil.encodePath(name, false);
+                String uris = "jar:" + uri + "!/" + encodedPath;
+                return Optional.of(URI.create(uris));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        Optional<InputStream> implOpen(String name) throws IOException {
+            JarEntry je = getEntry(name);
+            if (je != null) {
+                return Optional.of(jf.getInputStream(je));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        void implClose() throws IOException {
+            jf.close();
+        }
+    }
+
+
+    /**
+     * A ModuleReader for a JMOD file.
+     */
+    static class JModModuleReader extends SafeCloseModuleReader {
+        private final ZipFile zf;
+        private final URI uri;
+
+        static ZipFile newZipFile(Path path) {
+            try {
+                return new ZipFile(path.toFile());
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            }
+        }
+
+        JModModuleReader(Path path, URI uri) {
+            this.zf = newZipFile(path);
+            this.uri = uri;
+        }
+
+        private ZipEntry getEntry(String name) {
+            return zf.getEntry("classes/" + Objects.requireNonNull(name));
+        }
+
+        @Override
+        Optional<URI> implFind(String name) {
+            ZipEntry ze = getEntry(name);
+            if (ze != null) {
+                String encodedPath = ParseUtil.encodePath(name, false);
+                String uris = "jmod:" + uri + "!/" + encodedPath;
+                return Optional.of(URI.create(uris));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        Optional<InputStream> implOpen(String name) throws IOException {
+            ZipEntry ze = getEntry(name);
+            if (ze != null) {
+                return Optional.of(zf.getInputStream(ze));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        void implClose() throws IOException {
+            zf.close();
+        }
+    }
+
+
+    /**
+     * A ModuleReader for an exploded module.
+     */
+    static class ExplodedModuleReader implements ModuleReader {
+        private final Path dir;
+        private volatile boolean closed;
+
+        ExplodedModuleReader(Path dir) {
+            this.dir = dir;
+
+            // when running with a security manager then check that the caller
+            // has access to the directory.
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                boolean unused = Files.isDirectory(dir);
+            }
+        }
+
+        /**
+         * Returns a Path to access to the given resource.
+         */
+        private Path toPath(String name) {
+            Path path = Paths.get(name.replace('/', File.separatorChar));
+            if (path.getRoot() == null) {
+                return dir.resolve(path);
+            } else {
+                // drop the root component so that the resource is
+                // located relative to the module directory
+                int n = path.getNameCount();
+                return (n > 0) ? dir.resolve(path.subpath(0, n)) : null;
+            }
+        }
+
+        /**
+         * Throws IOException if the module reader is closed;
+         */
+        private void ensureOpen() throws IOException {
+            if (closed) throw new IOException("ModuleReader is closed");
+        }
+
+        @Override
+        public Optional<URI> find(String name) throws IOException {
+            ensureOpen();
+            Path path = toPath(name);
+            if (path != null && Files.isRegularFile(path)) {
+                try {
+                    return Optional.of(path.toUri());
+                } catch (IOError e) {
+                    throw (IOException) e.getCause();
+                }
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public Optional<InputStream> open(String name) throws IOException {
+            ensureOpen();
+            Path path = toPath(name);
+            if (path != null && Files.isRegularFile(path)) {
+                return Optional.of(Files.newInputStream(path));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public Optional<ByteBuffer> read(String name) throws IOException {
+            ensureOpen();
+            Path path = toPath(name);
+            if (path != null && Files.isRegularFile(path)) {
+                return Optional.of(ByteBuffer.wrap(Files.readAllBytes(path)));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public void close() {
+            closed = true;
+        }
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ResolutionException.java b/jdk/src/java.base/share/classes/java/lang/module/ResolutionException.java
new file mode 100644
index 0000000..fb14cfe
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ResolutionException.java
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+/**
+ * Thrown when resolving a set of modules or binding fails.
+ *
+ * @see Configuration
+ * @since 9
+ */
+public class ResolutionException extends RuntimeException {
+    private static final long serialVersionUID = -1031186845316729450L;
+
+    /**
+     * Constructs a {@code ResolutionException} with no detail message.
+     */
+    public ResolutionException() { }
+
+    /**
+     * Constructs a {@code ResolutionException} with the given detail
+     * message.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     */
+    public ResolutionException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs an instance of this exception with the given cause.
+     *
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public ResolutionException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a {@code ResolutionException} with the given detail message
+     * and cause.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public ResolutionException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ResolvedModule.java b/jdk/src/java.base/share/classes/java/lang/module/ResolvedModule.java
new file mode 100644
index 0000000..05ef3c4
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/ResolvedModule.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A module in a graph of <em>resolved modules</em>.
+ *
+ * <p> {@code ResolvedModule} defines the {@link #configuration configuration}
+ * method to get the configuration that the resolved module is in. It defines
+ * the {@link #reference() reference} method to get the reference to the
+ * module's content.
+ *
+ * @since 9
+ * @see Configuration#modules()
+ */
+public final class ResolvedModule {
+
+    private final Configuration cf;
+    private final ModuleReference mref;
+
+    ResolvedModule(Configuration cf, ModuleReference mref) {
+        this.cf = Objects.requireNonNull(cf);
+        this.mref = Objects.requireNonNull(mref);
+    }
+
+    /**
+     * Returns the configuration that this resolved module is in.
+     *
+     * @return The configuration that this resolved module is in
+     */
+    public Configuration configuration() {
+        return cf;
+    }
+
+    /**
+     * Returns the reference to the module's content.
+     *
+     * @return The reference to the module's content
+     */
+    public ModuleReference reference() {
+        return mref;
+    }
+
+    /**
+     * Returns the module descriptor.
+     *
+     * This convenience method is the equivalent to invoking:
+     * <pre> {@code
+     *     reference().descriptor()
+     * }</pre>
+     *
+     * @return The module descriptor
+     */
+    ModuleDescriptor descriptor() {
+        return reference().descriptor();
+    }
+
+    /**
+     * Returns the module name.
+     *
+     * This convenience method is the equivalent to invoking:
+     * <pre> {@code
+     *     reference().descriptor().name()
+     * }</pre>
+     *
+     * @return The module name
+     */
+    public String name() {
+        return reference().descriptor().name();
+    }
+
+    /**
+     * Returns the set of resolved modules that this resolved module reads.
+     *
+     * @return A possibly-empty unmodifiable set of resolved modules that
+     *         this resolved module reads
+     */
+    public Set<ResolvedModule> reads() {
+        return cf.reads(this);
+    }
+
+    /**
+     * Computes a hash code for this resolved module.
+     *
+     * <p> The hash code is based upon the components of the resolved module
+     * and satisfies the general contract of the {@link Object#hashCode
+     * Object.hashCode} method. </p>
+     *
+     * @return The hash-code value for this resolved module
+     */
+    @Override
+    public int hashCode() {
+        return cf.hashCode() ^ mref.hashCode();
+    }
+
+    /**
+     * Tests this resolved module for equality with the given object.
+     *
+     * <p> If the given object is not a {@code ResolvedModule} then this
+     * method returns {@code false}. Two {@code ResolvedModule} objects are
+     * equal if they are in the same configuration and have equal references
+     * to the module content. </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
+     *          reference that is equal to this module reference
+     */
+    @Override
+    public boolean equals(Object ob) {
+        if (!(ob instanceof ResolvedModule))
+            return false;
+
+        ResolvedModule that = (ResolvedModule) ob;
+        return Objects.equals(this.cf, that.cf)
+                && Objects.equals(this.mref, that.mref);
+    }
+
+    /**
+     * Returns a string describing this resolved module.
+     *
+     * @return A string describing this resolved module
+     */
+    @Override
+    public String toString() {
+        return System.identityHashCode(cf) + "/" + name();
+    }
+
+}
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
new file mode 100644
index 0000000..37eb0b1b
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
@@ -0,0 +1,823 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.reflect.Layer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+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.StringJoiner;
+import java.util.stream.Collectors;
+
+import jdk.internal.module.Hasher;
+
+/**
+ * The resolver used by {@link Configuration#resolveRequires} and
+ * {@link Configuration#resolveRequiresAndUses}.
+ */
+
+final class Resolver {
+
+    private final ModuleFinder beforeFinder;
+    private final Configuration parent;
+    private final ModuleFinder afterFinder;
+
+    // maps module name to module reference
+    private final Map<String, ModuleReference> nameToReference = new HashMap<>();
+
+
+    Resolver(ModuleFinder beforeFinder,
+             Configuration parent,
+             ModuleFinder afterFinder) {
+        this.beforeFinder = beforeFinder;
+        this.parent = parent;
+        this.afterFinder = afterFinder;
+    }
+
+
+    /**
+     * Resolves the given named modules.
+     *
+     * @throws ResolutionException
+     */
+    Resolver resolveRequires(Collection<String> roots) {
+
+        long start = trace_start("Resolve");
+
+        // create the visit stack to get us started
+        Deque<ModuleDescriptor> q = new ArrayDeque<>();
+        for (String root : roots) {
+
+            // find root module
+            ModuleReference mref = findWithBeforeFinder(root);
+            if (mref == null) {
+                if (parent.findModule(root).isPresent()) {
+                    // in parent, nothing to do
+                    continue;
+                }
+                mref = findWithAfterFinder(root);
+                if (mref == null) {
+                    fail("Module %s not found", root);
+                }
+            }
+
+            if (TRACE) {
+                trace("Root module %s located", root);
+                if (mref.location().isPresent())
+                    trace("  (%s)", mref.location().get());
+            }
+
+            assert mref.descriptor().name().equals(root);
+            nameToReference.put(root, mref);
+            q.push(mref.descriptor());
+        }
+
+        resolve(q);
+
+        if (TRACE) {
+            long duration = System.currentTimeMillis() - start;
+            Set<String> names = nameToReference.keySet();
+            trace("Resolver completed in %s ms", duration);
+            names.stream().sorted().forEach(name -> trace("  %s", name));
+        }
+
+        return this;
+    }
+
+    /**
+     * Resolve all modules in the given queue. On completion the queue will be
+     * empty and any resolved modules will be added to {@code nameToReference}.
+     *
+     * @return The set of module resolved by this invocation of resolve
+     */
+    private Set<ModuleDescriptor> resolve(Deque<ModuleDescriptor> q) {
+        Set<ModuleDescriptor> resolved = new HashSet<>();
+
+        while (!q.isEmpty()) {
+            ModuleDescriptor descriptor = q.poll();
+            assert nameToReference.containsKey(descriptor.name());
+
+            // process dependences
+            for (ModuleDescriptor.Requires requires : descriptor.requires()) {
+                String dn = requires.name();
+
+                // find dependence
+                ModuleReference mref = findWithBeforeFinder(dn);
+                if (mref == null) {
+                    if (parent.findModule(dn).isPresent())
+                        continue;
+
+                    mref = findWithAfterFinder(dn);
+                    if (mref == null) {
+                        fail("Module %s not found, required by %s",
+                                dn, descriptor.name());
+                    }
+                }
+
+                if (!nameToReference.containsKey(dn)) {
+                    nameToReference.put(dn, mref);
+                    q.offer(mref.descriptor());
+                    resolved.add(mref.descriptor());
+
+                    if (TRACE) {
+                        trace("Module %s located, required by %s",
+                                dn, descriptor.name());
+                        if (mref.location().isPresent())
+                            trace("  (%s)", mref.location().get());
+                    }
+                }
+
+            }
+
+            resolved.add(descriptor);
+        }
+
+        return resolved;
+    }
+
+    /**
+     * Augments the set of resolved modules with modules induced by the
+     * service-use relation.
+     */
+    Resolver resolveUses() {
+
+        long start = trace_start("Bind");
+
+        // Scan the finders for all available service provider modules. As
+        // java.base uses services then then module finders will be scanned
+        // anyway.
+        Map<String, Set<ModuleReference>> availableProviders = new HashMap<>();
+        for (ModuleReference mref : findAll()) {
+            ModuleDescriptor descriptor = mref.descriptor();
+            if (!descriptor.provides().isEmpty()) {
+
+                for (String sn : descriptor.provides().keySet()) {
+                    // computeIfAbsent
+                    Set<ModuleReference> providers = availableProviders.get(sn);
+                    if (providers == null) {
+                        providers = new HashSet<>();
+                        availableProviders.put(sn, providers);
+                    }
+                    providers.add(mref);
+                }
+
+            }
+        }
+
+        // create the visit stack
+        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);
+        }
+        for (ModuleReference mref : nameToReference.values()) {
+            candidateConsumers.add(mref.descriptor());
+        }
+
+
+        // Where there is a consumer of a service then resolve all modules
+        // that provide an implementation of that service
+        do {
+            for (ModuleDescriptor descriptor : candidateConsumers) {
+                if (!descriptor.uses().isEmpty()) {
+                    for (String service : descriptor.uses()) {
+                        Set<ModuleReference> mrefs = availableProviders.get(service);
+                        if (mrefs != null) {
+                            for (ModuleReference mref : mrefs) {
+                                ModuleDescriptor provider = mref.descriptor();
+                                if (!provider.equals(descriptor)) {
+
+                                    trace("Module %s provides %s, used by %s",
+                                            provider.name(), service, descriptor.name());
+
+                                    String pn = provider.name();
+                                    if (!nameToReference.containsKey(pn)) {
+
+                                        if (TRACE && mref.location().isPresent())
+                                            trace("  (%s)", mref.location().get());
+
+                                        nameToReference.put(pn, mref);
+                                        q.push(provider);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            candidateConsumers = resolve(q);
+
+        } while (!candidateConsumers.isEmpty());
+
+
+        if (TRACE) {
+            long duration = System.currentTimeMillis() - start;
+            Set<String> names = nameToReference.keySet();
+            trace("Bind completed in %s ms", duration);
+            names.stream().sorted().forEach(name -> trace("  %s", name));
+        }
+
+        return this;
+    }
+
+
+    /**
+     * Execute post-resolution checks and returns the module graph of resolved
+     * modules as {@code Map}. The resolved modules will be in the given
+     * configuration.
+     */
+    Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf) {
+
+        detectCycles();
+
+        checkPlatformConstraints();
+
+        checkHashes();
+
+        Map<ResolvedModule, Set<ResolvedModule>> graph = makeGraph(cf);
+
+        checkExportSuppliers(graph);
+
+        return graph;
+    }
+
+
+    /**
+     * Checks the given module graph for cycles.
+     *
+     * For now the implementation is a simple depth first search on the
+     * dependency graph. We'll replace this later, maybe with Tarjan.
+     */
+    private void detectCycles() {
+        visited = new HashSet<>();
+        visitPath = new LinkedHashSet<>(); // preserve insertion order
+        for (ModuleReference mref : nameToReference.values()) {
+            visit(mref.descriptor());
+        }
+        visited.clear();
+    }
+
+    // the modules that were visited
+    private Set<ModuleDescriptor> visited;
+
+    // the modules in the current visit path
+    private Set<ModuleDescriptor> visitPath;
+
+    private void visit(ModuleDescriptor descriptor) {
+        if (!visited.contains(descriptor)) {
+            boolean added = visitPath.add(descriptor);
+            if (!added) {
+                throw new ResolutionException("Cycle detected: " +
+                        cycleAsString(descriptor));
+            }
+            for (ModuleDescriptor.Requires requires : descriptor.requires()) {
+                String dn = requires.name();
+
+                ModuleReference mref = nameToReference.get(dn);
+                if (mref != null) {
+                    ModuleDescriptor other = mref.descriptor();
+                    if (other != descriptor) {
+                        // dependency is in this configuration
+                        visit(other);
+                    }
+                }
+            }
+            visitPath.remove(descriptor);
+            visited.add(descriptor);
+        }
+    }
+
+    /**
+     * Returns a String with a list of the modules in a detected cycle.
+     */
+    private String cycleAsString(ModuleDescriptor descriptor) {
+        List<ModuleDescriptor> list = new ArrayList<>(visitPath);
+        list.add(descriptor);
+        int index = list.indexOf(descriptor);
+        return list.stream()
+                .skip(index)
+                .map(ModuleDescriptor::name)
+                .collect(Collectors.joining(" -> "));
+    }
+
+
+    /**
+     * If there are platform specific modules then check that the OS name,
+     * architecture and version match.
+     *
+     * @apiNote This method does not currently check if the OS matches
+     *          platform specific modules in parent configurations.
+     */
+    private void checkPlatformConstraints() {
+
+        // first module encountered that is platform specific
+        String savedModuleName = null;
+        String savedOsName = null;
+        String savedOsArch = null;
+        String savedOsVersion = null;
+
+        for (ModuleReference mref : nameToReference.values()) {
+            ModuleDescriptor descriptor = mref.descriptor();
+
+            String osName = descriptor.osName().orElse(null);
+            String osArch = descriptor.osArch().orElse(null);
+            String osVersion = descriptor.osVersion().orElse(null);
+
+            if (osName != null || osArch != null || osVersion != null) {
+
+                if (savedModuleName == null) {
+
+                    savedModuleName = descriptor.name();
+                    savedOsName = osName;
+                    savedOsArch = osArch;
+                    savedOsVersion = osVersion;
+
+                } else {
+
+                    boolean matches = platformMatches(osName, savedOsName)
+                            && platformMatches(osArch, savedOsArch)
+                            && platformMatches(osVersion, savedOsVersion);
+
+                    if (!matches) {
+                        String s1 = platformAsString(savedOsName,
+                                                     savedOsArch,
+                                                     savedOsVersion);
+
+                        String s2 = platformAsString(osName, osArch, osVersion);
+                        fail("Mismatching constraints on target platform: "
+                                + savedModuleName + ": " + s1
+                                + ", " + descriptor.name() + ": " + s2);
+                    }
+
+                }
+
+            }
+        }
+
+    }
+
+    /**
+     * Returns true if the s1 and s2 are equal or one of them is null.
+     */
+    private boolean platformMatches(String s1, String s2) {
+        if (s1 == null || s2 == null)
+            return true;
+        else
+            return Objects.equals(s1, s2);
+    }
+
+    /**
+     * Return a string that encodes the OS name/arch/version.
+     */
+    private String platformAsString(String osName,
+                                    String osArch,
+                                    String osVersion) {
+
+        return new StringJoiner("-")
+                .add(Objects.toString(osName, "*"))
+                .add(Objects.toString(osArch, "*"))
+                .add(Objects.toString(osVersion, "*"))
+                .toString();
+
+    }
+
+
+    /**
+     * Checks the hashes in the module descriptor to ensure that they match
+     * the hash of the dependency's module reference.
+     */
+    private void checkHashes() {
+
+        for (ModuleReference mref : nameToReference.values()) {
+            ModuleDescriptor descriptor = mref.descriptor();
+
+            // get map of module names to hash
+            Optional<Hasher.DependencyHashes> ohashes = descriptor.hashes();
+            if (!ohashes.isPresent())
+                continue;
+            Hasher.DependencyHashes hashes = ohashes.get();
+
+            // check dependences
+            for (ModuleDescriptor.Requires d : descriptor.requires()) {
+                String dn = d.name();
+                String recordedHash = hashes.hashFor(dn);
+
+                if (recordedHash != null) {
+
+                    ModuleReference other = nameToReference.get(dn);
+                    if (other == null) {
+                        other = parent.findModule(dn)
+                                .map(ResolvedModule::reference)
+                                .orElse(null);
+                    }
+                    if (other == null)
+                        throw new InternalError(dn + " not found");
+
+                    String actualHash = other.computeHash(hashes.algorithm());
+                    if (actualHash == null)
+                        fail("Unable to compute the hash of module %s", dn);
+
+                    if (!recordedHash.equals(actualHash)) {
+                        fail("Hash of %s (%s) differs to expected hash (%s)",
+                                dn, actualHash, recordedHash);
+                    }
+
+                }
+
+            }
+        }
+
+    }
+
+
+    /**
+     * Computes and sets the readability graph for the modules in the given
+     * Resolution object.
+     *
+     * 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.
+     *
+     * TODO: Use a more efficient algorithm, maybe cache the requires public
+     *       in parent configurations.
+     */
+    private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
+
+        // 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<>();
+
+        // the "requires public" graph, contains requires public edges only
+        Map<ResolvedModule, Set<ResolvedModule>> g2 = new HashMap<>();
+
+
+        // need "requires public" 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()) {
+                ResolvedModule x = p.findModule(descriptor.name()).orElse(null);
+                if (x == null)
+                    throw new InternalError();
+                for (ModuleDescriptor.Requires requires : descriptor.requires()) {
+                    if (requires.modifiers().contains(Modifier.PUBLIC)) {
+                        String dn = requires.name();
+                        ResolvedModule y = p.findModule(dn).orElse(null);
+                        if (y == null)
+                            throw new InternalError(dn + " not found");
+                        g2.computeIfAbsent(x, k -> new HashSet<>()).add(y);
+                    }
+                }
+            }
+
+            p = p.parent().orElse(null);
+        }
+
+        // populate g1 and g2 with the dependences from the selected modules
+        for (ModuleReference mref : nameToReference.values()) {
+            ModuleDescriptor descriptor = mref.descriptor();
+            ResolvedModule x = new ResolvedModule(cf, mref);
+
+            Set<ResolvedModule> reads = new HashSet<>();
+            g1.put(x, reads);
+
+            Set<ResolvedModule> requiresPublic = new HashSet<>();
+            g2.put(x, requiresPublic);
+
+            for (ModuleDescriptor.Requires requires : descriptor.requires()) {
+                String dn = requires.name();
+
+                ResolvedModule y;
+                ModuleReference other = nameToReference.get(dn);
+                if (other != null) {
+                    y = new ResolvedModule(cf, other);  // cache?
+                } else {
+                    y = parent.findModule(dn).orElse(null);
+                    if (y == null)
+                        throw new InternalError("unable to find " + dn);
+                }
+
+                // m requires other => m reads other
+                reads.add(y);
+
+                // m requires public other
+                if (requires.modifiers().contains(Modifier.PUBLIC)) {
+                    requiresPublic.add(y);
+                }
+
+            }
+
+            // automatic modules reads all selected modules and all modules
+            // in parent configurations
+            if (descriptor.isAutomatic()) {
+                String name = descriptor.name();
+
+                // reads all selected modules
+                // requires public` all selected automatic modules
+                for (ModuleReference mref2 : nameToReference.values()) {
+                    ModuleDescriptor descriptor2 = mref2.descriptor();
+                    if (!name.equals(descriptor2.name())) {
+                        ResolvedModule m = new ResolvedModule(cf, mref2);
+                        reads.add(m);
+                        if (descriptor2.isAutomatic())
+                            requiresPublic.add(m);
+                    }
+                }
+
+                // 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);
+                }
+
+            }
+
+        }
+
+        // Iteratively update g1 until there are no more requires public to propagate
+        boolean changed;
+        Map<ResolvedModule, Set<ResolvedModule>> changes = new HashMap<>();
+        do {
+            changed = false;
+            for (Entry<ResolvedModule, Set<ResolvedModule>> entry : g1.entrySet()) {
+
+                ResolvedModule m1 = entry.getKey();
+                Set<ResolvedModule> m1Reads = entry.getValue();
+
+                for (ResolvedModule m2 : m1Reads) {
+                    Set<ResolvedModule> m2RequiresPublic = g2.get(m2);
+                    if (m2RequiresPublic != null) {
+                        for (ResolvedModule m3 : m2RequiresPublic) {
+                            if (!m1Reads.contains(m3)) {
+
+                                // computeIfAbsent
+                                Set<ResolvedModule> s = changes.get(m1);
+                                if (s == null) {
+                                    s = new HashSet<>();
+                                    changes.put(m1, s);
+                                }
+                                s.add(m3);
+                                changed = true;
+
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (changed) {
+                for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e :
+                        changes.entrySet()) {
+                    ResolvedModule m = e.getKey();
+                    g1.get(m).addAll(e.getValue());
+                }
+                changes.clear();
+            }
+
+        } while (changed);
+
+
+        return g1;
+    }
+
+
+    /**
+     * Checks the readability graph to ensure that no two modules export the
+     * same package to a module. This includes the case where module M has
+     * a local package P and M reads another module that exports P to M.
+     * Also checks the uses/provides of module M to ensure that it reads a
+     * module that exports the package of the service type to M.
+     */
+    private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
+
+        for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
+            ModuleDescriptor descriptor1 = e.getKey().descriptor();
+
+            // the map of packages that are local or exported to descriptor1
+            Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
+
+            // local packages
+            Set<String> packages = descriptor1.packages();
+            for (String pn : packages) {
+                packageToExporter.put(pn, descriptor1);
+            }
+
+            // descriptor1 reads descriptor2
+            Set<ResolvedModule> reads = e.getValue();
+            for (ResolvedModule endpoint : reads) {
+                ModuleDescriptor descriptor2 = endpoint.descriptor();
+
+                for (ModuleDescriptor.Exports export : descriptor2.exports()) {
+
+                    if (export.isQualified()) {
+                        if (!export.targets().contains(descriptor1.name()))
+                            continue;
+                    }
+
+                    // source is exported to descriptor2
+                    String source = export.source();
+                    ModuleDescriptor other
+                            = packageToExporter.put(source, descriptor2);
+
+                    if (other != null && other != descriptor2) {
+                        // package might be local to descriptor1
+                        if (other == descriptor1) {
+                            fail("Module %s contains package %s"
+                                 + ", module %s exports package %s to %s",
+                                    descriptor1.name(),
+                                    source,
+                                    descriptor2.name(),
+                                    source,
+                                    descriptor1.name());
+                        } else {
+                            fail("Modules %s and %s export package %s to module %s",
+                                    descriptor2.name(),
+                                    other.name(),
+                                    source,
+                                    descriptor1.name());
+                        }
+
+                    }
+                }
+            }
+
+            // uses S
+            for (String service : descriptor1.uses()) {
+                String pn = packageName(service);
+                if (!packageToExporter.containsKey(pn)) {
+                    fail("Module %s does not read a module that exports %s",
+                            descriptor1.name(), pn);
+                }
+            }
+
+            // 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);
+                if (!packageToExporter.containsKey(pn)) {
+                    fail("Module %s does not read a module that exports %s",
+                            descriptor1.name(), pn);
+                }
+
+                for (String provider : provides.providers()) {
+                    if (!packages.contains(packageName(provider))) {
+                        fail("Provider %s not in module %s",
+                                provider, descriptor1.name());
+                    }
+                }
+            }
+
+        }
+
+    }
+
+
+    /**
+     * Invokes the beforeFinder to find method to find the given module.
+     */
+    private ModuleReference findWithBeforeFinder(String mn) {
+        try {
+            return beforeFinder.find(mn).orElse(null);
+        } catch (FindException e) {
+            // unwrap
+            throw new ResolutionException(e.getMessage(), e.getCause());
+        }
+    }
+
+    /**
+     * Invokes the afterFinder to find method to find the given module.
+     */
+    private ModuleReference findWithAfterFinder(String mn) {
+        try {
+            return afterFinder.find(mn).orElse(null);
+        } catch (FindException e) {
+            // unwrap
+            throw new ResolutionException(e.getMessage(), e.getCause());
+        }
+    }
+
+    /**
+     * Returns the set of all modules that are observable with the before
+     * and after ModuleFinders.
+     */
+    private Set<ModuleReference> findAll() {
+        try {
+
+            Set<ModuleReference> beforeModules = beforeFinder.findAll();
+            Set<ModuleReference> afterModules = afterFinder.findAll();
+
+            if (afterModules.isEmpty())
+                return beforeModules;
+
+            if (beforeModules.isEmpty() && parent == 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())
+                    result.add(mref);
+            }
+
+            return result;
+
+        } catch (FindException e) {
+            // unwrap
+            throw new ResolutionException(e.getMessage(), e.getCause());
+        }
+    }
+
+    /**
+     * Returns the package name
+     */
+    private static String packageName(String cn) {
+        int index = cn.lastIndexOf(".");
+        return (index == -1) ? "" : cn.substring(0, index);
+    }
+
+    /**
+     * Throw ResolutionException with the given format string and arguments
+     */
+    private static void fail(String fmt, Object ... args) {
+        String msg = String.format(fmt, args);
+        throw new ResolutionException(msg);
+    }
+
+
+    /**
+     * Tracing support, limited to boot layer for now.
+     */
+
+    private final static boolean TRACE
+        = Boolean.getBoolean("jdk.launcher.traceResolver")
+            && (Layer.boot() == null);
+
+    private String op;
+
+    private long trace_start(String op) {
+        this.op = op;
+        return System.currentTimeMillis();
+    }
+
+    private void trace(String fmt, Object ... args) {
+        if (TRACE) {
+            System.out.print("[" + op + "] ");
+            System.out.format(fmt, args);
+            System.out.println();
+        }
+    }
+
+}
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
new file mode 100644
index 0000000..67766f9
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.module;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import jdk.internal.jimage.ImageLocation;
+import jdk.internal.jimage.ImageReader;
+import jdk.internal.jimage.ImageReaderFactory;
+import jdk.internal.module.SystemModules;
+import jdk.internal.module.ModulePatcher;
+import jdk.internal.perf.PerfCounter;
+
+/**
+ * A {@code ModuleFinder} that finds modules that are linked into the
+ * run-time image.
+ *
+ * The modules linked into the run-time image are assumed to have the
+ * ConcealedPackages attribute.
+ */
+
+class SystemModuleFinder implements ModuleFinder {
+
+    private static final PerfCounter initTime
+        = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
+    private static final PerfCounter moduleCount
+        = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules");
+    private static final PerfCounter packageCount
+        = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages");
+    private static final PerfCounter exportsCount
+        = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports");
+    // ImageReader used to access all modules in the image
+    private static final ImageReader imageReader;
+
+    // the set of modules in the run-time image
+    private static final Set<ModuleReference> modules;
+
+    // maps module name to module reference
+    private static final Map<String, ModuleReference> nameToModule;
+
+    /**
+     * For now, the module references are created eagerly on the assumption
+     * that service binding will require all modules to be located.
+     */
+    static {
+        long t0 = System.nanoTime();
+        imageReader = ImageReaderFactory.getImageReader();
+
+        String[] moduleNames = SystemModules.MODULE_NAMES;
+        ModuleDescriptor[] descriptors = null;
+
+        boolean fastLoad = System.getProperty("jdk.installed.modules.disable") == null;
+        if (fastLoad) {
+            // fast loading of ModuleDescriptor of installed modules
+            descriptors = SystemModules.modules();
+        }
+
+        int n = moduleNames.length;
+        moduleCount.add(n);
+
+        Set<ModuleReference> mods = new HashSet<>(n);
+        Map<String, ModuleReference> map = new HashMap<>(n);
+
+        for (int i = 0; i < n; i++) {
+            String mn = moduleNames[i];
+            ModuleDescriptor md;
+            if (fastLoad) {
+                md = descriptors[i];
+            } else {
+                // fallback to read module-info.class
+                // if fast loading of ModuleDescriptors is disabled
+                ImageLocation location = imageReader.findLocation(mn, "module-info.class");
+                md = ModuleDescriptor.read(imageReader.getResourceBuffer(location));
+            }
+            if (!md.name().equals(mn))
+                throw new InternalError();
+
+            // create the ModuleReference
+
+            URI uri = URI.create("jrt:/" + mn);
+
+            Supplier<ModuleReader> readerSupplier = new Supplier<>() {
+                @Override
+                public ModuleReader get() {
+                    return new ImageModuleReader(mn, uri);
+                }
+            };
+
+            ModuleReference mref = new ModuleReference(md, uri, readerSupplier);
+
+            // may need a reference to a patched module if -Xpatch specified
+            mref = ModulePatcher.interposeIfNeeded(mref);
+
+            mods.add(mref);
+            map.put(mn, mref);
+
+            // counters
+            packageCount.add(md.packages().size());
+            exportsCount.add(md.exports().size());
+        }
+
+        modules = Collections.unmodifiableSet(mods);
+        nameToModule = map;
+
+        initTime.addElapsedTimeFrom(t0);
+    }
+
+    SystemModuleFinder() { }
+
+    @Override
+    public Optional<ModuleReference> find(String name) {
+        Objects.requireNonNull(name);
+        return Optional.ofNullable(nameToModule.get(name));
+    }
+
+    @Override
+    public Set<ModuleReference> findAll() {
+        return modules;
+    }
+
+
+    /**
+     * A ModuleReader for reading resources from a module linked into the
+     * run-time image.
+     */
+    static class ImageModuleReader implements ModuleReader {
+        private final String module;
+        private volatile boolean closed;
+
+        /**
+         * If there is a security manager set then check permission to
+         * connect to the run-time image.
+         */
+        private static void checkPermissionToConnect(URI uri) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                try {
+                    URLConnection uc = uri.toURL().openConnection();
+                    sm.checkPermission(uc.getPermission());
+                } catch (IOException ioe) {
+                    throw new UncheckedIOException(ioe);
+                }
+            }
+        }
+
+        ImageModuleReader(String module, URI uri) {
+            checkPermissionToConnect(uri);
+            this.module = module;
+        }
+
+        /**
+         * Returns the ImageLocation for the given resource, {@code null}
+         * if not found.
+         */
+        private ImageLocation findImageLocation(String name) throws IOException {
+            if (closed)
+                throw new IOException("ModuleReader is closed");
+
+            if (imageReader != null) {
+                return imageReader.findLocation(module, name);
+            } else {
+                // not an images build
+                return null;
+            }
+        }
+
+        @Override
+        public Optional<URI> find(String name) throws IOException {
+            ImageLocation location = findImageLocation(name);
+            if (location != null) {
+                URI u = URI.create("jrt:/" + module + "/" + name);
+                return Optional.of(u);
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public Optional<InputStream> open(String name) throws IOException {
+            return read(name).map(this::toInputStream);
+        }
+
+        private InputStream toInputStream(ByteBuffer bb) { // ## -> ByteBuffer?
+            try {
+                int rem = bb.remaining();
+                byte[] bytes = new byte[rem];
+                bb.get(bytes);
+                return new ByteArrayInputStream(bytes);
+            } finally {
+                release(bb);
+            }
+        }
+
+        @Override
+        public Optional<ByteBuffer> read(String name) throws IOException {
+            ImageLocation location = findImageLocation(name);
+            if (location != null) {
+                return Optional.of(imageReader.getResourceBuffer(location));
+            } else {
+                return Optional.empty();
+            }
+        }
+
+        @Override
+        public void release(ByteBuffer bb) {
+            ImageReader.releaseByteBuffer(bb);
+        }
+
+        @Override
+        public void close() {
+            // nothing else to do
+            closed = true;
+        }
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/module/package-info.java b/jdk/src/java.base/share/classes/java/lang/module/package-info.java
new file mode 100644
index 0000000..a1c44d6
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/module/package-info.java
@@ -0,0 +1,39 @@
+/*
+ * 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.  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.
+ */
+
+/**
+ * Classes to support module descriptors and creating configurations of modules
+ * by means of resolution and service binding.
+ *
+ * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method of any class or interface in this package will cause a {@link
+ * java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
+ * invoking a method with an array or collection containing a {@code null} element
+ * will cause a {@code NullPointerException}, unless otherwise specified. </p>
+ *
+ * @since 9
+ */
+
+package java.lang.module;
diff --git a/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java b/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
index ead17ef..3b8c2c9 100644
--- a/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
@@ -143,7 +143,7 @@
 
     /* Called by Runtime.runFinalization() */
     static void runFinalization() {
-        if (!VM.isBooted()) {
+        if (VM.initLevel() == 0) {
             return;
         }
 
@@ -166,7 +166,7 @@
 
     /* Invoked by java.lang.Shutdown */
     static void runAllFinalizers() {
-        if (!VM.isBooted()) {
+        if (VM.initLevel() == 0) {
             return;
         }
 
@@ -201,10 +201,10 @@
 
             // Finalizer thread starts before System.initializeSystemClass
             // is called.  Wait until JavaLangAccess is available
-            while (!VM.isBooted()) {
+            while (VM.initLevel() == 0) {
                 // delay until VM completes initialization
                 try {
-                    VM.awaitBooted();
+                    VM.awaitInitLevel(1);
                 } catch (InterruptedException x) {
                     // ignore and continue
                 }
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 506e27d..5b1545d 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
 package java.lang.reflect;
 
 import java.security.AccessController;
+
+import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.ReflectionFactory;
 import java.lang.annotation.Annotation;
@@ -34,11 +36,14 @@
  * The AccessibleObject class is the base class for Field, Method and
  * Constructor objects.  It provides the ability to flag a reflected
  * object as suppressing default Java language access control checks
- * when it is used.  The access checks--for public, default (package)
- * access, protected, and private members--are performed when Fields,
- * Methods or Constructors are used to set or get fields, to invoke
- * methods, or to create and initialize new instances of classes,
- * respectively.
+ * when it is used. The access checks -- <em>module boundaries</em>,
+ * public, default (package) access, protected, and private members --
+ * are performed when Fields, Methods or Constructors are used to set
+ * or get fields, to invoke methods or to create and initialize new
+ * instances of classes, respectively. Unlike access control specified
+ * in the <cite>The Java&trade; Language Specification</cite> and
+ * <cite>The Java Virtual Machine Specification</cite>, access checks
+ * with reflected objects assume {@link Module#canRead readability}.
  *
  * <p>Setting the {@code accessible} flag in a reflected object
  * permits sophisticated applications with sufficient privilege, such
@@ -64,37 +69,49 @@
     private static final java.security.Permission ACCESS_PERMISSION =
         new ReflectPermission("suppressAccessChecks");
 
+    static void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
+    }
+
     /**
      * Convenience method to set the {@code accessible} flag for an
      * array of objects with a single security check (for efficiency).
      *
-     * <p>First, if there is a security manager, its
-     * {@code checkPermission} method is called with a
+     * <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}.
+     *
+     * <p>If there is a security manager, its
+     * {@code checkPermission} method is first called with a
      * {@code ReflectPermission("suppressAccessChecks")} permission.
      *
-     * <p>A {@code SecurityException} is raised if {@code flag} is
-     * {@code true} but accessibility of any of the elements of the input
-     * {@code array} may not be changed (for example, if the element
-     * object is a {@link Constructor} object for the class {@link
-     * java.lang.Class}).  In the event of such a SecurityException, the
-     * accessibility of objects is set to {@code flag} for array elements
-     * up to (and excluding) the element for which the exception occurred; the
-     * accessibility of elements beyond (and including) the element for which
-     * the exception occurred is unchanged.
+     * <p>A {@code SecurityException} is also thrown if any of the elements of
+     * the input {@code array} is a {@link java.lang.reflect.Constructor}
+     * object for the class {@code java.lang.Class} and {@code flag} is true.
      *
      * @param array the array of AccessibleObjects
      * @param flag  the new value for the {@code accessible} flag
      *              in each object
+     * @throws InaccessibleObjectException if access cannot be enabled
      * @throws SecurityException if the request is denied.
      * @see SecurityManager#checkPermission
-     * @see java.lang.RuntimePermission
+     * @see ReflectPermission
      */
-    public static void setAccessible(AccessibleObject[] array, boolean flag)
-        throws SecurityException {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
+    @CallerSensitive
+    public static void setAccessible(AccessibleObject[] array, boolean flag) {
+        checkPermission();
+        if (flag) {
+            Class<?> caller = Reflection.getCallerClass();
+            array = array.clone();
+            for (AccessibleObject ao : array) {
+                ao.checkCanSetAccessible(caller);
+            }
+        }
         for (AccessibleObject ao : array) {
-            setAccessible0(ao, flag);
+            ao.setAccessible0(flag);
         }
     }
 
@@ -103,45 +120,87 @@
      * the indicated boolean value.  A value of {@code true} indicates that
      * the reflected object should suppress Java language access
      * checking when it is used.  A value of {@code false} indicates
-     * that the reflected object should enforce Java language access checks.
+     * that the reflected object should enforce Java language access checks
+     * while assuming readability (as noted in the class description).
      *
-     * <p>First, if there is a security manager, its
-     * {@code checkPermission} method is called with a
+     * <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}.
+     *
+     * <p>If there is a security manager, its
+     * {@code checkPermission} method is first called with a
      * {@code ReflectPermission("suppressAccessChecks")} permission.
      *
-     * <p>A {@code SecurityException} is raised if {@code flag} is
-     * {@code true} but accessibility of this object may not be changed
-     * (for example, if this element object is a {@link Constructor} object for
-     * the class {@link java.lang.Class}).
-     *
-     * <p>A {@code SecurityException} is raised if this object is a {@link
-     * java.lang.reflect.Constructor} object for the class
-     * {@code java.lang.Class}, and {@code flag} is true.
-     *
      * @param flag the new value for the {@code accessible} flag
-     * @throws SecurityException if the request is denied.
+     * @throws InaccessibleObjectException if access cannot be enabled
+     * @throws SecurityException if the request is denied
      * @see SecurityManager#checkPermission
-     * @see java.lang.RuntimePermission
+     * @see ReflectPermission
      */
-    public void setAccessible(boolean flag) throws SecurityException {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
-        setAccessible0(this, flag);
+    public void setAccessible(boolean flag) {
+        AccessibleObject.checkPermission();
+        setAccessible0(flag);
     }
 
-    /* Check that you aren't exposing java.lang.Class.<init> or sensitive
-       fields in java.lang.Class. */
-    private static void setAccessible0(AccessibleObject obj, boolean flag)
-        throws SecurityException
-    {
-        if (obj instanceof Constructor && flag == true) {
-            Constructor<?> c = (Constructor<?>)obj;
-            if (c.getDeclaringClass() == Class.class) {
-                throw new SecurityException("Cannot make a java.lang.Class" +
-                                            " constructor accessible");
+    void setAccessible0(boolean flag) {
+        this.override = flag;
+    }
+
+   /**
+    * If the given AccessibleObject is a {@code Constructor}, {@code Method}
+    * or {@code Field} then checks that its declaring class is in a package
+    * that can be accessed by the given caller of setAccessible.
+    */
+    void checkCanSetAccessible(Class<?> caller) {
+        // do nothing, needs to be overridden by Constructor, Method, Field
+    }
+
+    void checkCanSetAccessible(Class<?> caller, Class<?> declaringClass) {
+        Module callerModule = caller.getModule();
+        Module declaringModule = declaringClass.getModule();
+
+        if (callerModule != declaringModule
+                && callerModule != Object.class.getModule()) {
+
+            // 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);
+            }
+
+        }
+
+        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);
             }
         }
-        obj.override = flag;
+    }
+
+    /**
+     * Returns the package name of the given class.
+     */
+    private static String packageName(Class<?> c) {
+        while (c.isArray()) {
+            c = c.getComponentType();
+        }
+        String pn = c.getPackageName();
+        return (pn != null) ? pn : "";
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
index 2e24d47..4b38728 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
@@ -159,6 +159,35 @@
         return res;
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p> A {@code SecurityException} is also thrown if this object is a
+     * {@code Constructor} object for the class {@code Class} and {@code flag}
+     * is true. </p>
+     *
+     * @param flag {@inheritDoc}
+     */
+    @Override
+    @CallerSensitive
+    public void setAccessible(boolean flag) {
+        AccessibleObject.checkPermission();
+        if (flag) {
+            checkCanSetAccessible(Reflection.getCallerClass());
+        }
+        setAccessible0(flag);
+    }
+
+    @Override
+    void checkCanSetAccessible(Class<?> caller) {
+        checkCanSetAccessible(caller, clazz);
+        if (clazz == Class.class) {
+            // can we change this to InaccessibleObjectException?
+            throw new SecurityException("Cannot make a java.lang.Class"
+                                        + " constructor accessible");
+        }
+    }
+
     @Override
     boolean hasGenericInformation() {
         return (getSignature() != null);
@@ -411,10 +440,8 @@
                IllegalArgumentException, InvocationTargetException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, null, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, null, modifiers);
         }
         if ((clazz.getModifiers() & Modifier.ENUM) != 0)
             throw new IllegalArgumentException("Cannot reflectively create enum objects");
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
index ff99cf91..062676f 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
@@ -157,10 +157,24 @@
         return res;
     }
 
+    @Override
+    @CallerSensitive
+    public void setAccessible(boolean flag) {
+        AccessibleObject.checkPermission();
+        if (flag) checkCanSetAccessible(Reflection.getCallerClass());
+        setAccessible0(flag);
+    }
+
+    @Override
+    void checkCanSetAccessible(Class<?> caller) {
+        checkCanSetAccessible(caller, clazz);
+    }
+
     /**
      * Returns the {@code Class} object representing the class or interface
      * that declares the field represented by this {@code Field} object.
      */
+    @Override
     public Class<?> getDeclaringClass() {
         return clazz;
     }
@@ -386,10 +400,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).get(obj);
     }
@@ -421,10 +433,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getBoolean(obj);
     }
@@ -456,10 +466,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getByte(obj);
     }
@@ -493,10 +501,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getChar(obj);
     }
@@ -530,10 +536,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getShort(obj);
     }
@@ -567,10 +571,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getInt(obj);
     }
@@ -604,10 +606,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getLong(obj);
     }
@@ -641,10 +641,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getFloat(obj);
     }
@@ -678,10 +676,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         return getFieldAccessor(obj).getDouble(obj);
     }
@@ -757,10 +753,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).set(obj, value);
     }
@@ -794,10 +788,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setBoolean(obj, z);
     }
@@ -831,10 +823,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setByte(obj, b);
     }
@@ -868,10 +858,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setChar(obj, c);
     }
@@ -905,10 +893,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setShort(obj, s);
     }
@@ -942,10 +928,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setInt(obj, i);
     }
@@ -979,10 +963,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setLong(obj, l);
     }
@@ -1016,10 +998,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setFloat(obj, f);
     }
@@ -1053,10 +1033,8 @@
         throws IllegalArgumentException, IllegalAccessException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         getFieldAccessor(obj).setDouble(obj, d);
     }
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java b/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java
new file mode 100644
index 0000000..d44d589
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * Thrown when Java language access checks cannot be suppressed.
+ *
+ * @see AccessibleObject#setAccessible(boolean)
+ * @since 9
+ */
+
+public class InaccessibleObjectException extends RuntimeException {
+    private static final long serialVersionUID = 4158786093378140901L;
+
+    /**
+     * Constructs a {@code InaccessibleObjectException} with no detail message.
+     */
+    public InaccessibleObjectException() {
+    }
+
+    /**
+     * Constructs a {@code InaccessibleObjectException} with the given detail
+     * message.
+     *
+     * @param msg
+     *        The detail message
+     */
+    public InaccessibleObjectException(String msg) {
+        super(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
new file mode 100644
index 0000000..3dde971
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
@@ -0,0 +1,552 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ResolvedModule;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import jdk.internal.loader.Loader;
+import jdk.internal.loader.LoaderPool;
+import jdk.internal.misc.SharedSecrets;
+import sun.security.util.SecurityConstants;
+
+
+/**
+ * A layer of modules in the Java virtual machine.
+ *
+ * <p> A layer is created from a graph of modules that is the {@link
+ * Configuration} and a function that maps each module to a {@link ClassLoader}.
+ * 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>
+ *
+ * <p> Creating a layer creates a {@link Module} object for each {@link
+ * ResolvedModule} in the configuration. For each resolved module that is
+ * {@link ResolvedModule#reads() read}, the {@code Module} {@link
+ * Module#canRead reads} the corresponding run-time {@code Module}, which may
+ * be in the same layer or a parent layer. The {@code Module} {@link
+ * Module#isExported(String) exports} the packages described by its {@link
+ * ModuleDescriptor}. </p>
+ *
+ * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
+ * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
+ * provide convenient ways to create a {@code Layer} where all modules are
+ * 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>
+ *
+ * <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
+ * started. The <em>system modules</em>, including {@code java.base}, are in
+ * the boot layer. The modules in the boot layer are mapped to the bootstrap
+ * class loader and other class loaders that are built-in into the ava virtual
+ * machine. The boot layer will often be the {@link #parent() parent} when
+ * creating additional layers. </p>
+ *
+ * <p> As when creating a {@code Configuration},
+ * {@link ModuleDescriptor#isAutomatic() automatic} modules receive
+ * <a href="../module/Configuration.html#automaticmoduleresolution">special
+ * treatment</a> when creating a layer. An automatic module is created in the
+ * Java virtual machine as a {@code Module} that reads every unnamed {@code
+ * Module} in the Java virtual machine. </p>
+ *
+ * <p> Unless otherwise specified, passing a {@code null} argument to a method
+ * in this class causes a {@link NullPointerException NullPointerException} to
+ * be thrown. </p>
+ *
+ * <h3> Example usage: </h3>
+ *
+ * <p> This example creates a configuration by resolving a module named
+ * "{@code myapp}" with the configuration for the boot layer as the parent. It
+ * then creates a new layer with the modules in this configuration. All modules
+ * are defined to the same class loader. </p>
+ *
+ * <pre>{@code
+ *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
+ *
+ *     Layer parent = Layer.boot();
+ *
+ *     Configuration cf = parent.configuration()
+ *         .resolveRequires(finder, ModuleFinder.empty(), Set.of("myapp"));
+ *
+ *     ClassLoader scl = ClassLoader.getSystemClassLoader();
+ *
+ *     Layer layer = parent.defineModulesWithOneLoader(cf, scl);
+ *
+ *     Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
+ * }</pre>
+ *
+ * @since 9
+ * @see Module#getLayer()
+ */
+
+public final class Layer {
+
+    // the empty Layer
+    private static final Layer EMPTY_LAYER
+        = new Layer(Configuration.empty(), null, 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;
+
+    // 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,
+                  Function<String, ClassLoader> clf)
+    {
+        this.cf = cf;
+        this.parent = parent;
+
+        Map<String, Module> map;
+        if (parent == null) {
+            map = Collections.emptyMap();
+        } else {
+            map = Module.defineModules(cf, clf, this);
+        }
+        this.nameToModule = map; // no need to do defensive copy
+    }
+
+
+    /**
+     * 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.
+     *
+     * <p> The class loader created by this method implements <em>direct
+     * delegation</em> when loading types from modules. When its {@link
+     * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
+     * load a class then it uses the package name of the class to map it to a
+     * module. This may be a module in this layer and hence defined to the same
+     * class loader. It may be a package in a module in a parent layer that is
+     * exported to one or more of the modules in this layer. The class
+     * loader delegates to the class loader of the module, throwing {@code
+     * ClassNotFoundException} if not found by that class loader.
+     *
+     * When {@code loadClass} is invoked to load classes that do not map to a
+     * module then it delegates to the parent class loader. </p>
+     *
+     * <p> Attempting to create a layer with all modules defined to the same
+     * class loader can fail for the following reasons:
+     *
+     * <ul>
+     *
+     *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
+     *     configuration have the same package (exported or concealed). </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
+     *     in a specific package. </p></li>
+     *
+     * </ul>
+     *
+     * <p> If there is a security manager then the class loader created by
+     * this method will load classes and resources with privileges that are
+     * restricted by the calling context of this method. </p>
+     *
+     * @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
+     * @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)
+    {
+        checkConfiguration(cf);
+        checkCreateClassLoaderPermission();
+        checkGetClassLoaderPermission();
+
+        Loader loader;
+        try {
+            loader = new Loader(cf.modules(), parentLoader);
+            loader.initRemotePackageMap(cf, this);
+        } catch (IllegalArgumentException e) {
+            throw new LayerInstantiationException(e.getMessage());
+        }
+        return new Layer(cf, this, mn -> loader);
+    }
+
+
+    /**
+     * 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.
+     *
+     * <p> The class loaders created by this method implement <em>direct
+     * delegation</em> when loading types from modules. When {@link
+     * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
+     * load a class then it uses the package name of the class to map it to a
+     * module. The package may be in the module defined to the class loader.
+     * The package may be exported by another module in this layer to the
+     * module defined to the class loader. It may be in a package exported by a
+     * module in a parent layer. The class loader delegates to the class loader
+     * of the module, throwing {@code ClassNotFoundException} if not found by
+     * that class loader.
+     *
+     * When {@code loadClass} is invoked to load classes that do not map to a
+     * module then it delegates to the parent class loader. </p>
+     *
+     * <p> If there is a security manager then the class loaders created by
+     * this method will load classes and resources with privileges that are
+     * restricted by the calling context of this method. </p>
+     *
+     * @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 SecurityException
+     *         If {@code RuntimePermission("createClassLoader")} or
+     *         {@code RuntimePermission("getClassLoader")} is denied by
+     *         the security manager
+     *
+     * @see #findLoader
+     */
+    public Layer defineModulesWithManyLoaders(Configuration cf,
+                                              ClassLoader parentLoader)
+    {
+        checkConfiguration(cf);
+        checkCreateClassLoaderPermission();
+        checkGetClassLoaderPermission();
+
+        LoaderPool pool = new LoaderPool(cf, this, parentLoader);
+        return new Layer(cf, this, pool::loaderFor);
+    }
+
+
+    /**
+     * 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. 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.
+     *
+     * <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> A module is mapped to a class loader that already has a
+     *     module of the same name defined to it. </p></li>
+     *
+     *     <li><p> A module is mapped to a class loader that has already
+     *     defined types in any of the packages in the module. </p></li>
+     *
+     * </ul>
+     *
+     * <p> If the function to map a module name to class loader throws an error
+     * or runtime exception then it is propagated to the caller of this method.
+     * </p>
+     *
+     * @apiNote It is implementation specific as to whether creating a Layer
+     * with this method is an atomic operation or not. Consequentially it is
+     * possible for this method to fail with some modules, but not all, defined
+     * to Java virtual machine.
+     *
+     * @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
+     * @throws SecurityException
+     *         If {@code RuntimePermission("getClassLoader")} is denied by
+     *         the security manager
+     */
+    public Layer defineModules(Configuration cf,
+                               Function<String, ClassLoader> clf)
+    {
+        checkConfiguration(cf);
+        Objects.requireNonNull(clf);
+
+        checkGetClassLoaderPermission();
+
+        // For now, no two modules in the boot Layer may contain the same
+        // package so we use a simple check for the boot Layer to keep
+        // the overhead at startup to a minimum
+        if (boot() == null) {
+            checkBootModulesForDuplicatePkgs(cf);
+        } else {
+            checkForDuplicatePkgs(cf, clf);
+        }
+
+        try {
+            return new Layer(cf, this, clf);
+        } catch (IllegalArgumentException iae) {
+            // IAE is thrown by VM when defining the module fails
+            throw new LayerInstantiationException(iae.getMessage());
+        }
+    }
+
+
+    private void checkConfiguration(Configuration cf) {
+        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");
+        }
+    }
+
+    private static void checkCreateClassLoaderPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
+    }
+
+    private static void checkGetClassLoaderPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+    }
+
+    /**
+     * Checks a configuration for the boot Layer to ensure that no two modules
+     * have the same package.
+     *
+     * @throws LayerInstantiationException
+     */
+    private static void checkBootModulesForDuplicatePkgs(Configuration cf) {
+        Map<String, String> packageToModule = new HashMap<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
+            String name = descriptor.name();
+            for (String p : descriptor.packages()) {
+                String other = packageToModule.putIfAbsent(p, name);
+                if (other != null) {
+                    throw fail("Package " + p + " in both module "
+                               + name + " and module " + other);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks a configuration and the module-to-loader mapping to ensure that
+     * no two modules mapped to the same class loader have the same package.
+     * It also checks that no two automatic modules have the same package.
+     *
+     * @throws LayerInstantiationException
+     */
+    private static void checkForDuplicatePkgs(Configuration cf,
+                                              Function<String, ClassLoader> clf)
+    {
+        // HashMap allows null keys
+        Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
+            ClassLoader loader = clf.apply(descriptor.name());
+
+            Set<String> loaderPackages
+                = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
+
+            for (String pkg : descriptor.packages()) {
+                boolean added = loaderPackages.add(pkg);
+                if (!added) {
+                    throw fail("More than one module with package %s mapped" +
+                               " to the same class loader", pkg);
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates a LayerInstantiationException with the a message formatted from
+     * the given format string and arguments.
+     */
+    private static LayerInstantiationException fail(String fmt, Object ... args) {
+        String msg = String.format(fmt, args);
+        return new LayerInstantiationException(msg);
+    }
+
+
+    /**
+     * Returns the configuration for this layer.
+     *
+     * @return The configuration for this layer
+     */
+    public Configuration configuration() {
+        return cf;
+    }
+
+
+    /**
+     * Returns this layer's parent unless this is the {@linkplain #empty empty
+     * layer}, which has no parent.
+     *
+     * @return This layer's parent
+     */
+    public Optional<Layer> parent() {
+        return Optional.ofNullable(parent);
+    }
+
+
+    /**
+     * Returns a set of the modules in this layer.
+     *
+     * @return A possibly-empty unmodifiable set of the modules in this layer
+     */
+    public Set<Module> modules() {
+        return Collections.unmodifiableSet(
+                nameToModule.values().stream().collect(Collectors.toSet()));
+    }
+
+
+    /**
+     * Returns the module with the given name in this layer, or if not in this
+     * layer, the {@linkplain #parent parent} layer.
+     *
+     * @param  name
+     *         The name of the module to find
+     *
+     * @return The module with the given name or an empty {@code Optional}
+     *         if there isn't a module with this name in this layer or any
+     *         parent layer
+     */
+    public Optional<Module> findModule(String name) {
+        Module m = nameToModule.get(Objects.requireNonNull(name));
+        if (m != null)
+            return Optional.of(m);
+        return parent().flatMap(l -> l.findModule(name));
+    }
+
+
+    /**
+     * 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.
+     *
+     * <p> If there is a security manager then its {@code checkPermission}
+     * method is called with a {@code RuntimePermission("getClassLoader")}
+     * permission to check that the caller is allowed to get access to the
+     * class loader. </p>
+     *
+     * @apiNote This method does not return an {@code Optional<ClassLoader>}
+     * because `null` must be used to represent the bootstrap class loader.
+     *
+     * @param  name
+     *         The name of the module to find
+     *
+     * @return The ClassLoader that the module is defined to
+     *
+     * @throws IllegalArgumentException if a module of the given name is not
+     *         defined in this layer or any parent of this layer
+     *
+     * @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");
+    }
+
+
+    /**
+     * Returns the <em>empty</em> layer. There are no modules in the empty
+     * layer. It has no parent.
+     *
+     * @return The empty layer
+     */
+    public static Layer empty() {
+        return EMPTY_LAYER;
+    }
+
+
+    /**
+     * Returns the boot layer. The boot layer contains at least one module,
+     * {@code java.base}. Its parent is the {@link #empty() empty} layer.
+     *
+     * @apiNote This method returns {@code null} during startup and before
+     *          the boot layer is fully initialized.
+     *
+     * @return The boot layer
+     */
+    public static Layer boot() {
+        return SharedSecrets.getJavaLangAccess().getBootLayer();
+    }
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/LayerInstantiationException.java b/jdk/src/java.base/share/classes/java/lang/reflect/LayerInstantiationException.java
new file mode 100644
index 0000000..ff61c41
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/LayerInstantiationException.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+/**
+ * Thrown when creating a Layer fails.
+ *
+ * @see Layer
+ *
+ * @since 9
+ */
+public class LayerInstantiationException extends RuntimeException {
+    private static final long serialVersionUID = -906239691613568347L;
+
+    /**
+     * Constructs a {@code LayerInstantiationException} with no detail message.
+     */
+    public LayerInstantiationException() {
+    }
+
+    /**
+     * Constructs a {@code LayerInstantiationException} with the given detail
+     * message.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     */
+    public LayerInstantiationException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a {@code LayerInstantiationException} with the given cause.
+     *
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public LayerInstantiationException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a {@code FindException} with the given detail message
+     * and cause.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     * @param cause
+     *        The cause; can be {@code null}
+     */
+    public LayerInstantiationException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+}
+
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
index c4a1db2..005ed24 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
@@ -176,6 +176,19 @@
         return res;
     }
 
+    @Override
+    @CallerSensitive
+    public void setAccessible(boolean flag) {
+        AccessibleObject.checkPermission();
+        if (flag) checkCanSetAccessible(Reflection.getCallerClass());
+        setAccessible0(flag);
+    }
+
+    @Override
+    void checkCanSetAccessible(Class<?> caller) {
+        checkCanSetAccessible(caller, clazz);
+    }
+
     /**
      * Used by Excecutable for annotation sharing.
      */
@@ -508,10 +521,8 @@
            InvocationTargetException
     {
         if (!override) {
-            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
-                Class<?> caller = Reflection.getCallerClass();
-                checkAccess(caller, clazz, obj, modifiers);
-            }
+            Class<?> caller = Reflection.getCallerClass();
+            checkAccess(caller, clazz, obj, modifiers);
         }
         MethodAccessor ma = methodAccessor;             // read volatile
         if (ma == null) {
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
new file mode 100644
index 0000000..406e3a3
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
@@ -0,0 +1,1216 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.Version;
+import java.lang.module.ResolvedModule;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.loader.BootLoader;
+import jdk.internal.misc.JavaLangReflectModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ServicesCatalog;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+import sun.security.util.SecurityConstants;
+
+/**
+ * Represents a run-time module, either {@link #isNamed() named} or unnamed.
+ *
+ * <p> Named modules have a {@link #getName() name} and are constructed by the
+ * Java Virtual Machine when a graph of modules is defined to the Java virtual
+ * machine to create a module {@link Layer Layer}. </p>
+ *
+ * <p> An unnamed module does not have a name. There is an unnamed module
+ * per {@link ClassLoader ClassLoader} that is obtained by invoking the class
+ * loader's {@link ClassLoader#getUnnamedModule() getUnnamedModule} method. The
+ * {@link Class#getModule() getModule} method of all types defined by a class
+ * loader that are not in a named module return the class loader's unnamed
+ * module. </p>
+ *
+ * <p> The package names that are parameters or returned by methods defined in
+ * this class are the fully-qualified names of the packages as defined in
+ * section 6.5.3 of <cite>The Java&trade; Language Specification </cite>, for
+ * example, {@code "java.lang"}. </p>
+ *
+ * <p> Unless otherwise specified, passing a {@code null} argument to a method
+ * in this class causes a {@link NullPointerException NullPointerException} to
+ * be thrown. </p>
+ *
+ * @since 9
+ * @see java.lang.Class#getModule
+ */
+
+public final class Module {
+
+    // the layer that contains this module, can be null
+    private final Layer layer;
+
+    // module name and loader, these fields are read by VM
+    private final String name;
+    private final ClassLoader loader;
+
+    // the module descriptor
+    private final ModuleDescriptor descriptor;
+
+
+    /**
+     * Creates a new named Module. The resulting Module will be defined to the
+     * VM but will not read any other modules, will not have any exports setup
+     * and will not be registered in the service catalog.
+     */
+    private Module(Layer layer,
+                   ClassLoader loader,
+                   ModuleDescriptor descriptor,
+                   URI uri)
+    {
+        this.layer = layer;
+        this.name = descriptor.name();
+        this.loader = loader;
+        this.descriptor = descriptor;
+
+        // define module to VM
+
+        Set<String> packages = descriptor.packages();
+        int n = packages.size();
+        String[] array = new String[n];
+        int i = 0;
+        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);
+    }
+
+
+    /**
+     * Create the unnamed Module for the given ClassLoader.
+     *
+     * @see ClassLoader#getUnnamedModule
+     */
+    private Module(ClassLoader loader) {
+        this.layer = null;
+        this.name = null;
+        this.loader = loader;
+        this.descriptor = null;
+
+        // unnamed modules are loose
+        this.loose = true;
+    }
+
+
+    /**
+     * Creates a named module but without defining the module to the VM.
+     *
+     * @apiNote This constructor is for VM white-box testing.
+     */
+    Module(ClassLoader loader, ModuleDescriptor descriptor) {
+        this.layer = null;
+        this.name = descriptor.name();
+        this.loader = loader;
+        this.descriptor = descriptor;
+    }
+
+
+
+    /**
+     * Returns {@code true} if this module is a named module.
+     *
+     * @return {@code true} if this is a named module
+     *
+     * @see ClassLoader#getUnnamedModule()
+     */
+    public boolean isNamed() {
+        return name != null;
+    }
+
+    /**
+     * Returns the module name or {@code null} if this module is an unnamed
+     * module.
+     *
+     * @return The module name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the {@code ClassLoader} for this module.
+     *
+     * <p> If there is a security manager then its {@code checkPermission}
+     * method if first called with a {@code RuntimePermission("getClassLoader")}
+     * permission to check that the caller is allowed to get access to the
+     * class loader. </p>
+     *
+     * @return The class loader for this module
+     *
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    public ClassLoader getClassLoader() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+        }
+        return loader;
+    }
+
+    /**
+     * Returns the module descriptor for this module or {@code null} if this
+     * module is an unnamed module.
+     *
+     * @return The module descriptor for this module
+     */
+    public ModuleDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * Returns the layer that contains this module or {@code null} if this
+     * module is not in a layer.
+     *
+     * A module {@code Layer} contains named modules and therefore this
+     * method always returns {@code null} when invoked on an unnamed module.
+     *
+     * <p> <a href="Proxy.html#dynamicmodule">Dynamic modules</a> are named
+     * modules that are generated at runtime. A dynamic module may or may
+     * not be in a module Layer. </p>
+     *
+     * @return The layer that contains this module
+     *
+     * @see Proxy
+     */
+    public Layer getLayer() {
+        if (isNamed()) {
+            Layer layer = this.layer;
+            if (layer != null)
+                return layer;
+
+            // special-case java.base as it is created before the boot Layer
+            if (loader == null && name.equals("java.base")) {
+                return SharedSecrets.getJavaLangAccess().getBootLayer();
+            }
+        }
+
+        return null;
+    }
+
+
+    // -- readability --
+
+    // true if this module reads all unnamed modules (a.k.a. loose module)
+    private volatile boolean loose;
+
+    // the modules that this module permanently reads
+    // (will be final when the modules are defined in reverse topology order)
+    private volatile Set<Module> reads;
+
+    // created lazily, additional modules that this module reflectively reads
+    private volatile WeakSet<Module> transientReads;
+
+
+    /**
+     * Indicates if this module reads the given module. This method returns
+     * {@code true} if invoked to test if this module reads itself. It also
+     * returns {@code true} if invoked on an unnamed module (as unnamed
+     * modules read all modules).
+     *
+     * @param  other
+     *         The other module
+     *
+     * @return {@code true} if this module reads {@code other}
+     *
+     * @see #addReads(Module)
+     */
+    public boolean canRead(Module other) {
+        Objects.requireNonNull(other);
+
+        // an unnamed module reads all modules
+        if (!this.isNamed())
+            return true;
+
+        // all modules read themselves
+        if (other == this)
+            return true;
+
+        // check if this module reads other
+        if (other.isNamed()) {
+
+            Set<Module> reads = this.reads; // volatile read
+            if (reads != null && reads.contains(other))
+                return true;
+
+        } else {
+
+            // loose modules read all unnamed modules
+            if (this.loose)
+                return true;
+
+        }
+
+        // check if this module reads the other module reflectively
+        WeakSet<Module> tr = this.transientReads; // volatile read
+        if (tr != null && tr.contains(other))
+            return true;
+
+        return false;
+    }
+
+    /**
+     * 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).
+     *
+     * @param  other
+     *         The other module
+     *
+     * @return this module
+     *
+     * @throws IllegalStateException
+     *         If this is a named module and the caller is not this module
+     *
+     * @see #canRead
+     */
+    @CallerSensitive
+    public Module addReads(Module other) {
+        Objects.requireNonNull(other);
+        if (this.isNamed()) {
+            Module caller = Reflection.getCallerClass().getModule();
+            if (caller != this) {
+                throw new IllegalStateException(caller + " != " + this);
+            }
+            implAddReads(other, true);
+        }
+        return this;
+    }
+
+    /**
+     * Updates this module to read another module.
+     *
+     * @apiNote This method is for Proxy use and white-box testing.
+     */
+    void implAddReads(Module other) {
+        implAddReads(other, true);
+    }
+
+    /**
+     * Makes the given {@code Module} readable to this module without
+     * notifying the VM.
+     *
+     * @apiNote This method is for VM white-box testing.
+     */
+    void implAddReadsNoSync(Module other) {
+        implAddReads(other, false);
+    }
+
+    /**
+     * Makes the given {@code Module} readable to this module.
+     *
+     * If {@code syncVM} is {@code true} then the VM is notified.
+     */
+    private void implAddReads(Module other, boolean syncVM) {
+
+        // nothing to do
+        if (other == this || !this.isNamed())
+            return;
+
+        // if the other is null then change this module to be loose.
+        if (other == null) {
+            if (syncVM)
+                addReads0(this, null);
+            this.loose = true;
+            return;
+        }
+
+        // check if we already read this module
+        Set<Module> reads = this.reads;
+        if (reads != null && reads.contains(other))
+            return;
+
+        // update VM first, just in case it fails
+        if (syncVM)
+            addReads0(this, other);
+
+        // add reflective read
+        WeakSet<Module> tr = this.transientReads;
+        if (tr == null) {
+            synchronized (this) {
+                tr = this.transientReads;
+                if (tr == null) {
+                    tr = new WeakSet<>();
+                    this.transientReads = tr;
+                }
+            }
+        }
+        tr.add(other);
+    }
+
+
+    // -- exports --
+
+    // 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;
+
+    // created lazily, additional exports added at run-time
+    private volatile Map<String, WeakSet<Module>> transientExports;
+
+    // the special Module to mean exported to all modules
+    private static final Module EVERYONE_MODULE = new Module(null);
+    private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
+
+    // the special Module to mean exported to all unnamed modules
+    private static final Module ALL_UNNAMED_MODULE = new Module(null);
+
+
+    /**
+     * 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
+     * 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 exports the package to at least the
+     *         given module
+     */
+    public boolean isExported(String pn, Module other) {
+        Objects.requireNonNull(pn);
+        Objects.requireNonNull(other);
+        return implIsExported(pn, other);
+    }
+
+    /**
+     * 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 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
+     */
+    public boolean isExported(String pn) {
+        Objects.requireNonNull(pn);
+        return implIsExported(pn, EVERYONE_MODULE);
+    }
+
+    /**
+     * 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.
+     */
+    private boolean implIsExported(String pn, Module other) {
+
+        // all packages are exported by unnamed modules
+        if (!isNamed())
+            return true;
+
+        // exported via module declaration/descriptor
+        if (isExportedPermanently(pn, other))
+            return true;
+
+        // exported via addExports
+        if (isExportedReflectively(pn, other))
+            return true;
+
+        // not exported or not exported to other
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this module permanently exports the given
+     * package to the given module.
+     */
+    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) {
+
+                // exported to all modules
+                if (targets.contains(EVERYONE_MODULE))
+                    return true;
+
+                if (other != EVERYONE_MODULE) {
+                    // exported to other
+                    if (targets.contains(other))
+                        return true;
+
+                    // other is an unnamed module && exported to all unnamed
+                    if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
+                        return true;
+                }
+
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this module reflectively exports the given
+     * package package to the given module.
+     */
+    private boolean isExportedReflectively(String pn, Module other) {
+        Map<String, WeakSet<Module>> te = this.transientExports;
+        if (te != null) {
+            WeakSet<Module> targets = te.get(pn);
+
+            if (targets != null) {
+
+                // exported to all modules
+                if (targets.contains(EVERYONE_MODULE))
+                    return true;
+
+                if (other != EVERYONE_MODULE) {
+
+                    // exported to other
+                    if (targets.contains(other))
+                        return true;
+
+                    // other is an unnamed module && exported to all unnamed
+                    if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
+                        return true;
+                }
+            }
+
+        }
+        return false;
+    }
+
+
+    /**
+     * If the caller's module is this module then update this module to export
+     * package {@code pn} to the given module.
+     *
+     * <p> This method has no effect if the package is already exported to the
+     * given module. If also has no effect if invoked on an unnamed module (as
+     * unnamed modules export all packages). </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
+     */
+    @CallerSensitive
+    public Module addExports(String pn, Module other) {
+        if (pn == null)
+            throw new IllegalArgumentException("package is null");
+        Objects.requireNonNull(other);
+
+        if (isNamed()) {
+            Module caller = Reflection.getCallerClass().getModule();
+            if (caller != this) {
+                throw new IllegalStateException(caller + " != " + this);
+            }
+            implAddExports(pn, other, true);
+        }
+
+        return this;
+    }
+
+    /**
+     * Updates the exports so that package {@code pn} is exported to module
+     * {@code other} but without notifying the VM.
+     *
+     * @apiNote This method is for VM white-box testing.
+     */
+    void implAddExportsNoSync(String pn, Module other) {
+        if (other == null)
+            other = EVERYONE_MODULE;
+        implAddExports(pn.replace('/', '.'), other, false);
+    }
+
+    /**
+     * Updates the exports so that package {@code pn} is exported to module
+     * {@code other}.
+     *
+     * @apiNote This method is for white-box testing.
+     */
+    void implAddExports(String pn, Module other) {
+        implAddExports(pn, other, true);
+    }
+
+    /**
+     * Updates the exports so that package {@code pn} is exported to module
+     * {@code other}.
+     *
+     * If {@code syncVM} is {@code true} then the VM is notified.
+     */
+    private void implAddExports(String pn, Module other, boolean syncVM) {
+        Objects.requireNonNull(other);
+        Objects.requireNonNull(pn);
+
+        // unnamed modules export all packages
+        if (!isNamed())
+            return;
+
+        // nothing to do if already exported to other
+        if (implIsExported(pn, other))
+            return;
+
+        // can only export a package in the module
+        if (!containsPackage(pn)) {
+            throw new IllegalArgumentException("package " + pn
+                                               + " not in contents");
+        }
+
+        // update VM first, just in case it fails
+        if (syncVM) {
+            String pkgInternalForm = pn.replace('.', '/');
+            if (other == EVERYONE_MODULE) {
+                addExportsToAll0(this, pkgInternalForm);
+            } else if (other == ALL_UNNAMED_MODULE) {
+                addExportsToAllUnnamed0(this, pkgInternalForm);
+            } else {
+                addExports0(this, pkgInternalForm, other);
+            }
+        }
+
+        // create transientExports if needed
+        Map<String, WeakSet<Module>> te = this.transientExports; // read
+        if (te == null) {
+            synchronized (this) {
+                te = this.transientExports;
+                if (te == null) {
+                    te = new ConcurrentHashMap<>();
+                    this.transientExports = te;  // volatile write
+                }
+            }
+        }
+
+        // add package name to transientExports if absent
+        WeakSet<Module> s = te.get(pn);
+        if (s == null) {
+            s = new WeakSet<>();
+            WeakSet<Module> prev = te.putIfAbsent(pn, s);
+            if (prev != null)
+                s = prev;
+        }
+        s.add(other);
+    }
+
+
+    // -- services --
+
+    // created lazily, additional service types that this module uses
+    private volatile WeakSet<Class<?>> transientUses;
+
+    /**
+     * If the caller's module is this module then update this module to add a
+     * service dependence on the given service type. This method is intended
+     * 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.
+     *
+     * <p> This method does not cause {@link
+     * Configuration#resolveRequiresAndUses resolveRequiresAndUses} to be
+     * re-run. </p>
+     *
+     * @param  st
+     *         The service type
+     *
+     * @return this module
+     *
+     * @throws IllegalStateException
+     *         If this is a named module and the caller is not this module
+     *
+     * @see #canUse(Class)
+     * @see ModuleDescriptor#uses()
+     */
+    @CallerSensitive
+    public Module addUses(Class<?> st) {
+        Objects.requireNonNull(st);
+
+        if (isNamed()) {
+
+            Module caller = Reflection.getCallerClass().getModule();
+            if (caller != this) {
+                throw new IllegalStateException(caller + " != " + this);
+            }
+
+            if (!canUse(st)) {
+                WeakSet<Class<?>> uses = this.transientUses;
+                if (uses == null) {
+                    synchronized (this) {
+                        uses = this.transientUses;
+                        if (uses == null) {
+                            uses = new WeakSet<>();
+                            this.transientUses = uses;
+                        }
+                    }
+                }
+                uses.add(st);
+            }
+
+        }
+
+        return this;
+    }
+
+    /**
+     * 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.
+     *
+     * @param  st
+     *         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);
+
+        if (!isNamed())
+            return true;
+
+        if (descriptor.isAutomatic())
+            return true;
+
+        // uses was declared
+        if (descriptor.uses().contains(st.getName()))
+            return true;
+
+        // uses added via addUses
+        WeakSet<Class<?>> uses = this.transientUses;
+        if (uses != null && uses.contains(st))
+            return true;
+
+        return false;
+    }
+
+
+
+    // -- packages --
+
+    // Additional packages that are added to the module at run-time.
+    // The field is volatile as it may be replaced at run-time
+    private volatile Set<String> extraPackages;
+
+    private boolean containsPackage(String pn) {
+        if (descriptor.packages().contains(pn))
+            return true;
+        Set<String> extraPackages = this.extraPackages;
+        if (extraPackages != null && extraPackages.contains(pn))
+            return true;
+        return false;
+    }
+
+
+    /**
+     * Returns an array of the package names of the packages in this module.
+     *
+     * <p> For named modules, the returned array contains an element for each
+     * package in the module. It may contain elements corresponding to packages
+     * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
+     * for example, after it was loaded.
+     *
+     * <p> For unnamed modules, this method is the equivalent of invoking the
+     * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
+     * this module's class loader and returning the array of package names. </p>
+     *
+     * <p> A package name appears at most once in the returned array. </p>
+     *
+     * @apiNote This method returns an array rather than a {@code Set} for
+     * consistency with other {@code java.lang.reflect} types.
+     *
+     * @return an array of the package names of the packages in this module
+     */
+    public String[] getPackages() {
+        if (isNamed()) {
+
+            Set<String> packages = descriptor.packages();
+            Set<String> extraPackages = this.extraPackages;
+            if (extraPackages == null) {
+                return packages.toArray(new String[0]);
+            } else {
+                return Stream.concat(packages.stream(),
+                                     extraPackages.stream())
+                        .toArray(String[]::new);
+            }
+
+        } else {
+            // unnamed module
+            Stream<Package> packages;
+            if (loader == null) {
+                packages = BootLoader.packages();
+            } else {
+                packages = SharedSecrets.getJavaLangAccess().packages(loader);
+            }
+            return packages.map(Package::getName).toArray(String[]::new);
+        }
+    }
+
+    /**
+     * Add a package to this module.
+     *
+     * @apiNote This method is for Proxy use.
+     *
+     * @apiNote This is an expensive operation, not expected to be used often.
+     * At this time then it does not validate that the package name is a
+     * valid java identifier.
+     */
+    void addPackage(String pn) {
+        implAddPackage(pn, true);
+    }
+
+    /**
+     * Add a package to this module without notifying the VM.
+     *
+     * @apiNote This method is VM white-box testing.
+     */
+    void implAddPackageNoSync(String pn) {
+        implAddPackage(pn.replace('/', '.'), false);
+    }
+
+    /**
+     * Add a package to this module.
+     *
+     * 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 (descriptor.packages().contains(pn)) {
+            // already in module
+            return;
+        }
+
+        Set<String> extraPackages = this.extraPackages;
+        if (extraPackages != null && extraPackages.contains(pn)) {
+            // already added
+            return;
+        }
+        synchronized (this) {
+            // recheck under lock
+            extraPackages = this.extraPackages;
+            if (extraPackages != null) {
+                if (extraPackages.contains(pn)) {
+                    // already added
+                    return;
+                }
+
+                // copy the set
+                extraPackages = new HashSet<>(extraPackages);
+                extraPackages.add(pn);
+            } else {
+                extraPackages = Collections.singleton(pn);
+            }
+
+            // update VM first, just in case it fails
+            if (syncVM)
+                addPackage0(this, pn.replace('.', '/'));
+
+            // replace with new set
+            this.extraPackages = extraPackages; // volatile write
+        }
+    }
+
+
+    // -- creating Module objects --
+
+    /**
+     * Find the runtime Module corresponding to the given ReadDependence
+     * 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.
+     *
+     * @return a map of module name to runtime {@code Module}
+     *
+     * @throws IllegalArgumentException
+     *         If defining any of the modules to the VM fails
+     */
+    static Map<String, Module> defineModules(Configuration cf,
+                                             Function<String, ClassLoader> clf,
+                                             Layer layer)
+    {
+        Map<String, Module> modules = new HashMap<>();
+        Map<String, ClassLoader> loaders = new HashMap<>();
+
+        // 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);
+
+            Module m;
+            if (loader == null && name.equals("java.base")) {
+                m = Object.class.getModule();
+            } else {
+                m = new Module(layer, loader, descriptor, uri);
+            }
+
+            modules.put(name, m);
+            loaders.put(name, loader);
+        }
+
+        // setup readability and exports
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleReference mref = resolvedModule.reference();
+            ModuleDescriptor descriptor = mref.descriptor();
+
+            String mn = descriptor.name();
+            Module m = modules.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;
+                } else {
+                    m2 = find(d, layer.parent().orElse(null));
+                }
+
+                reads.add(m2);
+
+                // update VM view
+                addReads0(m, m2);
+            }
+            m.reads = reads;
+
+            // automatic modules reads all unnamed modules
+            if (descriptor.isAutomatic()) {
+                m.implAddReads(null, true);
+            }
+
+            // exports
+            Map<String, Set<Module>> exports = new HashMap<>();
+            for (Exports export : descriptor.exports()) {
+                String source = export.source();
+                String sourceInternalForm = source.replace('.', '/');
+
+                if (export.isQualified()) {
+
+                    // 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);
+                            addExports0(m, sourceInternalForm, 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);
+                }
+                catalog.register(m);
+            }
+        }
+
+        return modules;
+    }
+
+
+    // -- misc --
+
+
+    /**
+     * 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.
+     *
+     * <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.
+     *
+     * @param  name
+     *         The resource name
+     *
+     * @return An input stream for reading the resource or {@code null}
+     *
+     * @throws IOException
+     *         If an I/O error occurs
+     *
+     * @see java.lang.module.ModuleReader#open(String)
+     */
+    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);
+            }
+
+            // 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
+        if (url != null) {
+            try {
+                return url.openStream();
+            } catch (SecurityException e) { }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the string representation of this module. For a named module,
+     * the representation is the string {@code "module"}, followed by a space,
+     * and then the module name. For an unnamed module, the representation is
+     * the string {@code "unnamed module"}, followed by a space, and then an
+     * implementation specific identifier for the unnamed module.
+     *
+     * @return The string representation of this module
+     */
+    @Override
+    public String toString() {
+        if (isNamed()) {
+            return "module " + name;
+        } else {
+            String id = Integer.toHexString(System.identityHashCode(this));
+            return "unnamed module @" + id;
+        }
+    }
+
+
+    // -- supporting classes --
+
+
+    /**
+     * A "not-a-Set" set of weakly referenced objects that supports concurrent
+     * access.
+     */
+    private static class WeakSet<E> {
+        private final ReadWriteLock lock = new ReentrantReadWriteLock();
+        private final Lock readLock = lock.readLock();
+        private final Lock writeLock = lock.writeLock();
+
+        private final WeakHashMap<E, Boolean> map = new WeakHashMap<>();
+
+        /**
+         * Adds the specified element to the set.
+         */
+        void add(E e) {
+            writeLock.lock();
+            try {
+                map.put(e, Boolean.TRUE);
+            } finally {
+                writeLock.unlock();
+            }
+        }
+
+        /**
+         * Returns {@code true} if this set contains the specified element.
+         */
+        boolean contains(E e) {
+            readLock.lock();
+            try {
+                return map.containsKey(e);
+            } finally {
+                readLock.unlock();
+            }
+        }
+    }
+
+
+    // -- native methods --
+
+    // JVM_DefineModule
+    private static native void defineModule0(Module module,
+                                             String version,
+                                             String location,
+                                             String[] pns);
+
+    // JVM_AddReadsModule
+    private static native void addReads0(Module from, Module to);
+
+    // JVM_AddModuleExports
+    private static native void addExports0(Module from, String pn, Module to);
+
+    // JVM_AddModuleExportsToAll
+    private static native void addExportsToAll0(Module from, String pn);
+
+    // JVM_AddModuleExportsToAllUnnamed
+    private static native void addExportsToAllUnnamed0(Module from, String pn);
+
+    // JVM_AddModulePackage
+    private static native void addPackage0(Module m, String pn);
+
+    /**
+     * Register shared secret to provide access to package-private methods
+     */
+    static {
+        SharedSecrets.setJavaLangReflectModuleAccess(
+            new JavaLangReflectModuleAccess() {
+                @Override
+                public Module defineUnnamedModule(ClassLoader loader) {
+                    return new Module(loader);
+                }
+                @Override
+                public Module defineModule(ClassLoader loader,
+                                           ModuleDescriptor descriptor,
+                                           URI uri) {
+                   return new Module(null, loader, descriptor, uri);
+                }
+                @Override
+                public void addReads(Module m1, Module m2) {
+                    m1.implAddReads(m2, true);
+                }
+                @Override
+                public void addExports(Module m, String pn, Module other) {
+                    m.implAddExports(pn, Objects.requireNonNull(other), true);
+                }
+                @Override
+                public void addExportsToAll(Module m, String pn) {
+                    m.implAddExports(pn, Module.EVERYONE_MODULE, true);
+                }
+                @Override
+                public void addExportsToAllUnnamed(Module m, String pn) {
+                    m.implAddExports(pn, Module.ALL_UNNAMED_MODULE, true);
+                }
+                @Override
+                public void addPackage(Module m, String pn) {
+                    m.implAddPackage(pn, true);
+                }
+            });
+    }
+}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
index f6c6ebd..ca4a0fd 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
@@ -29,45 +29,48 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IdentityHashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.module.Modules;
 import jdk.internal.misc.VM;
+import sun.misc.Unsafe;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.util.SecurityConstants;
 
 /**
- * {@code Proxy} provides static methods for creating dynamic proxy
- * classes and instances, and it is also the superclass of all
- * dynamic proxy classes created by those methods.
  *
- * <p>To create a proxy for some interface {@code Foo}:
- * <pre>
+ * {@code Proxy} provides static methods for creating objects that act like instances
+ * of interfaces but allow for customized method invocation.
+ * To create a proxy instance for some interface {@code Foo}:
+ * <pre>{@code
  *     InvocationHandler handler = new MyInvocationHandler(...);
- *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
- *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
- *                     newInstance(handler);
- * </pre>
- * or more simply:
- * <pre>
  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- *                                          new Class&lt;?&gt;[] { Foo.class },
+ *                                          new Class<?>[] { Foo.class },
  *                                          handler);
- * </pre>
+ * }</pre>
  *
- * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
- * class</i> below) is a class that implements a list of interfaces
- * specified at runtime when the class is created, with behavior as
- * described below.
- *
- * A <i>proxy interface</i> is such an interface that is implemented
- * by a proxy class.
- *
- * A <i>proxy instance</i> is an instance of a proxy class.
+ * <p>
+ * A <em>proxy class</em> is a class created at runtime that implements a specified
+ * list of interfaces, known as <em>proxy interfaces</em>. A <em>proxy instance</em>
+ * is an instance of a proxy class.
  *
  * Each proxy instance has an associated <i>invocation handler</i>
  * object, which implements the interface {@link InvocationHandler}.
@@ -84,65 +87,41 @@
  * <p>A proxy class has the following properties:
  *
  * <ul>
- * <li>Proxy classes are <em>public, final, and not abstract</em> if
- * all proxy interfaces are public.</li>
- *
- * <li>Proxy classes are <em>non-public, final, and not abstract</em> if
- * any of the proxy interfaces is non-public.</li>
- *
  * <li>The unqualified name of a proxy class is unspecified.  The space
  * of class names that begin with the string {@code "$Proxy"}
  * should be, however, reserved for proxy classes.
  *
+ * <li>The package and module in which a proxy class is defined is specified
+ * <a href="#membership">below</a>.
+ *
+ * <li>A proxy class is <em>final and non-abstract</em>.
+ *
  * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
  *
  * <li>A proxy class implements exactly the interfaces specified at its
- * creation, in the same order.
- *
- * <li>If a proxy class implements a non-public interface, then it will
- * be defined in the same package as that interface.  Otherwise, the
- * package of a proxy class is also unspecified.  Note that package
- * sealing will not prevent a proxy class from being successfully defined
- * in a particular package at runtime, and neither will classes already
- * defined by the same class loader and the same package with particular
- * signers.
- *
- * <li>Since a proxy class implements all of the interfaces specified at
- * its creation, invoking {@code getInterfaces} on its
- * {@code Class} object will return an array containing the same
+ * creation, in the same order. Invoking {@link Class#getInterfaces getInterfaces}
+ * on its {@code Class} object will return an array containing the same
  * list of interfaces (in the order specified at its creation), invoking
- * {@code getMethods} on its {@code Class} object will return
+ * {@link Class#getMethods getMethods} on its {@code Class} object will return
  * an array of {@code Method} objects that include all of the
  * methods in those interfaces, and invoking {@code getMethod} will
  * find methods in the proxy interfaces as would be expected.
  *
- * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
- * return true if it is passed a proxy class-- a class returned by
- * {@code Proxy.getProxyClass} or the class of an object returned by
- * {@code Proxy.newProxyInstance}-- and false otherwise.
- *
- * <li>The {@code java.security.ProtectionDomain} of a proxy class
+ * <li>The {@link java.security.ProtectionDomain} of a proxy class
  * is the same as that of system classes loaded by the bootstrap class
  * loader, such as {@code java.lang.Object}, because the code for a
  * proxy class is generated by trusted system code.  This protection
- * domain will typically be granted
- * {@code java.security.AllPermission}.
+ * domain will typically be granted {@code java.security.AllPermission}.
  *
- * <li>Each proxy class has one public constructor that takes one argument,
- * an implementation of the interface {@link InvocationHandler}, to set
- * the invocation handler for a proxy instance.  Rather than having to use
- * the reflection API to access the public constructor, a proxy instance
- * can be also be created by calling the {@link Proxy#newProxyInstance
- * Proxy.newProxyInstance} method, which combines the actions of calling
- * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
- * constructor with an invocation handler.
+ * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method can be used
+ * to determine if a given class is a proxy class.
  * </ul>
  *
  * <p>A proxy instance has the following properties:
  *
  * <ul>
  * <li>Given a proxy instance {@code proxy} and one of the
- * interfaces implemented by its proxy class {@code Foo}, the
+ * interfaces, {@code Foo}, implemented by its proxy class, the
  * following expression will return true:
  * <pre>
  *     {@code proxy instanceof Foo}
@@ -177,9 +156,82 @@
  * like they do for instances of {@code java.lang.Object}.
  * </ul>
  *
+ * <h3><a name="membership">Package and Module Membership of Proxy Class</a></h3>
+ *
+ * The package and module to which a proxy class belongs are chosen such that
+ * the accessibility of the proxy class is in line with the accessibility of
+ * the proxy interfaces. Specifically, the package and the module membership
+ * of a proxy class defined via the
+ * {@link Proxy#getProxyClass(ClassLoader, Class[])} or
+ * {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}
+ * methods is specified as follows:
+ *
+ * <ol>
+ * <li>If all the proxy interfaces are in <em>exported</em> packages:
+ * <ol type="a">
+ * <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
+ *     <em>public</em> in a package exported by the
+ *     {@linkplain ClassLoader#getUnnamedModule() unnamed module} of the specified
+ *     loader. The name of the package is unspecified.</li>
+ *
+ * <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
+ *     the proxy class is <em>non-public</em> in the package and module of the
+ *     non-public interfaces. All the non-public interfaces must be in the same
+ *     package and module; otherwise, proxying them is
+ *     <a href="#restrictions">not possible</a>.</li>
+ * </ol>
+ * </li>
+ * <li>If at least one proxy interface is a <em>non-exported</em> package:
+ * <ol type="a">
+ * <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
+ *     <em>public</em> in a <em>non-exported</em> package of
+ *     <a href="#dynamicmodule"><em>dynamic module</em>.</a>
+ *     The names of the package and the module are unspecified.</li>
+ *
+ * <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
+ *     the proxy class is <em>non-public</em> in the package and module of the
+ *     non-public interfaces. All the non-public interfaces must be in the same
+ *     package and module; otherwise, proxying them is
+ *     <a href="#restrictions">not possible</a>.</li>
+ * </ol>
+ * </li>
+ * </ol>
+ *
+ * <p>
+ * Note that if proxy interfaces with a mix of accessibilities --
+ * exported public, exported non-public, non-exported public, non-exported non-public --
+ * are proxied by the same instance, then the proxy class's accessibility is
+ * governed by the least accessible proxy interface.
+ * <p>
+ * Note that it is possible for arbitrary code to obtain access to a proxy class
+ * in an exported package with {@link AccessibleObject#setAccessible setAccessible},
+ * whereas a proxy class in a non-exported package is never accessible to
+ * code outside the module of the proxy class.
+ *
+ * <p>
+ * Throughout this specification, a "non-exported package" refers to a package that
+ * is not exported to all modules. Specifically, it refers to a package that
+ * either is not exported at all by its containing module or is exported in a
+ * qualified fashion by its containing module.
+ *
+ * <h3><a name="dynamicmodule">Dynamic Modules</a></h3>
+ * <p>
+ * A dynamic module is a named module generated at runtime. A proxy class
+ * defined in a dynamic module is encapsulated and not accessible to any module.
+ * Calling {@link Constructor#newInstance(Object...)} on a proxy class in
+ * a dynamic module will throw {@code IllegalAccessException};
+ * {@code Proxy.newProxyInstance} method should be used instead.
+ *
+ * <p>
+ * A dynamic module can read the modules of all of the superinterfaces of a proxy class
+ * and the modules of the types referenced by all public method signatures
+ * of a proxy class.  If a superinterface or a referenced type, say {@code T},
+ * is in a non-exported package, the {@linkplain java.lang.reflect.Module module}
+ * of {@code T} is updated to export the package of {@code T} to the dynamic module.
+ *
  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
  *
- * <p>When two or more interfaces of a proxy class contain a method with
+ * <p>When two or more proxy interfaces contain a method with
  * the same name and parameter signature, the order of the proxy class's
  * interfaces becomes significant.  When such a <i>duplicate method</i>
  * is invoked on a proxy instance, the {@code Method} object passed
@@ -225,7 +277,6 @@
  * @since       1.3
  */
 public class Proxy implements java.io.Serializable {
-
     private static final long serialVersionUID = -2222568056686623797L;
 
     /** parameter types of a proxy class constructor */
@@ -233,12 +284,6 @@
         { InvocationHandler.class };
 
     /**
-     * a cache of proxy classes
-     */
-    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
-        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
-
-    /**
      * the invocation handler for this proxy instance.
      * @serial
      */
@@ -276,67 +321,13 @@
      * a proxy class for those interfaces will be generated dynamically
      * and defined by the class loader.
      *
-     * <p>There are several restrictions on the parameters that may be
-     * passed to {@code Proxy.getProxyClass}:
-     *
-     * <ul>
-     * <li>All of the {@code Class} objects in the
-     * {@code interfaces} array must represent interfaces, not
-     * classes or primitive types.
-     *
-     * <li>No two elements in the {@code interfaces} array may
-     * refer to identical {@code Class} objects.
-     *
-     * <li>All of the interface types must be visible by name through the
-     * specified class loader.  In other words, for class loader
-     * {@code cl} and every interface {@code i}, the following
-     * expression must be true:
-     * <pre>
-     *     Class.forName(i.getName(), false, cl) == i
-     * </pre>
-     *
-     * <li>All non-public interfaces must be in the same package;
-     * otherwise, it would not be possible for the proxy class to
-     * implement all of the interfaces, regardless of what package it is
-     * defined in.
-     *
-     * <li>For any set of member methods of the specified interfaces
-     * that have the same signature:
-     * <ul>
-     * <li>If the return type of any of the methods is a primitive
-     * type or void, then all of the methods must have that same
-     * return type.
-     * <li>Otherwise, one of the methods must have a return type that
-     * is assignable to all of the return types of the rest of the
-     * methods.
-     * </ul>
-     *
-     * <li>The resulting proxy class must not exceed any limits imposed
-     * on classes by the virtual machine.  For example, the VM may limit
-     * the number of interfaces that a class may implement to 65535; in
-     * that case, the size of the {@code interfaces} array must not
-     * exceed 65535.
-     * </ul>
-     *
-     * <p>If any of these restrictions are violated,
-     * {@code Proxy.getProxyClass} will throw an
-     * {@code IllegalArgumentException}.  If the {@code interfaces}
-     * array argument or any of its elements are {@code null}, a
-     * {@code NullPointerException} will be thrown.
-     *
-     * <p>Note that the order of the specified proxy interfaces is
-     * significant: two requests for a proxy class with the same combination
-     * of interfaces but in a different order will result in two distinct
-     * proxy classes.
-     *
      * @param   loader the class loader to define the proxy class
      * @param   interfaces the list of interfaces for the proxy class
      *          to implement
      * @return  a proxy class that is defined in the specified class loader
      *          and that implements the specified interfaces
-     * @throws  IllegalArgumentException if any of the restrictions on the
-     *          parameters that may be passed to {@code getProxyClass}
-     *          are violated
+     * @throws  IllegalArgumentException if any of the <a href="#restrictions">
+     *          restrictions</a> on the parameters are violated
      * @throws  SecurityException if a security manager, <em>s</em>, is present
      *          and any of the following conditions is met:
      *          <ul>
@@ -352,22 +343,32 @@
      *             invocation of {@link SecurityManager#checkPackageAccess
      *             s.checkPackageAccess()} denies access to {@code intf}.</li>
      *          </ul>
-
      * @throws  NullPointerException if the {@code interfaces} array
      *          argument or any of its elements are {@code null}
+     *
+     * @deprecated Proxy classes generated in a named module are encapsulated and not
+     *      accessible to code outside its module.
+     *      {@link Constructor#newInstance(Object...) Constructor.newInstance} will throw
+     *      {@code IllegalAccessException} when it is called on an inaccessible proxy class.
+     *      Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
+     *      to create a proxy instance instead.
+     *
+     * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
      */
+    @Deprecated
     @CallerSensitive
     public static Class<?> getProxyClass(ClassLoader loader,
                                          Class<?>... interfaces)
         throws IllegalArgumentException
     {
-        final Class<?>[] intfs = interfaces.clone();
+        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
         final SecurityManager sm = System.getSecurityManager();
+        final Class<?> caller = Reflection.getCallerClass();
         if (sm != null) {
-            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
+            checkProxyAccess(caller, loader, intfs);
         }
 
-        return getProxyClass0(loader, intfs);
+        return new ProxyBuilder(loader, intfs).build();
     }
 
     /*
@@ -386,11 +387,11 @@
      * the defining loader of the interface.  If the caller's class loader
      * is not the same as the defining loader of the interface, the VM
      * will throw IllegalAccessError when the generated proxy class is
-     * being defined via the defineClass0 method.
+     * being defined.
      */
     private static void checkProxyAccess(Class<?> caller,
                                          ClassLoader loader,
-                                         Class<?>... interfaces)
+                                         List<Class<?>> interfaces)
     {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -398,26 +399,10 @@
             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
             }
-            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
+            ReflectUtil.checkProxyPackageAccess(ccl, interfaces.toArray(EMPTY_CLASS_ARRAY));
         }
     }
 
-    /**
-     * Generate a proxy class.  Must call the checkProxyAccess method
-     * to perform permission checks before calling this.
-     */
-    private static Class<?> getProxyClass0(ClassLoader loader,
-                                           Class<?>... interfaces) {
-        if (interfaces.length > 65535) {
-            throw new IllegalArgumentException("interface limit exceeded");
-        }
-
-        // If the proxy class defined by the given loader implementing
-        // the given interfaces exists, this will simply return the cached copy;
-        // otherwise, it will create the proxy class via the ProxyClassFactory
-        return proxyClassCache.get(loader, interfaces);
-    }
-
     /*
      * a key used for proxy class with 0 implemented interfaces
      */
@@ -495,11 +480,12 @@
         private final WeakReference<Class<?>>[] refs;
 
         @SuppressWarnings("unchecked")
-        KeyX(Class<?>[] interfaces) {
-            hash = Arrays.hashCode(interfaces);
-            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
-            for (int i = 0; i < interfaces.length; i++) {
-                refs[i] = new WeakReference<>(interfaces[i]);
+        KeyX(List<Class<?>> interfaces) {
+            hash = Arrays.hashCode(interfaces.toArray());
+            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.size()];
+            int i = 0;
+            for (Class<?> intf : interfaces) {
+                refs[i++] = new WeakReference<>(intf);
             }
         }
 
@@ -535,14 +521,14 @@
      * A function that maps an array of interfaces to an optimal key where
      * Class objects representing interfaces are weakly referenced.
      */
-    private static final class KeyFactory
-        implements BiFunction<ClassLoader, Class<?>[], Object>
+    private static final class KeyFactory<T>
+        implements BiFunction<T, List<Class<?>>, Object>
     {
         @Override
-        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
-            switch (interfaces.length) {
-                case 1: return new Key1(interfaces[0]); // the most frequent
-                case 2: return new Key2(interfaces[0], interfaces[1]);
+        public Object apply(T t, List<Class<?>> interfaces) {
+            switch (interfaces.size()) {
+                case 1: return new Key1(interfaces.get(0)); // the most frequent
+                case 2: return new Key2(interfaces.get(0), interfaces.get(1));
                 case 0: return key0;
                 default: return new KeyX(interfaces);
             }
@@ -550,53 +536,19 @@
     }
 
     /**
-     * A factory function that generates, defines and returns the proxy class given
-     * the ClassLoader and array of interfaces.
+     * A factory function that generates, defines and returns the proxy class
+     * given the ClassLoader and array of interfaces.
      */
-    private static final class ProxyClassFactory
-        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
-    {
+    private static final class ProxyClassFactory {
+        private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
         // prefix for all proxy class names
         private static final String proxyClassNamePrefix = "$Proxy";
 
         // next number to use for generation of unique proxy class names
         private static final AtomicLong nextUniqueNumber = new AtomicLong();
 
-        @Override
-        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
-
-            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
-            for (Class<?> intf : interfaces) {
-                /*
-                 * Verify that the class loader resolves the name of this
-                 * interface to the same Class object.
-                 */
-                Class<?> interfaceClass = null;
-                try {
-                    interfaceClass = Class.forName(intf.getName(), false, loader);
-                } catch (ClassNotFoundException e) {
-                }
-                if (interfaceClass != intf) {
-                    throw new IllegalArgumentException(
-                        intf + " is not visible from class loader");
-                }
-                /*
-                 * Verify that the Class object actually represents an
-                 * interface.
-                 */
-                if (!interfaceClass.isInterface()) {
-                    throw new IllegalArgumentException(
-                        interfaceClass.getName() + " is not an interface");
-                }
-                /*
-                 * Verify that this interface is not a duplicate.
-                 */
-                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
-                    throw new IllegalArgumentException(
-                        "repeated interface: " + interfaceClass.getName());
-                }
-            }
-
+        private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
             String proxyPkg = null;     // package to define proxy class in
             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 
@@ -608,38 +560,49 @@
             for (Class<?> intf : interfaces) {
                 int flags = intf.getModifiers();
                 if (!Modifier.isPublic(flags)) {
-                    accessFlags = Modifier.FINAL;
-                    String name = intf.getName();
-                    int n = name.lastIndexOf('.');
-                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
+                    accessFlags = Modifier.FINAL;  // non-public, final
+                    String pkg = intf.getPackageName();
                     if (proxyPkg == null) {
                         proxyPkg = pkg;
                     } else if (!pkg.equals(proxyPkg)) {
                         throw new IllegalArgumentException(
-                            "non-public interfaces from different packages");
+                                "non-public interfaces from different packages");
                     }
                 }
             }
 
             if (proxyPkg == null) {
-                // if no non-public proxy interfaces, use com.sun.proxy package
-                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
+                // all proxy interfaces are public
+                proxyPkg = m.isNamed() ? PROXY_PACKAGE_PREFIX + "." + m.getName()
+                                       : PROXY_PACKAGE_PREFIX;
+            } else if (proxyPkg.isEmpty() && m.isNamed()) {
+                throw new IllegalArgumentException(
+                        "Unnamed package cannot be added to " + m);
+            }
+
+            // add the package to the runtime module if not exists
+            if (m.isNamed()) {
+                m.addPackage(proxyPkg);
             }
 
             /*
              * Choose a name for the proxy class to generate.
              */
             long num = nextUniqueNumber.getAndIncrement();
-            String proxyName = proxyPkg + proxyClassNamePrefix + num;
+            String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num
+                                                  : proxyPkg + "." + proxyClassNamePrefix + num;
+
+            ClassLoader loader = getLoader(m);
+            trace(proxyName, m, loader, interfaces);
 
             /*
              * Generate the specified proxy class.
              */
             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
-                proxyName, interfaces, accessFlags);
+                    proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
             try {
-                return defineClass0(loader, proxyName,
-                                    proxyClassFile, 0, proxyClassFile.length);
+                return UNSAFE.defineClass(proxyName, proxyClassFile, 0, proxyClassFile.length,
+                                          loader, null);
             } catch (ClassFormatError e) {
                 /*
                  * A ClassFormatError here means that (barring bugs in the
@@ -651,16 +614,410 @@
                 throw new IllegalArgumentException(e.toString());
             }
         }
+
+        /**
+         * Test if the given class is a proxy class
+         */
+        static boolean isProxyClass(Class<?> c) {
+            return proxyCache.containsValue(c);
+        }
+
+        /**
+         * Returns the proxy class.  It will return the cached proxy class
+         * if exists; otherwise, it will create the proxy class and store in
+         * the cache.
+         */
+        static Class<?> get(Module module, List<Class<?>> interfaces) {
+            return proxyCache.get(module, interfaces);
+        }
+
+        /**
+         * a cache of proxy classes in the named and unnamed module
+         */
+        private static final WeakCache<Module, List<Class<?>>, Class<?>> proxyCache =
+            new WeakCache<>(new KeyFactory<Module>(),
+                new BiFunction<Module, List<Class<?>>, Class<?>>()  {
+                    @Override
+                    public Class<?> apply(Module m, List<Class<?>> interfaces) {
+                        Objects.requireNonNull(m);
+                        return defineProxyClass(m, interfaces);
+                    }
+            });
+
+
+        private static boolean isExportedType(Class<?> c) {
+            String pn = c.getPackageName();
+            return Modifier.isPublic(c.getModifiers()) && c.getModule().isExported(pn);
+        }
+
+        private static boolean isPackagePrivateType(Class<?> c) {
+            return !Modifier.isPublic(c.getModifiers());
+        }
+
+        private static String toDetails(Class<?> c) {
+            String access = "unknown";
+            if (isExportedType(c)) {
+                access = "exported";
+            } else if (isPackagePrivateType(c)) {
+                access = "package-private";
+            } else {
+                access = "module-private";
+            }
+            ClassLoader ld = c.getClassLoader();
+            return String.format("   %s/%s %s loader %s",
+                    c.getModule().getName(), c.getName(), access, ld);
+        }
+
+        static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) {
+            if (isDebug()) {
+                System.out.format("PROXY: %s/%s defined by %s%n", module.getName(), cn, loader);
+            }
+            if (isDebug("debug")) {
+                interfaces.stream()
+                          .forEach(c -> System.out.println(toDetails(c)));
+            }
+        }
+
+        private static final String DEBUG =
+            AccessController.doPrivileged(new PrivilegedAction<>() {
+                public String run() {
+                    return System.getProperty("jdk.proxy.debug", "");
+                }
+            });
+
+        private static final boolean isDebug() {
+            return !DEBUG.isEmpty();
+        }
+        private static final boolean isDebug(String flag) {
+            return DEBUG.equals(flag);
+        }
     }
 
     /**
-     * Returns an instance of a proxy class for the specified interfaces
+     * Builder for a proxy class.
+     *
+     * If the module is not specified in this ProxyBuilder constructor,
+     * it will map from the given loader and interfaces to the module
+     * in which the proxy class will be defined.
+     */
+    private static final class ProxyBuilder {
+        final ClassLoader loader;
+        final List<Class<?>> interfaces;
+        final Module module;
+        ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
+            if (!VM.isModuleSystemInited()) {
+                throw new InternalError("Proxy is not supported until module system is fully initialzed");
+            }
+            if (interfaces.size() > 65535) {
+                throw new IllegalArgumentException("interface limit exceeded");
+            }
+
+            Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
+
+            // IAE if violates any restrictions specified in newProxyInstance
+            validateProxyInterfaces(loader, interfaces, refTypes);
+
+            this.loader = loader;
+            this.interfaces = interfaces;
+            this.module = mapToModule(loader, interfaces, refTypes);
+            assert getLoader(module) == loader;
+        }
+
+        /**
+         * Generate a proxy class.  If the target module does not have any
+         * to any interface types, IllegalAccessError will be thrown by the VM
+         * at defineClass time.
+         *
+         * Must call the checkProxyAccess method to perform permission checks
+         * before calling this.
+         */
+        Class<?> build() {
+            return ProxyClassFactory.get(module, interfaces);
+        }
+
+        /**
+         * Validate the given proxy interfaces and the given referenced types
+         * are visible to the defining loader.
+         *
+         * @throws IllegalArgumentException if it violates the restrictions specified
+         *         in {@link Proxy#newProxyInstance}
+         */
+        static void validateProxyInterfaces(ClassLoader loader,
+                                            List<Class<?>> interfaces,
+                                            Set<Class<?>> refTypes)
+        {
+            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.size());
+            for (Class<?> intf : interfaces) {
+                /*
+                 * Verify that the class loader resolves the name of this
+                 * interface to the same Class object.
+                 */
+                ensureVisible(loader, intf);
+
+                /*
+                 * Verify that the Class object actually represents an
+                 * interface.
+                 */
+                if (!intf.isInterface()) {
+                    throw new IllegalArgumentException(intf.getName() + " is not an interface");
+                }
+
+                /*
+                 * Verify that this interface is not a duplicate.
+                 */
+                if (interfaceSet.put(intf, Boolean.TRUE) != null) {
+                    throw new IllegalArgumentException("repeated interface: " + intf.getName());
+                }
+            }
+
+            for (Class<?> type : refTypes) {
+                ensureVisible(loader, type);
+            }
+        }
+
+        /*
+         * Returns all types referenced by all public method signatures of
+         * the proxy interfaces
+         */
+        static Set<Class<?>> referencedTypes(ClassLoader loader, List<Class<?>> interfaces) {
+            return interfaces.stream()
+                 .flatMap(intf -> Stream.of(intf.getMethods())
+                                        .flatMap(m -> methodRefTypes(m))
+                                        .map(ProxyBuilder::getElementType)
+                                        .filter(t -> !t.isPrimitive()))
+                 .collect(Collectors.toSet());
+        }
+
+        /*
+         * Extracts all types referenced on a method signature including
+         * its return type, parameter types, and exception types.
+         */
+        static Stream<Class<?>> methodRefTypes(Method m) {
+            return Stream.of(new Class<?>[] { m.getReturnType() },
+                             m.getParameterTypes(),
+                             m.getExceptionTypes())
+                         .flatMap(a -> Stream.of(a));
+        }
+
+        /**
+         * Returns the module that the generated proxy class belongs to.
+         *
+         * If all proxy interfaces are public and in exported packages,
+         * then the proxy class is in unnamed module.
+         *
+         * If any of proxy interface is package-private, then the proxy class
+         * is in the same module of the package-private interface.
+         *
+         * If all proxy interfaces are public and at least one in a non-exported
+         * package, then the proxy class is in a dynamic module in a non-exported
+         * package.  Reads edge and qualified exports are added for
+         * dynamic module to access.
+         */
+        static Module mapToModule(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes) {
+            Map<Class<?>, Module> modulePrivateTypes = new HashMap<>();
+            Map<Class<?>, Module> packagePrivateTypes = new HashMap<>();
+            for (Class<?> intf : interfaces) {
+                Module m = intf.getModule();
+                if (Modifier.isPublic(intf.getModifiers())) {
+                    // module-private types
+                    if (!m.isExported(intf.getPackageName())) {
+                        modulePrivateTypes.put(intf, m);
+                    }
+                } else {
+                    packagePrivateTypes.put(intf, m);
+                }
+            }
+
+            // all proxy interfaces are public and exported, the proxy class is in unnamed module
+            // Such proxy class is accessible to any unnamed module and named module that
+            // can read unnamed module
+            if (packagePrivateTypes.isEmpty() && modulePrivateTypes.isEmpty()) {
+                return loader != null ? loader.getUnnamedModule() : BootLoader.getUnnamedModule();
+            }
+
+            if (packagePrivateTypes.size() > 0) {
+                // all package-private types must be in the same runtime package
+                // i.e. same package name and same module (named or unnamed)
+                //
+                // Configuration will fail if M1 and in M2 defined by the same loader
+                // and both have the same package p (so no need to check class loader)
+                if (packagePrivateTypes.size() > 1 &&
+                        (packagePrivateTypes.keySet().stream()  // more than one package
+                                 .map(Class::getPackageName).distinct().count() > 1 ||
+                         packagePrivateTypes.values().stream()  // or more than one module
+                                 .distinct().count() > 1)) {
+                    throw new IllegalArgumentException(
+                            "non-public interfaces from different packages");
+                }
+
+                // all package-private types are in the same module (named or unnamed)
+                Module target = null;
+                for (Module m : packagePrivateTypes.values()) {
+                    if (getLoader(m) != loader) {
+                        // the specified loader is not the same class loader of the non-public interface
+                        throw new IllegalArgumentException(
+                                "non-public interface is not defined by the given loader");
+                    }
+                    target = m;
+                }
+
+                // validate if the target module can access all other interfaces
+                for (Class<?> intf : interfaces) {
+                    Module m = intf.getModule();
+                    if (m == target) continue;
+
+                    if (!target.canRead(m) || !m.isExported(intf.getPackageName(), target)) {
+                        throw new IllegalArgumentException(target + " can't access " + intf.getName());
+                    }
+                }
+
+                // return the module of the package-private interface
+                return target;
+            }
+
+            // all proxy interfaces are public and at least one in a non-exported package
+            // map to dynamic proxy module and add reads edge and qualified exports, if necessary
+            Module target = getDynamicModule(loader);
+
+            // set up proxy class access to proxy interfaces and superinterfaces
+            Deque<Class<?>> deque = new LinkedList<>(interfaces);
+            Set<Class<?>> visited = new HashSet<>();
+            while (!deque.isEmpty()) {
+                Class<?> c = deque.poll();
+                if (visited.contains(c)) {
+                    continue;
+                }
+                visited.add(c);
+                ensureAccess(target, c);
+
+                // add all superinterfaces
+                for (Class<?> intf : c.getInterfaces()) {
+                    deque.add(intf);
+                }
+            }
+
+            // set up proxy class access to types referenced in the method signature
+            refTypes.stream()
+                    .filter(t -> !visited.contains(t))
+                    .forEach(t -> ensureAccess(target, t));
+            return target;
+        }
+
+        /*
+         * Ensure the given module can access the given class.
+         */
+        static void ensureAccess(Module target, Class<?> c) {
+            Module m = c.getModule();
+            // add read edge and qualified export for the target module to access
+            if (!target.canRead(m)) {
+                Modules.addReads(target, m);
+            }
+            String pn = c.getPackageName();
+            if (!m.isExported(pn, target)) {
+                Modules.addExports(m, pn, target);
+            }
+        }
+
+        /*
+         * Ensure the given class is visible to the class loader.
+         */
+        static void ensureVisible(ClassLoader ld, Class<?> c) {
+            Class<?> type = null;
+            try {
+                type = Class.forName(c.getName(), false, ld);
+            } catch (ClassNotFoundException e) {
+            }
+            if (type != c) {
+                throw new IllegalArgumentException(c.getName() +
+                        " referenced from a method is not visible from class loader");
+            }
+        }
+
+        static Class<?> getElementType(Class<?> type) {
+            Class<?> e = type;
+            while (e.isArray()) {
+                e = e.getComponentType();
+            }
+            return e;
+        }
+
+        private static final WeakHashMap<ClassLoader, Module> dynProxyModules = new WeakHashMap<>();
+        private static final AtomicInteger counter = new AtomicInteger();
+
+        /*
+         * Define a dynamic module for the generated proxy classes in a non-exported package
+         * named com.sun.proxy.$MODULE.
+         *
+         * Each class loader will have one dynamic module.
+         */
+        static Module getDynamicModule(ClassLoader loader) {
+            return dynProxyModules.computeIfAbsent(loader, ld -> {
+                // create a dynamic module and setup module access
+                String mn = "jdk.proxy" + counter.incrementAndGet();
+                String pn = PROXY_PACKAGE_PREFIX + "." + mn;
+                Module m = Modules.defineModule(loader, mn, Collections.singleton(pn));
+                Modules.addReads(m, Proxy.class.getModule());
+                // java.base to create proxy instance
+                Modules.addExports(m, pn, Object.class.getModule());
+                return m;
+            });
+        }
+    }
+
+    /**
+     * Returns a proxy instance for the specified interfaces
      * that dispatches method invocations to the specified invocation
      * handler.
+     * <p>
+     * <a name="restrictions">{@code IllegalArgumentException} will be thrown
+     * if any of the following restrictions is violated:</a>
+     * <ul>
+     * <li>All of {@code Class} objects in the given {@code interfaces} array
+     * must represent interfaces, not classes or primitive types.
      *
-     * <p>{@code Proxy.newProxyInstance} throws
-     * {@code IllegalArgumentException} for the same reasons that
-     * {@code Proxy.getProxyClass} does.
+     * <li>No two elements in the {@code interfaces} array may
+     * refer to identical {@code Class} objects.
+     *
+     * <li>All of the interface types must be visible by name through the
+     * specified class loader. In other words, for class loader
+     * {@code cl} and every interface {@code i}, the following
+     * expression must be true:<p>
+     * {@code Class.forName(i.getName(), false, cl) == i}
+     *
+     * <li>All of the types referenced by all
+     * public method signatures of the specified interfaces
+     * and those inherited by their superinterfaces
+     * must be visible by name through the specified class loader.
+     *
+     * <li>All non-public interfaces must be in the same package
+     * and module, defined by the specified class loader and
+     * the module of the non-public interfaces can access all of
+     * the interface types; otherwise, it would not be possible for
+     * the proxy class to implement all of the interfaces,
+     * regardless of what package it is defined in.
+     *
+     * <li>For any set of member methods of the specified interfaces
+     * that have the same signature:
+     * <ul>
+     * <li>If the return type of any of the methods is a primitive
+     * type or void, then all of the methods must have that same
+     * return type.
+     * <li>Otherwise, one of the methods must have a return type that
+     * is assignable to all of the return types of the rest of the
+     * methods.
+     * </ul>
+     *
+     * <li>The resulting proxy class must not exceed any limits imposed
+     * on classes by the virtual machine.  For example, the VM may limit
+     * the number of interfaces that a class may implement to 65535; in
+     * that case, the size of the {@code interfaces} array must not
+     * exceed 65535.
+     * </ul>
+     *
+     * <p>Note that the order of the specified proxy interfaces is
+     * significant: two requests for a proxy class with the same combination
+     * of interfaces but in a different order will result in two distinct
+     * proxy classes.
      *
      * @param   loader the class loader to define the proxy class
      * @param   interfaces the list of interfaces for the proxy class
@@ -669,9 +1026,8 @@
      * @return  a proxy instance with the specified invocation handler of a
      *          proxy class that is defined by the specified class loader
      *          and that implements the specified interfaces
-     * @throws  IllegalArgumentException if any of the restrictions on the
-     *          parameters that may be passed to {@code getProxyClass}
-     *          are violated
+     * @throws  IllegalArgumentException if any of the <a href="#restrictions">
+     *          restrictions</a> on the parameters are violated
      * @throws  SecurityException if a security manager, <em>s</em>, is present
      *          and any of the following conditions is met:
      *          <ul>
@@ -697,43 +1053,47 @@
      *          argument or any of its elements are {@code null}, or
      *          if the invocation handler, {@code h}, is
      *          {@code null}
+     *
+     * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
      */
     @CallerSensitive
     public static Object newProxyInstance(ClassLoader loader,
                                           Class<?>[] interfaces,
-                                          InvocationHandler h)
-        throws IllegalArgumentException
-    {
+                                          InvocationHandler h) {
         Objects.requireNonNull(h);
 
-        final Class<?>[] intfs = interfaces.clone();
+        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
         final SecurityManager sm = System.getSecurityManager();
+        final Class<?> caller = Reflection.getCallerClass();
         if (sm != null) {
-            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
+            checkProxyAccess(caller, loader, intfs);
         }
 
         /*
          * Look up or generate the designated proxy class.
          */
-        Class<?> cl = getProxyClass0(loader, intfs);
+        Class<?> cl = new ProxyBuilder(loader, intfs).build();
 
+        return newProxyInstance(cl, caller, h);
+    }
+
+    private static Object newProxyInstance(Class<?> proxyClass, Class<?> caller, InvocationHandler h) {
         /*
          * Invoke its constructor with the designated invocation handler.
          */
         try {
+            final SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
-                checkNewProxyPermission(Reflection.getCallerClass(), cl);
+                checkNewProxyPermission(caller, proxyClass);
             }
 
-            final Constructor<?> cons = cl.getConstructor(constructorParams);
-            if (!Modifier.isPublic(cl.getModifiers())) {
-                AccessController.doPrivileged(new PrivilegedAction<>() {
-                    public Void run() {
-                        cons.setAccessible(true);
-                        return null;
-                    }
-                });
-            }
+            final Constructor<?> cons = proxyClass.getConstructor(constructorParams);
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    cons.setAccessible(true);
+                    return null;
+                }
+            });
             return cons.newInstance(new Object[]{h});
         } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {
             throw new InternalError(e.toString(), e);
@@ -770,11 +1130,17 @@
     }
 
     /**
-     * Returns true if and only if the specified class was dynamically
-     * generated to be a proxy class using the {@code getProxyClass}
-     * method or the {@code newProxyInstance} method.
+     * Returns the class loader for the given module.
+     */
+    private static ClassLoader getLoader(Module m) {
+        PrivilegedAction<ClassLoader> pa = m::getClassLoader;
+        return AccessController.doPrivileged(pa);
+    }
+
+    /**
+     * Returns true if the given class is a proxy class.
      *
-     * <p>The reliability of this method is important for the ability
+     * @implNote The reliability of this method is important for the ability
      * to use it to make security decisions, so its implementation should
      * not just test if the class in question extends {@code Proxy}.
      *
@@ -784,7 +1150,7 @@
      * @throws  NullPointerException if {@code cl} is {@code null}
      */
     public static boolean isProxyClass(Class<?> cl) {
-        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
+        return Proxy.class.isAssignableFrom(cl) && ProxyClassFactory.isProxyClass(cl);
     }
 
     /**
@@ -827,6 +1193,6 @@
         return ih;
     }
 
-    private static native Class<?> defineClass0(ClassLoader loader, String name,
-                                                byte[] b, int off, int len);
+    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
+    private static final String PROXY_PACKAGE_PREFIX = ReflectUtil.PROXY_PACKAGE;
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/package-info.java b/jdk/src/java.base/share/classes/java/lang/reflect/package-info.java
index cf0a1a2..c8cb025 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/package-info.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, 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
@@ -24,12 +24,12 @@
  */
 
 /**
- * Provides classes and interfaces for obtaining reflective
- * information about classes and objects.  Reflection allows
- * programmatic access to information about the fields, methods and
- * constructors of loaded classes, and the use of reflected fields,
- * methods, and constructors to operate on their underlying
- * counterparts, within security restrictions.
+ * Provides classes and interfaces for obtaining reflective information about
+ * modules, classes and objects.  Reflection allows programmatic access to
+ * information about modules and to the fields, methods and constructors of
+ * loaded classes, and the use of reflected fields, methods, and constructors
+ * to operate on their underlying counterparts, within encapsulation and
+ * security restrictions.
  *
  * <p>{@code AccessibleObject} allows suppression of access checks if
  * the necessary {@code ReflectPermission} is available.
diff --git a/jdk/src/java.base/share/classes/java/net/URL.java b/jdk/src/java.base/share/classes/java/net/URL.java
index 598e410..cce9cf9 100644
--- a/jdk/src/java.base/share/classes/java/net/URL.java
+++ b/jdk/src/java.base/share/classes/java/net/URL.java
@@ -1213,11 +1213,15 @@
         String packagePrefixList = java.security.AccessController.doPrivileged(
                 new PrivilegedAction<>() {
                     public String run() {
-                        return System.getProperty(protocolPathProp, "");
+                        return System.getProperty(protocolPathProp, null);
                     }
                 });
-        String[] packagePrefixes = packagePrefixList.split("\\|");
+        if (packagePrefixList == null) {
+            // not set
+            return null;
+        }
 
+        String[] packagePrefixes = packagePrefixList.split("\\|");
         URLStreamHandler handler = null;
         for (int i=0; handler == null && i<packagePrefixes.length; i++) {
             String packagePrefix = packagePrefixes[i].trim();
@@ -1287,9 +1291,6 @@
     private static ThreadLocal<Object> gate = new ThreadLocal<>();
 
     private static URLStreamHandler lookupViaProviders(final String protocol) {
-        if (!jdk.internal.misc.VM.isBooted())
-            return null;
-
         if (gate.get() != null)
             throw new Error("Circular loading of URL stream handler providers detected");
 
@@ -1359,7 +1360,7 @@
         URLStreamHandlerFactory fac;
         boolean checkedWithFactory = false;
 
-        if (isOverrideable(protocol)) {
+        if (isOverrideable(protocol) && jdk.internal.misc.VM.isBooted()) {
             // Use the factory (if any). Volatile read makes
             // URLStreamHandlerFactory appear fully initialized to current thread.
             fac = factory;
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 1cf064d..c120ab7 100644
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
@@ -42,7 +42,6 @@
 import java.util.Enumeration;
 import java.util.List;
 import java.util.NoSuchElementException;
-import java.util.Objects;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.jar.Attributes;
@@ -394,7 +393,7 @@
      */
     private Package getAndVerifyPackage(String pkgname,
                                         Manifest man, URL url) {
-        Package pkg = getPackage(pkgname);
+        Package pkg = getDefinedPackage(pkgname);
         if (pkg != null) {
             // Package found, so check package sealing.
             if (pkg.isSealed()) {
@@ -416,29 +415,6 @@
         return pkg;
     }
 
-    // Also called by VM to define Package for classes loaded from the CDS
-    // archive
-    private void definePackageInternal(String pkgname, Manifest man, URL url)
-    {
-        if (getAndVerifyPackage(pkgname, man, url) == null) {
-            try {
-                if (man != null) {
-                    definePackage(pkgname, man, url);
-                } else {
-                    definePackage(pkgname, null, null, null, null, null, null, null);
-                }
-            } catch (IllegalArgumentException iae) {
-                // parallel-capable class loaders: re-verify in case of a
-                // race condition
-                if (getAndVerifyPackage(pkgname, man, url) == null) {
-                    // Should never happen
-                    throw new AssertionError("Cannot find package " +
-                                             pkgname);
-                }
-            }
-        }
-    }
-
     /*
      * Defines a Class using the class bytes obtained from the specified
      * Resource. The resulting Class must be resolved before it can be
@@ -452,7 +428,23 @@
             String pkgname = name.substring(0, i);
             // Check if package already loaded.
             Manifest man = res.getManifest();
-            definePackageInternal(pkgname, man, url);
+            if (getAndVerifyPackage(pkgname, man, url) == null) {
+                try {
+                    if (man != null) {
+                        definePackage(pkgname, man, url);
+                    } else {
+                        definePackage(pkgname, null, null, null, null, null, null, null);
+                    }
+                } catch (IllegalArgumentException iae) {
+                    // parallel-capable class loaders: re-verify in case of a
+                    // race condition
+                    if (getAndVerifyPackage(pkgname, man, url) == null) {
+                        // Should never happen
+                        throw new AssertionError("Cannot find package " +
+                                                 pkgname);
+                    }
+                }
+            }
         }
         // Now read the class bytes and define the class
         java.nio.ByteBuffer bb = res.getByteBuffer();
@@ -574,7 +566,7 @@
                 }
             }, acc);
 
-        return url != null ? ucp.checkURL(url) : null;
+        return url != null ? URLClassPath.checkURL(url) : null;
     }
 
     /**
@@ -609,7 +601,7 @@
                         }, acc);
                     if (u == null)
                         break;
-                    url = ucp.checkURL(u);
+                    url = URLClassPath.checkURL(u);
                 } while (url == null);
                 return url != null;
             }
diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java
index 2b8e8ba..d8b3024 100644
--- a/jdk/src/java.base/share/classes/java/nio/Bits.java
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java
@@ -614,7 +614,7 @@
     // which a process may access.  All sizes are specified in bytes.
     static void reserveMemory(long size, int cap) {
 
-        if (!memoryLimitSet && VM.isBooted()) {
+        if (!memoryLimitSet && VM.initLevel() >= 1) {
             maxMemory = VM.maxDirectMemory();
             memoryLimitSet = true;
         }
diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java b/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java
index a5216b9..08ff1f0 100644
--- a/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java
+++ b/jdk/src/java.base/share/classes/java/nio/file/FileSystems.java
@@ -30,8 +30,11 @@
 import java.io.IOException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.*;
 import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.Map;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * Factory methods for file systems. This class defines the {@link #getDefault
@@ -51,8 +54,7 @@
  * installed file system providers. Installed providers are loaded using the
  * service-provider loading facility defined by the {@link ServiceLoader} class.
  * Installed providers are loaded using the system class loader. If the
- * system class loader cannot be found then the extension class loader is used;
- * if there is no extension class loader then the bootstrap class loader is used.
+ * system class loader cannot be found then the platform class loader is used.
  * Providers are typically installed by placing them in a JAR file on the
  * application class path, the JAR file contains a
  * provider-configuration file named {@code java.nio.file.spi.FileSystemProvider}
@@ -82,7 +84,16 @@
  */
 
 public final class FileSystems {
-    private FileSystems() {
+    private FileSystems() { }
+
+    // Built-in file system provider
+    private static final FileSystemProvider builtinFileSystemProvider =
+        sun.nio.fs.DefaultFileSystemProvider.create();
+
+    // built-in file system
+    private static class BuiltinFileSystemHolder {
+        static final FileSystem builtinFileSystem =
+            builtinFileSystemProvider.getFileSystem(URI.create("file:///"));
     }
 
     // lazy initialization of default file system
@@ -105,7 +116,7 @@
 
         // returns default provider
         private static FileSystemProvider getDefaultProvider() {
-            FileSystemProvider provider = sun.nio.fs.DefaultFileSystemProvider.create();
+            FileSystemProvider provider = builtinFileSystemProvider;
 
             // if the property java.nio.file.spi.DefaultFileSystemProvider is
             // set then its value is the name of the default provider (or a list)
@@ -173,7 +184,11 @@
      * @return  the default file system
      */
     public static FileSystem getDefault() {
-        return DefaultFileSystemHolder.defaultFileSystem;
+        if (jdk.internal.misc.VM.isBooted()) {
+            return DefaultFileSystemHolder.defaultFileSystem;
+        } else {
+            return BuiltinFileSystemHolder.builtinFileSystem;
+        }
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/nio/file/Files.java b/jdk/src/java.base/share/classes/java/nio/file/Files.java
index 8f8a504..982846e 100644
--- a/jdk/src/java.base/share/classes/java/nio/file/Files.java
+++ b/jdk/src/java.base/share/classes/java/nio/file/Files.java
@@ -1579,9 +1579,8 @@
      * list of file type detectors. Installed file type detectors are loaded
      * using the service-provider loading facility defined by the {@link ServiceLoader}
      * class. Installed file type detectors are loaded using the system class
-     * loader. If the system class loader cannot be found then the extension class
-     * loader is used; If the extension class loader cannot be found then the
-     * bootstrap class loader is used. File type detectors are typically installed
+     * loader. If the system class loader cannot be found then the platform class
+     * loader is used. File type detectors are typically installed
      * by placing them in a JAR file on the application class path,
      * the JAR file contains a provider-configuration file
      * named {@code java.nio.file.spi.FileTypeDetector} in the resource directory
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 d6d79f5..80f7738 100644
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.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
@@ -45,6 +45,10 @@
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
@@ -56,11 +60,16 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.jar.JarEntry;
 import java.util.spi.ResourceBundleControlProvider;
+import java.util.spi.ResourceBundleProvider;
 
+import jdk.internal.misc.JavaUtilResourceBundleAccess;
+import jdk.internal.misc.SharedSecrets;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 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;
 
 
 /**
@@ -191,6 +200,56 @@
  * known concrete subclasses {@code ListResourceBundle} and
  * {@code PropertyResourceBundle} are thread-safe.
  *
+ * <h3><a name="bundleprovider">Resource Bundles in Named Modules</a></h3>
+ *
+ * When resource bundles are deployed in named modules, the following
+ * module-specific requirements and restrictions are applied.
+ *
+ * <ul>
+ * <li>Code in a named module that calls {@link #getBundle(String, Locale)}
+ * will locate resource bundles in the caller's module (<em>caller module</em>).</li>
+ * <li>If resource bundles are deployed in named modules separate from
+ * the caller module, those resource bundles need to be loaded from service
+ * providers of {@link ResourceBundleProvider}. The caller module must declare
+ * "{@code uses}" and the service interface name is the concatenation of the
+ * base name of the bundles and the string "{@code Provider}". The
+ * <em>bundle provider modules</em> containing resource bundles must
+ * declare "{@code provides}" with the service interface name and
+ * its implementation class name. For example, if the base name is
+ * "{@code com.example.app.MyResources}", the caller module must declare
+ * "{@code uses com.example.app.MyResourcesProvider;}" and a module containing resource
+ * bundles must declare "{@code provides com.example.app.MyResourcesProvider
+ * with com.example.app.internal.MyResourcesProviderImpl;}"
+ * where {@code com.example.app.internal.MyResourcesProviderImpl} is an
+ * implementation class of {@code com.example.app.MyResourcesProvider}.</li>
+ * <li>If you want to use non-standard formats in named modules, such as XML,
+ * {@link ResourceBundleProvider} needs to be used.</li>
+ * <li>The {@code getBundle} method with a {@code ClassLoader} may not be able to
+ * find resource bundles using the given {@code ClassLoader} in named modules.
+ * The {@code getBundle} method with a {@code Module} can be used, instead.</li>
+ * <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules.
+ * If the {@code getBundle} method with a {@code ResourceBundle.Control} is called
+ * in a named module, the method will throw an {@code UnsupportedOperationException}.
+ * Any service providers of {@link ResourceBundleControlProvider} are ignored in
+ * named modules.
+ * </li>
+ * </ul>
+ *
+ * <h3><a name="RBP_support">ResourceBundleProvider Service Providers</a></h3>
+ *
+ * The {@code getBundle} factory methods load service providers of
+ * {@link ResourceBundleProvider}, if available, using {@link ServiceLoader}.
+ * The service type is designated by {@code basename+"Provider"}. For
+ * example, if the base name is "{@code com.example.app.MyResources}", the service
+ * type is {@code com.example.app.MyResourcesProvider}.
+ * <p>
+ * In named modules, the loaded service providers for the given base name are
+ * 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
+ * formats for local module searching are "java.class" and "java.properties".
+ *
  * <h3>ResourceBundle.Control</h3>
  *
  * The {@link ResourceBundle.Control} class provides information necessary
@@ -282,6 +341,7 @@
  * @see ListResourceBundle
  * @see PropertyResourceBundle
  * @see MissingResourceException
+ * @see ResourceBundleProvider
  * @since 1.1
  */
 public abstract class ResourceBundle {
@@ -289,6 +349,32 @@
     /** initial size of the bundle cache */
     private static final int INITIAL_CACHE_SIZE = 32;
 
+    static {
+        SharedSecrets.setJavaUtilResourceBundleAccess(
+            new JavaUtilResourceBundleAccess() {
+                @Override
+                public void setParent(ResourceBundle bundle,
+                                      ResourceBundle parent) {
+                    bundle.setParent(parent);
+                }
+
+                @Override
+                public ResourceBundle getParent(ResourceBundle bundle) {
+                    return bundle.parent;
+                }
+
+                @Override
+                public void setLocale(ResourceBundle bundle, Locale locale) {
+                    bundle.locale = locale;
+                }
+
+                @Override
+                public void setName(ResourceBundle bundle, String name) {
+                    bundle.name = name;
+                }
+            });
+    }
+
     /** constant indicating that no resource bundle exists */
     private static final ResourceBundle NONEXISTENT_BUNDLE = new ResourceBundle() {
             public Enumeration<String> getKeys() { return null; }
@@ -484,6 +570,11 @@
         return cl;
     }
 
+    private static ClassLoader getLoader(Module module) {
+        PrivilegedAction<ClassLoader> pa = module::getClassLoader;
+        return AccessController.doPrivileged(pa);
+    }
+
     /**
      * A wrapper of ClassLoader.getSystemClassLoader().
      */
@@ -494,23 +585,24 @@
                             return new RBClassLoader();
                         }
                     });
-        private static final ClassLoader loader = ClassLoader.getSystemClassLoader();
-
         private RBClassLoader() {
         }
         public Class<?> loadClass(String name) throws ClassNotFoundException {
+            ClassLoader loader = ClassLoader.getSystemClassLoader();
             if (loader != null) {
                 return loader.loadClass(name);
             }
             return Class.forName(name);
         }
         public URL getResource(String name) {
+            ClassLoader loader = ClassLoader.getSystemClassLoader();
             if (loader != null) {
                 return loader.getResource(name);
             }
             return ClassLoader.getSystemResource(name);
         }
         public InputStream getResourceAsStream(String name) {
+            ClassLoader loader = ClassLoader.getSystemClassLoader();
             if (loader != null) {
                 return loader.getResourceAsStream(name);
             }
@@ -532,16 +624,18 @@
 
     /**
      * Key used for cached resource bundles.  The key checks the base
-     * name, the locale, and the class loader to determine if the
-     * resource is a match to the requested one. The loader may be
-     * null, but the base name and the locale must have a non-null
-     * value.
+     * name, the locale, the class loader, and the caller module
+     * to determine if the resource is a match to the requested one.
+     * The loader may be null, but the base name, the locale and
+     * module must have a non-null value.
      */
     private static class CacheKey implements Cloneable {
-        // These three are the actual keys for lookup in Map.
+        // These four are the actual keys for lookup in Map.
         private String name;
         private Locale locale;
-        private LoaderReference loaderRef;
+        private KeyElementReference<ClassLoader> loaderRef;
+        private KeyElementReference<Module> moduleRef;
+
 
         // bundle format which is necessary for calling
         // Control.needsReload().
@@ -564,14 +658,24 @@
         // of this instance.
         private int hashCodeCache;
 
-        CacheKey(String baseName, Locale locale, ClassLoader loader) {
+        // ResourceBundleProviders for loading ResourceBundles
+        private ServiceLoader<ResourceBundleProvider> providers;
+
+        // Boolean.TRUE if the factory method caller provides a ResourceBundleProvier.
+        private Boolean callerHasProvider;
+
+        CacheKey(String baseName, Locale locale, ClassLoader loader, Module module) {
+            Objects.requireNonNull(module);
+
             this.name = baseName;
             this.locale = locale;
             if (loader == null) {
                 this.loaderRef = null;
             } else {
-                loaderRef = new LoaderReference(loader, referenceQueue, this);
+                this.loaderRef = new KeyElementReference<>(loader, referenceQueue, this);
             }
+            this.moduleRef = new KeyElementReference<>(module, referenceQueue, this);
+            this.providers = getServiceLoader(module, baseName);
             calculateHashCode();
         }
 
@@ -603,6 +707,23 @@
             return (loaderRef != null) ? loaderRef.get() : null;
         }
 
+        Module getModule() {
+            return moduleRef.get();
+        }
+
+        ServiceLoader<ResourceBundleProvider> getProviders() {
+            return providers;
+        }
+
+        boolean hasProviders() {
+            return providers != null;
+        }
+
+        boolean callerHasProvider() {
+            return callerHasProvider == Boolean.TRUE;
+        }
+
+        @Override
         public boolean equals(Object other) {
             if (this == other) {
                 return true;
@@ -625,18 +746,22 @@
                 if (loaderRef == null) {
                     return otherEntry.loaderRef == null;
                 }
-                ClassLoader loader = loaderRef.get();
+                ClassLoader loader = getLoader();
+                Module module = getModule();
                 return (otherEntry.loaderRef != null)
                         // with a null reference we can no longer find
-                        // out which class loader was referenced; so
+                        // out which class loader or module was referenced; so
                         // treat it as unequal
                         && (loader != null)
-                        && (loader == otherEntry.loaderRef.get());
-            } catch (    NullPointerException | ClassCastException e) {
+                        && (loader == otherEntry.getLoader())
+                        && (module != null)
+                        && (module.equals(otherEntry.getModule()));
+            } catch (NullPointerException | ClassCastException e) {
             }
             return false;
         }
 
+        @Override
         public int hashCode() {
             return hashCodeCache;
         }
@@ -648,17 +773,28 @@
             if (loader != null) {
                 hashCodeCache ^= loader.hashCode();
             }
+            Module module = getModule();
+            if (module != null) {
+                hashCodeCache ^= module.hashCode();
+            }
         }
 
+        @Override
         public Object clone() {
             try {
                 CacheKey clone = (CacheKey) super.clone();
                 if (loaderRef != null) {
-                    clone.loaderRef = new LoaderReference(loaderRef.get(),
-                                                          referenceQueue, clone);
+                    clone.loaderRef = new KeyElementReference<>(getLoader(),
+                                                                referenceQueue, clone);
                 }
+                clone.moduleRef = new KeyElementReference<>(getModule(),
+                                                            referenceQueue, clone);
+                // Clear the reference to ResourceBundleProviders
+                clone.providers = null;
                 // Clear the reference to a Throwable
                 clone.cause = null;
+                // Clear callerHasProvider
+                clone.callerHasProvider = null;
                 return clone;
             } catch (CloneNotSupportedException e) {
                 //this should never happen
@@ -690,6 +826,7 @@
             return cause;
         }
 
+        @Override
         public String toString() {
             String l = locale.toString();
             if (l.length() == 0) {
@@ -713,19 +850,19 @@
     }
 
     /**
-     * References to class loaders are weak references, so that they can be
-     * garbage collected when nobody else is using them. The ResourceBundle
-     * class has no reason to keep class loaders alive.
+     * References to a CacheKey element as a WeakReference so that it can be
+     * garbage collected when nobody else is using it.
      */
-    private static class LoaderReference extends WeakReference<ClassLoader>
-                                         implements CacheKeyReference {
-        private CacheKey cacheKey;
+    private static class KeyElementReference<T> extends WeakReference<T>
+                                                implements CacheKeyReference {
+        private final CacheKey cacheKey;
 
-        LoaderReference(ClassLoader referent, ReferenceQueue<Object> q, CacheKey key) {
+        KeyElementReference(T referent, ReferenceQueue<Object> q, CacheKey key) {
             super(referent, q);
             cacheKey = key;
         }
 
+        @Override
         public CacheKey getCacheKey() {
             return cacheKey;
         }
@@ -737,13 +874,14 @@
      */
     private static class BundleReference extends SoftReference<ResourceBundle>
                                          implements CacheKeyReference {
-        private CacheKey cacheKey;
+        private final CacheKey cacheKey;
 
         BundleReference(ResourceBundle referent, ReferenceQueue<Object> q, CacheKey key) {
             super(referent, q);
             cacheKey = key;
         }
 
+        @Override
         public CacheKey getCacheKey() {
             return cacheKey;
         }
@@ -770,9 +908,9 @@
     @CallerSensitive
     public static final ResourceBundle getBundle(String baseName)
     {
+        Class<?> caller = Reflection.getCallerClass();
         return getBundleImpl(baseName, Locale.getDefault(),
-                             getLoader(Reflection.getCallerClass()),
-                             getDefaultControl(baseName));
+                             caller, getDefaultControl(caller, baseName));
     }
 
     /**
@@ -795,26 +933,28 @@
      * @param control
      *        the control which gives information for the resource bundle
      *        loading process
-     * @return a resource bundle for the given base name and the default
-     *        locale
-     * @exception NullPointerException
-     *        if <code>baseName</code> or <code>control</code> is
-     *        <code>null</code>
-     * @exception MissingResourceException
-     *        if no resource bundle for the specified base name can be found
-     * @exception IllegalArgumentException
-     *        if the given <code>control</code> doesn't perform properly
-     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
-     *        Note that validation of <code>control</code> is performed as
-     *        needed.
+     * @return a resource bundle for the given base name and the default locale
+     * @throws NullPointerException
+     *         if <code>baseName</code> or <code>control</code> is
+     *         <code>null</code>
+     * @throws MissingResourceException
+     *         if no resource bundle for the specified base name can be found
+     * @throws IllegalArgumentException
+     *         if the given <code>control</code> doesn't perform properly
+     *         (e.g., <code>control.getCandidateLocales</code> returns null.)
+     *         Note that validation of <code>control</code> is performed as
+     *         needed.
+     * @throws UnsupportedOperationException
+     *         if this method is called in a named module
      * @since 1.6
      */
     @CallerSensitive
     public static final ResourceBundle getBundle(String baseName,
                                                  Control control) {
-        return getBundleImpl(baseName, Locale.getDefault(),
-                             getLoader(Reflection.getCallerClass()),
-                             control);
+        Class<?> caller = Reflection.getCallerClass();
+        Locale targetLocale = Locale.getDefault();
+        checkNamedModule(caller);
+        return getBundleImpl(baseName, targetLocale, caller, control);
     }
 
     /**
@@ -842,9 +982,78 @@
     public static final ResourceBundle getBundle(String baseName,
                                                  Locale locale)
     {
+        Class<?> caller = Reflection.getCallerClass();
         return getBundleImpl(baseName, locale,
-                             getLoader(Reflection.getCallerClass()),
-                             getDefaultControl(baseName));
+                             caller, getDefaultControl(caller, baseName));
+    }
+
+    /**
+     * Gets a resource bundle using the specified base name and the default locale
+     * on behalf of the specified module. This method is equivalent to calling
+     * <blockquote>
+     * <code>getBundle(baseName, Locale.getDefault(), module)</code>
+     * </blockquote>
+     *
+     * @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
+     * @throws NullPointerException
+     *         if {@code baseName} or {@code module} is {@code null}
+     * @throws SecurityException
+     *         if a security manager exists and the caller is not the specified
+     *         module and doesn't have {@code RuntimePermission("getClassLoader")}
+     * @throws MissingResourceException
+     *         if no resource bundle for the specified base name can be found in the
+     *         specified module
+     * @return a resource bundle for the given base name and the default locale
+     * @since 9
+     * @see ResourceBundleProvider
+     */
+    @CallerSensitive
+    public static ResourceBundle getBundle(String baseName, Module module) {
+        return getBundleFromModule(Reflection.getCallerClass(), module, baseName,
+                                   Locale.getDefault(), Control.INSTANCE);
+    }
+
+    /**
+     * Gets a resource bundle using the specified base name and locale
+     * on behalf of the specified module.
+     *
+     * <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
+     * <a href="#bundleprovider">Resource Bundles in Named Modules</a> section
+     * for details).
+     *
+     * <p>
+     * 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.
+     *
+     * @param baseName the base name of the resource bundle,
+     *                 a fully qualified class name
+     * @param targetLocale the locale for which a resource bundle is desired
+     * @param module   the module for which the resource bundle is searched
+     * @throws NullPointerException
+     *         if {@code baseName}, {@code targetLocale}, or {@code module} is
+     *         {@code null}
+     * @throws SecurityException
+     *         if a security manager exists and the caller is not the specified
+     *         module and doesn't have {@code RuntimePermission("getClassLoader")}
+     * @throws MissingResourceException
+     *         if no resource bundle for the specified base name and locale can
+     *         be found in the specified {@code module}
+     * @return a resource bundle for the given base name and locale in the module
+     * @since 9
+     */
+    @CallerSensitive
+    public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) {
+        return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale,
+                                   Control.INSTANCE);
     }
 
     /**
@@ -870,26 +1079,28 @@
      *        the control which gives information for the resource
      *        bundle loading process
      * @return a resource bundle for the given base name and a
-     *        <code>Locale</code> in <code>locales</code>
-     * @exception NullPointerException
-     *        if <code>baseName</code>, <code>locales</code> or
-     *        <code>control</code> is <code>null</code>
-     * @exception MissingResourceException
-     *        if no resource bundle for the specified base name in any
-     *        of the <code>locales</code> can be found.
-     * @exception IllegalArgumentException
-     *        if the given <code>control</code> doesn't perform properly
-     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
-     *        Note that validation of <code>control</code> is performed as
-     *        needed.
+     *         <code>Locale</code> in <code>locales</code>
+     * @throws NullPointerException
+     *         if <code>baseName</code>, <code>locales</code> or
+     *         <code>control</code> is <code>null</code>
+     * @throws MissingResourceException
+     *         if no resource bundle for the specified base name in any
+     *         of the <code>locales</code> can be found.
+     * @throws IllegalArgumentException
+     *         if the given <code>control</code> doesn't perform properly
+     *         (e.g., <code>control.getCandidateLocales</code> returns null.)
+     *         Note that validation of <code>control</code> is performed as
+     *         needed.
+     * @throws UnsupportedOperationException
+     *         if this method is called in a named module
      * @since 1.6
      */
     @CallerSensitive
     public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
                                                  Control control) {
-        return getBundleImpl(baseName, targetLocale,
-                             getLoader(Reflection.getCallerClass()),
-                             control);
+        Class<?> caller = Reflection.getCallerClass();
+        checkNamedModule(caller);
+        return getBundleImpl(baseName, targetLocale, caller, control);
     }
 
     /**
@@ -906,6 +1117,16 @@
      * <p><a name="default_behavior">The following describes the default
      * behavior</a>.
      *
+     * <p>
+     * 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.
+     * 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
+     * modules.
+     *
      * <p><code>getBundle</code> uses the base name, the specified locale, and
      * the default locale (obtained from {@link java.util.Locale#getDefault()
      * Locale.getDefault}) to generate a sequence of <a
@@ -1063,6 +1284,13 @@
      * hidden by the MyResources_fr_CH.class. Likewise, MyResources.properties
      * is also hidden by MyResources.class.
      *
+     * @apiNote If the caller module is a named module and the given
+     * {@code loader} is the caller module's class loader, this method is
+     * equivalent to {@code getBundle(baseName, locale)}; otherwise, it will not
+     * find resource bundles from named modules.
+     * Use {@link #getBundle(String, Locale, Module)} to load resource bundles
+     * on behalf on a specific module instead.
+     *
      * @param baseName the base name of the resource bundle, a fully qualified class name
      * @param locale the locale for which a resource bundle is desired
      * @param loader the class loader from which to load the resource bundle
@@ -1073,13 +1301,15 @@
      *        if no resource bundle for the specified base name can be found
      * @since 1.2
      */
+    @CallerSensitive
     public static ResourceBundle getBundle(String baseName, Locale locale,
                                            ClassLoader loader)
     {
         if (loader == null) {
             throw new NullPointerException();
         }
-        return getBundleImpl(baseName, locale, loader, getDefaultControl(baseName));
+        Class<?> caller = Reflection.getCallerClass();
+        return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName));
     }
 
     /**
@@ -1278,29 +1508,34 @@
      *        the control which gives information for the resource
      *        bundle loading process
      * @return a resource bundle for the given base name and locale
-     * @exception NullPointerException
-     *        if <code>baseName</code>, <code>targetLocale</code>,
-     *        <code>loader</code>, or <code>control</code> is
-     *        <code>null</code>
-     * @exception MissingResourceException
-     *        if no resource bundle for the specified base name can be found
-     * @exception IllegalArgumentException
-     *        if the given <code>control</code> doesn't perform properly
-     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
-     *        Note that validation of <code>control</code> is performed as
-     *        needed.
+     * @throws NullPointerException
+     *         if <code>baseName</code>, <code>targetLocale</code>,
+     *         <code>loader</code>, or <code>control</code> is
+     *         <code>null</code>
+     * @throws MissingResourceException
+     *         if no resource bundle for the specified base name can be found
+     * @throws IllegalArgumentException
+     *         if the given <code>control</code> doesn't perform properly
+     *         (e.g., <code>control.getCandidateLocales</code> returns null.)
+     *         Note that validation of <code>control</code> is performed as
+     *         needed.
+     * @throws UnsupportedOperationException
+     *         if this method is called in a named module
      * @since 1.6
      */
+    @CallerSensitive
     public static ResourceBundle getBundle(String baseName, Locale targetLocale,
                                            ClassLoader loader, Control control) {
         if (loader == null || control == null) {
             throw new NullPointerException();
         }
-        return getBundleImpl(baseName, targetLocale, loader, control);
+        Class<?> caller = Reflection.getCallerClass();
+        checkNamedModule(caller);
+        return getBundleImpl(baseName, targetLocale, caller, loader, control);
     }
 
-    private static Control getDefaultControl(String baseName) {
-        if (providers != null) {
+    private static Control getDefaultControl(Class<?> caller, String baseName) {
+        if (providers != null && !caller.getModule().isNamed()) {
             for (ResourceBundleControlProvider provider : providers) {
                 Control control = provider.getControl(baseName);
                 if (control != null) {
@@ -1311,17 +1546,80 @@
         return Control.INSTANCE;
     }
 
-    private static ResourceBundle getBundleImpl(String baseName, Locale locale,
-                                                ClassLoader loader, Control control) {
+    private static void checkNamedModule(Class<?> caller) {
+        if (caller.getModule().isNamed()) {
+            throw new UnsupportedOperationException(
+                    "ResourceBundle.Control not supported in named modules");
+        }
+    }
+
+    private static ResourceBundle getBundleImpl(String baseName,
+                                                Locale locale,
+                                                Class<?> caller,
+                                                Control control) {
+        return getBundleImpl(baseName, locale, caller, getLoader(caller), control);
+    }
+
+    /**
+     * This method will find resource bundles using the legacy mechanism
+     * if the caller is unnamed module or the given class loader is
+     * not the class loader of the caller module getting the resource
+     * bundle, i.e. find the class that is visible to the class loader
+     * and properties from unnamed module.
+     *
+     * The module-aware resource bundle lookup mechanism will load
+     * the service providers using the service loader mechanism
+     * as well as properties local in the caller module.
+     */
+    private static ResourceBundle getBundleImpl(String baseName,
+                                                Locale locale,
+                                                Class<?> caller,
+                                                ClassLoader loader,
+                                                Control control) {
+        if (caller != null && caller.getModule().isNamed()) {
+            Module module = caller.getModule();
+            ClassLoader ml = getLoader(module);
+            // 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);
+            }
+        }
+        // find resource bundles from unnamed module
+        Module module = loader != null ? loader.getUnnamedModule()
+                                       : ClassLoader.getSystemClassLoader().getUnnamedModule();
+        return getBundleImpl(baseName, locale, loader, module, control);
+    }
+
+    private static ResourceBundle getBundleFromModule(Class<?> caller,
+                                                      Module module,
+                                                      String baseName,
+                                                      Locale locale,
+                                                      Control control) {
+        Objects.requireNonNull(module);
+        if (caller.getModule() != module) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(GET_CLASSLOADER_PERMISSION);
+            }
+        }
+        return getBundleImpl(baseName, locale, getLoader(module), module, control);
+    }
+
+    private static ResourceBundle getBundleImpl(String baseName,
+                                                Locale locale,
+                                                ClassLoader loader,
+                                                Module module,
+                                                Control control) {
         if (locale == null || control == null) {
             throw new NullPointerException();
         }
 
-        // We create a CacheKey here for use by this call. The base
-        // name and loader will never change during the bundle loading
+        // We create a CacheKey here for use by this call. The base name
+        // loader, and module will never change during the bundle loading
         // process. We have to make sure that the locale is set before
         // using it as a cache key.
-        CacheKey cacheKey = new CacheKey(baseName, locale, loader);
+        CacheKey cacheKey = new CacheKey(baseName, locale, loader, module);
         ResourceBundle bundle = null;
 
         // Quick lookup of the cache.
@@ -1358,7 +1656,7 @@
                 throw new IllegalArgumentException("Invalid Control: getCandidateLocales");
             }
 
-            bundle = findBundle(cacheKey, candidateLocales, formats, 0, control, baseBundle);
+            bundle = findBundle(cacheKey, module, 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
@@ -1408,6 +1706,7 @@
     }
 
     private static ResourceBundle findBundle(CacheKey cacheKey,
+                                             Module module,
                                              List<Locale> candidateLocales,
                                              List<String> formats,
                                              int index,
@@ -1416,7 +1715,7 @@
         Locale targetLocale = candidateLocales.get(index);
         ResourceBundle parent = null;
         if (index != candidateLocales.size() - 1) {
-            parent = findBundle(cacheKey, candidateLocales, formats, index + 1,
+            parent = findBundle(cacheKey, module, candidateLocales, formats, index + 1,
                                 control, baseBundle);
         } else if (baseBundle != null && Locale.ROOT.equals(targetLocale)) {
             return baseBundle;
@@ -1462,7 +1761,11 @@
             CacheKey constKey = (CacheKey) cacheKey.clone();
 
             try {
-                bundle = loadBundle(cacheKey, formats, control, expiredBundle);
+                if (module.isNamed()) {
+                    bundle = loadBundle(cacheKey, formats, control, module);
+                } else {
+                    bundle = loadBundle(cacheKey, formats, control, expiredBundle);
+                }
                 if (bundle != null) {
                     if (bundle.parent == null) {
                         bundle.setParent(parent);
@@ -1484,6 +1787,146 @@
         return parent;
     }
 
+    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) {
+        String baseName = cacheKey.getName();
+        Locale targetLocale = cacheKey.getLocale();
+
+        ResourceBundle bundle = null;
+        if (cacheKey.hasProviders()) {
+            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.
+        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);
+                        break;
+                    case "java.properties":
+                        bundle = ResourceBundleProviderSupport.loadPropertyResourceBundle(module, bundleName);
+                        break;
+                    default:
+                        throw new InternalError("unexpected format: " + format);
+                    }
+
+                    if (bundle != null) {
+                        cacheKey.setFormat(format);
+                        break;
+                    }
+                } catch (Exception e) {
+                    cacheKey.setCause(e);
+                }
+            }
+        }
+        return bundle;
+    }
+
+    private static ServiceLoader<ResourceBundleProvider> getServiceLoader(Module module,
+                                                                          String baseName) {
+        PrivilegedAction<ClassLoader> pa = module::getClassLoader;
+        ClassLoader loader = AccessController.doPrivileged(pa);
+        return getServiceLoader(module, loader, baseName);
+    }
+
+        /**
+         * 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)
+    {
+        // 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(
+            new PrivilegedAction<>() {
+                @Override
+                public Class<ResourceBundleProvider> run() {
+                    try {
+                        Class<?> c = Class.forName(providerName, false, loader);
+                        if (ResourceBundleProvider.class.isAssignableFrom(c)) {
+                            @SuppressWarnings("unchecked")
+                            Class<ResourceBundleProvider> s = (Class<ResourceBundleProvider>) c;
+                            return s;
+                        }
+                    } catch (ClassNotFoundException e) {}
+                    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;
+    }
+
+    /**
+     * Loads ResourceBundle from service providers.
+     */
+    private static ResourceBundle loadBundleFromProviders(String baseName,
+                                                          Locale locale,
+                                                          ServiceLoader<ResourceBundleProvider> providers,
+                                                          CacheKey cacheKey)
+    {
+        if (providers == null) return null;
+
+        return AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    public ResourceBundle run() {
+                        for (Iterator<ResourceBundleProvider> itr = providers.iterator(); itr.hasNext(); ) {
+                            try {
+                                ResourceBundleProvider provider = itr.next();
+                                if (cacheKey != null && cacheKey.callerHasProvider == null
+                                        && cacheKey.getModule() == provider.getClass().getModule()) {
+                                    cacheKey.callerHasProvider = Boolean.TRUE;
+                                }
+                                ResourceBundle bundle = provider.getBundle(baseName, locale);
+                                if (bundle != null) {
+                                    return bundle;
+                                }
+                            } catch (ServiceConfigurationError | SecurityException e) {
+                                if (cacheKey != null) {
+                                    cacheKey.setCause(e);
+                                }
+                            }
+                        }
+                        if (cacheKey != null && cacheKey.callerHasProvider == null) {
+                            cacheKey.callerHasProvider = Boolean.FALSE;
+                        }
+                        return null;
+                    }
+                });
+
+    }
+
+    /*
+     * Legacy mechanism to load resource bundles
+     */
     private static ResourceBundle loadBundle(CacheKey cacheKey,
                                              List<String> formats,
                                              Control control,
@@ -1496,6 +1939,7 @@
         ResourceBundle bundle = null;
         for (String format : formats) {
             try {
+                // ResourceBundle.Control.newBundle may be overridden
                 bundle = control.newBundle(cacheKey.getName(), targetLocale, format,
                                            cacheKey.getLoader(), reload);
             } catch (LinkageError | Exception error) {
@@ -1732,35 +2176,54 @@
 
     /**
      * Removes all resource bundles from the cache that have been loaded
-     * using the caller's class loader.
+     * by the caller's module using the caller's class loader.
      *
      * @since 1.6
      * @see ResourceBundle.Control#getTimeToLive(String,Locale)
      */
     @CallerSensitive
     public static final void clearCache() {
-        clearCache(getLoader(Reflection.getCallerClass()));
+        Class<?> caller = Reflection.getCallerClass();
+        clearCache(getLoader(caller), caller.getModule());
     }
 
     /**
      * Removes all resource bundles from the cache that have been loaded
-     * using the given class loader.
+     * by the caller's module using the given class loader.
      *
      * @param loader the class loader
      * @exception NullPointerException if <code>loader</code> is null
      * @since 1.6
      * @see ResourceBundle.Control#getTimeToLive(String,Locale)
      */
+    @CallerSensitive
     public static final void clearCache(ClassLoader loader) {
-        if (loader == null) {
-            throw new NullPointerException();
-        }
+        Objects.requireNonNull(loader);
+        clearCache(loader, Reflection.getCallerClass().getModule());
+    }
+
+    /**
+     * Removes all resource bundles from the cache that have been loaded by the
+     * given {@code module}.
+     *
+     * @param module the module
+     * @throws NullPointerException
+     *         if {@code module} is {@code null}
+     * @throws SecurityException
+     *         if the caller doesn't have the permission to
+     *         {@linkplain Module#getClassLoader() get the class loader}
+     *         of the given {@code module}
+     * @since 9
+     * @see ResourceBundle.Control#getTimeToLive(String,Locale)
+     */
+    public static final void clearCache(Module module) {
+        clearCache(module.getClassLoader(), module);
+    }
+
+    private static void clearCache(ClassLoader loader, Module module) {
         Set<CacheKey> set = cacheList.keySet();
-        for (CacheKey key : set) {
-            if (key.getLoader() == loader) {
-                set.remove(key);
-            }
-        }
+        set.stream().filter((key) -> (key.getLoader() == loader && key.getModule() == module))
+                .forEach(set::remove);
     }
 
     /**
@@ -1871,6 +2334,7 @@
      * the callback methods provides the information necessary for the
      * factory methods to perform the <a
      * href="./ResourceBundle.html#default_behavior">default behavior</a>.
+     * <a href="#note">Note that this class is not supported in named modules.</a>
      *
      * <p>In addition to the callback methods, the {@link
      * #toBundleName(String, Locale) toBundleName} and {@link
@@ -2006,7 +2470,14 @@
      * }
      * </pre>
      *
+     * @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
+     * in named modules.</a> If the {@code ResourceBundle.getBundle} method with
+     * a {@code ResourceBundle.Control} is called in a named module, the method
+     * will throw an {@link UnsupportedOperationException}. Any service providers
+     * of {@link ResourceBundleControlProvider} are ignored in named modules.
+     *
      * @since 1.6
+     * @see java.util.spi.ResourceBundleProvider
      */
     public static class Control {
         /**
@@ -2623,56 +3094,81 @@
          * @exception IOException
          *        if an error occurred when reading resources using
          *        any I/O operations
+         * @see java.util.spi.ResourceBundleProvider#getBundle(String, Locale)
          */
         public ResourceBundle newBundle(String baseName, Locale locale, String format,
                                         ClassLoader loader, boolean reload)
                     throws IllegalAccessException, InstantiationException, IOException {
+            /*
+             * 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;
             if (format.equals("java.class")) {
                 try {
-                    @SuppressWarnings("unchecked")
-                    Class<? extends ResourceBundle> bundleClass
-                        = (Class<? extends ResourceBundle>)loader.loadClass(bundleName);
-
+                    Class<?> c = loader.loadClass(bundleName);
                     // If the class isn't a ResourceBundle subclass, throw a
                     // ClassCastException.
-                    if (ResourceBundle.class.isAssignableFrom(bundleClass)) {
-                        bundle = bundleClass.newInstance();
+                    if (ResourceBundle.class.isAssignableFrom(c)) {
+                        @SuppressWarnings("unchecked")
+                        Class<ResourceBundle> bundleClass = (Class<ResourceBundle>)c;
+
+                        // 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());
+                        }
+                        try {
+                            // bundle in a unnamed module
+                            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);
+                            bundle = ctor.newInstance((Object[]) null);
+                        } catch (InvocationTargetException e) {
+                            uncheckedThrow(e);
+                        }
                     } else {
-                        throw new ClassCastException(bundleClass.getName()
-                                     + " cannot be cast to ResourceBundle");
+                        throw new ClassCastException(c.getName()
+                                + " cannot be cast to ResourceBundle");
                     }
-                } catch (ClassNotFoundException e) {
+                } catch (ClassNotFoundException|NoSuchMethodException e) {
                 }
             } else if (format.equals("java.properties")) {
                 final String resourceName = toResourceName0(bundleName, "properties");
                 if (resourceName == null) {
                     return bundle;
                 }
-                final ClassLoader classLoader = loader;
+
                 final boolean reloadFlag = reload;
                 InputStream stream = null;
                 try {
                     stream = AccessController.doPrivileged(
                         new PrivilegedExceptionAction<>() {
                             public InputStream run() throws IOException {
-                                InputStream is = null;
+                                URL url = loader.getResource(resourceName);
+                                if (url == null) return null;
+
+                                URLConnection connection = url.openConnection();
                                 if (reloadFlag) {
-                                    URL url = classLoader.getResource(resourceName);
-                                    if (url != null) {
-                                        URLConnection connection = url.openConnection();
-                                        if (connection != null) {
-                                            // Disable caches to get fresh data for
-                                            // reloading.
-                                            connection.setUseCaches(false);
-                                            is = connection.getInputStream();
-                                        }
-                                    }
-                                } else {
-                                    is = classLoader.getResourceAsStream(resourceName);
+                                    // Disable caches to get fresh data for
+                                    // reloading.
+                                    connection.setUseCaches(false);
                                 }
-                                return is;
+                                return connection.getInputStream();
                             }
                         });
                 } catch (PrivilegedActionException e) {
@@ -2753,6 +3249,7 @@
          * the <a href="Calendar.html#Epoch"> <code>Calendar</code>
          * Epoch</a>.
          *
+         * <p>
          * The calling <code>ResourceBundle.getBundle</code> factory method
          * calls this method on the <code>ResourceBundle.Control</code>
          * instance used for its current invocation, not on the instance
@@ -2877,6 +3374,7 @@
          * @exception NullPointerException
          *        if <code>baseName</code> or <code>locale</code>
          *        is <code>null</code>
+         * @see java.util.spi.AbstractResourceBundleProvider#toBundleName(String, Locale)
          */
         public String toBundleName(String baseName, Locale locale) {
             if (locale == Locale.ROOT) {
@@ -2951,6 +3449,14 @@
         }
     }
 
+    @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");
+    }
+
     private static class SingleFormatControl extends Control {
         private static final Control PROPERTIES_ONLY
             = new SingleFormatControl(FORMAT_PROPERTIES);
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 cf15891..8d38e78 100644
--- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
+++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,15 +29,30 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Layer;
+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.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.Loader;
+import jdk.internal.loader.LoaderPool;
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.VM;
+import jdk.internal.module.ServicesCatalog;
+import jdk.internal.module.ServicesCatalog.ServiceProvider;
+
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
 
 
 /**
@@ -47,8 +62,11 @@
  * abstract) classes.  A <i>service provider</i> is a specific implementation
  * of a service.  The classes in a provider typically implement the interfaces
  * and subclass the classes defined in the service itself.
- * Providers can be made available by adding them to the
- * application's class path or by some other platform-specific means.
+ * Providers may be developed and deployed as modules and made available using
+ * the application module path. Providers may alternatively be packaged as JAR
+ * files and made available by adding them to the application class path. The
+ * advantage of developing a provider as a module is that the provider can be
+ * fully encapsulated to hide all details of its implementation.
  *
  * <p> For the purpose of loading, a service is represented by a single type,
  * that is, a single interface or abstract class.  (A concrete class can be
@@ -60,27 +78,38 @@
  * 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.  The only requirement enforced by this facility is that
- * provider classes must have a zero-argument constructor so that they can be
- * instantiated during loading.
+ * defined here. A requirement enforced by this facility is that each provider
+ * class must have a {@code public} zero-argument constructor.
  *
- * <p><a name="format"> A service provider is identified by placing a
- * <i>provider-configuration file</i> in the resource directory
- * <tt>META-INF/services</tt>.</a>  The file's name is the fully-qualified <a
- * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
- * The file contains a list of fully-qualified binary names of concrete
+ * <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
+ * implementations of the service. A corresponding requirement is that a
+ * provider deployed as a named modules 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.
+ *
+ * <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
+ * directory <tt>META-INF/services</tt>. The file's name is the fully-qualified
+ * <a href="../lang/ClassLoader.html#name">binary name</a> of the service's
+ * type. The file contains a list of fully-qualified binary names of concrete
  * provider classes, one per line.  Space and tab characters surrounding each
  * name, as well as blank lines, are ignored.  The comment character is
  * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>,
  * <font style="font-size:smaller;">NUMBER SIGN</font>); on
  * each line all characters following the first comment character are ignored.
  * The file must be encoded in UTF-8.
- *
- * <p> If a particular concrete provider class is named in more than one
+ * If a particular concrete provider class is named in more than one
  * configuration file, or is named in the same configuration file more than
  * once, then the duplicates are ignored.  The configuration file naming a
- * particular provider need not be in the same jar file or other distribution
- * unit as the provider itself.  The provider must be accessible from the same
+ * particular provider need not be in the same JAR file or other distribution
+ * unit as the provider itself. The provider must be visible from the same
  * class loader that was initially queried to locate the configuration file;
  * note that this is not necessarily the class loader from which the file was
  * actually loaded.
@@ -93,7 +122,9 @@
  * providers, adding each one to the cache in turn.  The cache can be cleared
  * via the {@link #reload reload} method.
  *
- * <p> Service loaders always execute in the security context of the caller.
+ * <p> Service loaders always execute in the security context of the caller
+ * of the iterator 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.
@@ -104,7 +135,6 @@
  * <p> Unless otherwise specified, passing a <tt>null</tt> 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
  * intended to represent sets of encoder/decoder pairs for some protocol.  In
@@ -118,30 +148,20 @@
  * does not support the given encoding.  Typical providers support more than
  * one encoding.
  *
- * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
- * <tt>CodecSet</tt> service then its jar file also contains a file named
- *
- * <blockquote><pre>
- * META-INF/services/com.example.CodecSet</pre></blockquote>
- *
- * <p> This file contains the single line:
- *
- * <blockquote><pre>
- * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
- *
  * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
  * at initialization:
  *
- * <blockquote><pre>
- * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
- *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
+ * <pre>{@code
+ * private static ServiceLoader<CodecSet> codecSetLoader
+ *     = ServiceLoader.load(CodecSet.class);
+ * }</pre>
  *
  * <p> To locate an encoder for a given encoding name it defines a static
  * factory method which iterates through the known and available providers,
  * returning only when it has located a suitable encoder or has run out of
  * providers.
  *
- * <blockquote><pre>
+ * <pre>{@code
  * public static Encoder getEncoder(String encodingName) {
  *     for (CodecSet cp : codecSetLoader) {
  *         Encoder enc = cp.getEncoder(encodingName);
@@ -149,10 +169,27 @@
  *             return enc;
  *     }
  *     return null;
- * }</pre></blockquote>
+ * }}</pre>
  *
- * <p> A <tt>getDecoder</tt> method is defined similarly.
+ * <p> A {@code getDecoder} method is defined similarly.
  *
+ * <p> If the code creating and using the service loader is developed as
+ * a module then its module descriptor will declare the usage with:
+ * <pre>{@code uses com.example.CodecSet;}</pre>
+ *
+ * <p> Now suppose that {@code com.example.impl.StandardCodecs} is an
+ * implementation of the {@code CodecSet} service and developed as a module.
+ * In that case then the module with the service provider module will declare
+ * this in its module descriptor:
+ * <pre>{@code provides com.example.CodecSet with com.example.impl.StandardCodecs;
+ * }</pre>
+ *
+ * <p> On the other hand, suppose {@code com.example.impl.StandardCodecs} is
+ * packaged in a JAR file for the class path then the JAR file will contain a
+ * file named:
+ * <pre>{@code META-INF/services/com.example.CodecSet}</pre>
+ * that contains the single line:
+ * <pre>{@code com.example.impl.StandardCodecs    # Standard codecs}</pre>
  *
  * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
  * the class path of a class loader that is used for provider loading includes
@@ -183,23 +220,43 @@
 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 loader used to locate, load, and instantiate providers
+    // The module Layer used to locate providers; null when locating
+    // providers using a class loader
+    private final Layer layer;
+
+    // The class loader used to locate, load, and instantiate providers;
+    // null when locating provider using a module Layer
     private final ClassLoader loader;
 
     // The access control context taken when the ServiceLoader is created
     private final AccessControlContext acc;
 
     // Cached providers, in instantiation order
-    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
+    private List<S> providers = new ArrayList<>();
 
-    // The current lazy-lookup iterator
-    private LazyIterator lookupIterator;
+    // The class names of the cached providers, only used when locating
+    // service providers via a class loader
+    private Set<String> providerNames = new HashSet<>();
+
+    // 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
@@ -214,16 +271,110 @@
      */
     public void reload() {
         providers.clear();
-        lookupIterator = new LazyIterator(service, loader);
+
+        assert layer == null || loader == null;
+        if (layer != null) {
+            layerLookupIterator = new LayerLookupIterator();
+        } else {
+            providerNames.clear();
+            moduleServicesIterator = new ModuleServicesIterator();
+            lazyClassPathIterator = new LazyClassPathIterator();
+        }
+
+        reloadCount++;
     }
 
-    private ServiceLoader(Class<S> svc, ClassLoader cl) {
-        service = Objects.requireNonNull(svc, "Service interface cannot be null");
-        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
-        acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
+
+    /**
+     * 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.
+     */
+    private ServiceLoader(Class<?> caller, Layer layer, Class<S> svc) {
+
+        checkModule(caller.getModule(), svc);
+
+        this.service = svc;
+        this.layer = layer;
+        this.loader = null;
+        this.acc = (System.getSecurityManager() != null)
+                ? AccessController.getContext()
+                : null;
+
         reload();
     }
 
+    /**
+     * Initializes a new instance of this class for locating service providers
+     * 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.
+     */
+    private ServiceLoader(Module callerModule, Class<S> svc, ClassLoader cl) {
+        if (VM.isBooted()) {
+
+            checkModule(callerModule, 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 base = Object.class.getModule();
+            Module svcModule = svc.getModule();
+            if (callerModule != base || svcModule != base) {
+                fail(svc, "not accessible to " + callerModule + " during VM init");
+            }
+
+            // restricted to boot loader during startup
+            cl = null;
+        }
+
+        this.service = svc;
+        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);
+    }
+
+
+
+    /**
+     * 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.
+     */
+    private static void checkModule(Module module, Class<?> svc) {
+
+        // 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);
+        }
+
+        // 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);
+        }
+
+    }
+
     private static void fail(Class<?> service, String msg, Throwable cause)
         throws ServiceConfigurationError
     {
@@ -269,71 +420,373 @@
                 if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
                     fail(service, u, lc, "Illegal provider-class name: " + ln);
             }
-            if (!providers.containsKey(ln) && !names.contains(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
-    //
-    // @throws ServiceConfigurationError
-    //         If an I/O error occurs while reading from the given URL, or
-    //         if a configuration-file format error is detected
-    //
+    /**
+     * 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
+     *
+     * @throws ServiceConfigurationError
+     *         If an I/O error occurs while reading from the given URL, or
+     *         if a configuration-file format error is detected
+     *
+     */
     private Iterator<String> parse(Class<?> service, URL u)
         throws ServiceConfigurationError
     {
-        InputStream in = null;
-        BufferedReader r = null;
         ArrayList<String> names = new ArrayList<>();
         try {
-            in = u.openStream();
-            r = new BufferedReader(new InputStreamReader(in, "utf-8"));
-            int lc = 1;
-            while ((lc = parseLine(service, u, r, lc, names)) >= 0);
-        } catch (IOException x) {
-            fail(service, "Error reading configuration file", x);
-        } finally {
-            try {
-                if (r != null) r.close();
-                if (in != null) in.close();
-            } catch (IOException y) {
-                fail(service, "Error closing configuration file", y);
+            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);
             }
+        } catch (IOException x) {
+            fail(service, "Error accessing configuration file", x);
         }
         return names.iterator();
     }
 
-    // Private inner class implementing fully-lazy provider lookup
-    //
-    private class LazyIterator
-        implements Iterator<S>
+    /**
+     * 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();
 
-        Class<S> service;
-        ClassLoader loader;
-        Enumeration<URL> configs = null;
-        Iterator<String> pending = null;
-        String nextName = null;
-
-        private LazyIterator(Class<S> service, ClassLoader loader) {
-            this.service = service;
-            this.loader = loader;
+        // 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");
         }
 
-        private boolean hasNextService() {
+        // 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);
+        }
+    }
+
+    /**
+     * An Iterator that runs the next and hasNext methods with permissions
+     * restricted by the {@code AccessControlContext} obtained when the
+     * ServiceLoader was created.
+     */
+    private abstract class RestrictedIterator<S>
+        implements Iterator<S>
+    {
+        /**
+         * Returns {@code true} if the iteration has more elements.
+         */
+        abstract boolean hasNextService();
+
+        /**
+         * Returns the next element in the iteration
+         */
+        abstract S nextService();
+
+        public final boolean hasNext() {
+            if (acc == null) {
+                return hasNextService();
+            } else {
+                PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
+                    public Boolean run() { return hasNextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
+            }
+        }
+
+        public final S next() {
+            if (acc == null) {
+                return nextService();
+            } else {
+                PrivilegedAction<S> action = new PrivilegedAction<S>() {
+                    public S run() { return nextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
+            }
+        }
+    }
+
+    /**
+     * Implements lazy service provider lookup of service providers that
+     * are provided by modules in a module Layer.
+     *
+     * For now, this iterator examines all modules in each Layer. This will
+     * be replaced once we decide on how the service-use graph is exposed
+     * in the module API.
+     */
+    private class LayerLookupIterator
+        extends RestrictedIterator<S>
+    {
+        final String serviceName;
+        Layer currentLayer;
+        Iterator<ModuleDescriptor> descriptorIterator;
+        Iterator<String> providersIterator;
+
+        Module nextModule;
+        String nextProvider;
+
+        LayerLookupIterator() {
+            serviceName = service.getName();
+            currentLayer = layer;
+
+            // need to get us started
+            descriptorIterator = descriptors(layer, serviceName);
+        }
+
+        Iterator<ModuleDescriptor> descriptors(Layer layer, String service) {
+            return layer.modules().stream()
+                    .map(Module::getDescriptor)
+                    .filter(d -> d.provides().get(service) != null)
+                    .iterator();
+        }
+
+        @Override
+        boolean hasNextService() {
+
+            // already have the next provider cached
+            if (nextProvider != null)
+                return true;
+
+            while (true) {
+
+                // next provider
+                if (providersIterator != null && providersIterator.hasNext()) {
+                    nextProvider = providersIterator.next();
+                    return true;
+                }
+
+                // next descriptor
+                if (descriptorIterator.hasNext()) {
+                    ModuleDescriptor descriptor = descriptorIterator.next();
+
+                    nextModule = currentLayer.findModule(descriptor.name()).get();
+
+                    Provides provides = descriptor.provides().get(serviceName);
+                    providersIterator = provides.providers().iterator();
+
+                    continue;
+                }
+
+                // next layer
+                Layer parent = currentLayer.parent().orElse(null);
+                if (parent == null)
+                    return false;
+
+                currentLayer = parent;
+                descriptorIterator = descriptors(currentLayer, serviceName);
+            }
+        }
+
+        @Override
+        S nextService() {
+            if (!hasNextService())
+                throw new NoSuchElementException();
+
+            assert nextModule != null && nextProvider != null;
+
+            String cn = nextProvider;
+            nextProvider = null;
+
+            // attempt to load the provider
+            Class<?> c = loadClassInModule(nextModule, 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;
+        }
+    }
+
+    /**
+     * Implements lazy service provider lookup of service providers that
+     * are provided by modules defined to a class loader.
+     */
+    private class ModuleServicesIterator
+        extends RestrictedIterator<S>
+    {
+        final JavaLangAccess langAccess = SharedSecrets.getJavaLangAccess();
+
+        ClassLoader currentLoader;
+        Iterator<ServiceProvider> iterator;
+        ServiceProvider nextProvider;
+
+        ModuleServicesIterator() {
+            this.currentLoader = loader;
+            this.iterator = iteratorFor(loader);
+        }
+
+        /**
+         * Returns an iterator to iterate over the implementations of {@code
+         * service} in modules defined to the given 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();
+                }
+            }
+
+            ServicesCatalog catalog;
+            if (currentLoader == null) {
+                catalog = BootLoader.getServicesCatalog();
+            } else {
+                catalog = langAccess.getServicesCatalog(currentLoader);
+            }
+            if (catalog == null) {
+                return Collections.emptyIterator();
+            } else {
+                return catalog.findServices(service.getName()).iterator();
+            }
+        }
+
+        @Override
+        boolean hasNextService() {
+            // already have the next provider cached
+            if (nextProvider != null)
+                return true;
+
+            while (true) {
+                if (iterator.hasNext()) {
+                    nextProvider = iterator.next();
+                    return true;
+                }
+
+                // move to the next class loader if possible
+                if (currentLoader == null) {
+                    return false;
+                } else {
+                    currentLoader = currentLoader.getParent();
+                    iterator = iteratorFor(currentLoader);
+                }
+            }
+        }
+
+        @Override
+        S nextService() {
+            if (!hasNextService())
+                throw new NoSuchElementException();
+
+            ServiceProvider provider = nextProvider;
+            nextProvider = null;
+
+            // attempt to load the 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;
+        }
+    }
+
+    /**
+     * Implements lazy service provider lookup where the service providers
+     * are configured via service configuration files.
+     */
+    private class LazyClassPathIterator
+        extends RestrictedIterator<S>
+    {
+        Enumeration<URL> configs;
+        Iterator<String> pending;
+        String nextName;
+
+        @Override
+        boolean hasNextService() {
             if (nextName != null) {
                 return true;
             }
@@ -358,7 +811,8 @@
             return true;
         }
 
-        private S nextService() {
+        @Override
+        S nextService() {
             if (!hasNextService())
                 throw new NoSuchElementException();
             String cn = nextName;
@@ -374,44 +828,18 @@
                 fail(service,
                      "Provider " + cn  + " not a subtype");
             }
+            S p = null;
             try {
-                S p = service.cast(c.newInstance());
-                providers.put(cn, p);
-                return p;
+                p = service.cast(c.newInstance());
             } catch (Throwable x) {
                 fail(service,
                      "Provider " + cn + " could not be instantiated",
                      x);
             }
-            throw new Error();          // This cannot happen
+            providers.add(p);
+            providerNames.add(cn);
+            return p;
         }
-
-        public boolean hasNext() {
-            if (acc == null) {
-                return hasNextService();
-            } else {
-                PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
-                    public Boolean run() { return hasNextService(); }
-                };
-                return AccessController.doPrivileged(action, acc);
-            }
-        }
-
-        public S next() {
-            if (acc == null) {
-                return nextService();
-            } else {
-                PrivilegedAction<S> action = new PrivilegedAction<S>() {
-                    public S run() { return nextService(); }
-                };
-                return AccessController.doPrivileged(action, acc);
-            }
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
     }
 
     /**
@@ -422,16 +850,14 @@
      * loads and instantiates any remaining providers, adding each one to the
      * cache in turn.
      *
-     * <p> To achieve laziness the actual work of parsing the available
-     * provider-configuration files 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-configuration file
-     * violates the specified format, or if it names a provider class that
-     * cannot be found and instantiated, or if the result of instantiating the
-     * class is not assignable 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
+     * <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.
      *
      * <p> If such an error is thrown then subsequent invocations of the
@@ -447,6 +873,14 @@
      * 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
+     * #reload() reload} method then existing iterators for this service
+     * loader should be discarded.
+     * The {@link java.util.Iterator#hasNext() hasNext} and {@link
+     * java.util.Iterator#next() next} methods of the iterator throw {@link
+     * java.util.ConcurrentModificationException ConcurrentModificationException}
+     * if used after the provider cache has been cleared.
+     *
      * <p> The iterator returned by this method does not support removal.
      * Invoking its {@link java.util.Iterator#remove() remove} method will
      * cause an {@link UnsupportedOperationException} to be thrown.
@@ -463,29 +897,85 @@
     public Iterator<S> iterator() {
         return new Iterator<S>() {
 
-            Iterator<Map.Entry<String,S>> knownProviders
-                = providers.entrySet().iterator();
+            // record reload count
+            final int expectedReloadCount = ServiceLoader.this.reloadCount;
+
+            // index into the cached providers list
+            int index;
+
+            /**
+             * Throws ConcurrentModificationException if the list of cached
+             * providers has been cleared by reload.
+             */
+            private void checkReloadCount() {
+                if (ServiceLoader.this.reloadCount != expectedReloadCount)
+                    throw new ConcurrentModificationException();
+            }
 
             public boolean hasNext() {
-                if (knownProviders.hasNext())
+                checkReloadCount();
+                if (index < providers.size())
                     return true;
-                return lookupIterator.hasNext();
+
+                if (layerLookupIterator != null) {
+                    return layerLookupIterator.hasNext();
+                } else {
+                    return moduleServicesIterator.hasNext() ||
+                            lazyClassPathIterator.hasNext();
+                }
             }
 
             public S next() {
-                if (knownProviders.hasNext())
-                    return knownProviders.next().getValue();
-                return lookupIterator.next();
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
+                checkReloadCount();
+                S next;
+                if (index < providers.size()) {
+                    next = providers.get(index);
+                } else {
+                    if (layerLookupIterator != null) {
+                        next = layerLookupIterator.next();
+                    } else {
+                        if (moduleServicesIterator.hasNext()) {
+                            next = moduleServicesIterator.next();
+                        } else {
+                            next = lazyClassPathIterator.next();
+                        }
+                    }
+                }
+                index++;
+                return next;
             }
 
         };
     }
 
     /**
+     * Creates a new service loader for the given service type, class
+     * loader, and caller.
+     *
+     * @param  <S> the class of the service type
+     *
+     * @param  service
+     *         The interface or abstract class representing the service
+     *
+     * @param  loader
+     *         The class loader to be used to load provider-configuration files
+     *         and provider classes, or <tt>null</tt> if the system class
+     *         loader (or, failing that, the bootstrap class loader) is to be
+     *         used
+     *
+     * @param  callerModule
+     *         The caller's module for which a new service loader is created
+     *
+     * @return A new service loader
+     */
+    static <S> ServiceLoader<S> load(Class<S> service,
+                                     ClassLoader loader,
+                                     Module callerModule)
+    {
+        return new ServiceLoader<>(callerModule, service, loader);
+    }
+
+    /**
      * Creates a new service loader for the given service type and class
      * loader.
      *
@@ -496,16 +986,22 @@
      *
      * @param  loader
      *         The class loader to be used to load provider-configuration files
-     *         and provider classes, or <tt>null</tt> if the system class
+     *         and provider classes, or {@code null} if the system class
      *         loader (or, failing that, the bootstrap class loader) is to be
      *         used
      *
      * @return A new service loader
+     *
+     * @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
+     *         not declare that it uses {@code service}
      */
+    @CallerSensitive
     public static <S> ServiceLoader<S> load(Class<S> service,
                                             ClassLoader loader)
     {
-        return new ServiceLoader<>(service, loader);
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, loader);
     }
 
     /**
@@ -530,30 +1026,32 @@
      *         The interface or abstract class representing the service
      *
      * @return A new service loader
+     *
+     * @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
+     *         not declare that it uses {@code service}
      */
+    @CallerSensitive
     public static <S> ServiceLoader<S> load(Class<S> service) {
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        return ServiceLoader.load(service, cl);
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
     }
 
     /**
      * Creates a new service loader for the given service type, using the
-     * extension class loader.
+     * {@linkplain ClassLoader#getPlatformClassLoader() platform class loader}.
      *
-     * <p> This convenience method simply locates the extension class loader,
-     * call it <tt><i>extClassLoader</i></tt>, and then returns
+     * <p> This convenience method is equivalent to: </p>
      *
      * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
-     *
-     * <p> If the extension class loader cannot be found then the system class
-     * loader is used; if there is no system class loader then the bootstrap
-     * class loader is used.
+     * ServiceLoader.load(<i>service</i>, <i>ClassLoader.getPlatformClassLoader())</i>
+     * </pre></blockquote>
      *
      * <p> This method is intended for use when only installed providers are
      * desired.  The resulting service will only find and load providers that
      * have been installed into the current Java virtual machine; providers on
-     * the application's class path will be ignored.
+     * the application's module path or class path will be ignored.
      *
      * @param  <S> the class of the service type
      *
@@ -561,7 +1059,13 @@
      *         The interface or abstract class representing the service
      *
      * @return A new service loader
+     *
+     * @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
+     *         not declare that it uses {@code service}
      */
+    @CallerSensitive
     public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
         ClassLoader cl = ClassLoader.getSystemClassLoader();
         ClassLoader prev = null;
@@ -569,7 +1073,40 @@
             prev = cl;
             cl = cl.getParent();
         }
-        return ServiceLoader.load(service, prev);
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, prev);
+    }
+
+    /**
+     * Creates a new service loader for the given service type that loads
+     * service providers from modules in the given {@code Layer} and its
+     * ancestors.
+     *
+     * @apiNote Unlike the other load methods defined here, the service type
+     * is the second parameter. The reason for this is to avoid source
+     * compatibility issues for code that uses {@code load(S, null)}.
+     *
+     * @param  <S> the class of the service type
+     *
+     * @param  layer
+     *         The module Layer
+     *
+     * @param  service
+     *         The interface or abstract class representing the service
+     *
+     * @return A new service loader
+     *
+     * @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
+     *         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));
     }
 
     /**
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
new file mode 100644
index 0000000..1a6ee65
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.spi;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Module;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Locale;
+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.
+ *
+ * @since 9
+ */
+public abstract class AbstractResourceBundleProvider implements ResourceBundleProvider {
+    private static final String FORMAT_CLASS = "java.class";
+    private static final String FORMAT_PROPERTIES = "java.properties";
+
+    private final String[] formats;
+
+    /**
+     * Constructs an {@code AbstractResourceBundleProvider} with the
+     * "java.properties" format. This constructor is equivalent to
+     * {@code AbstractResourceBundleProvider("java.properties")}.
+     */
+    protected AbstractResourceBundleProvider() {
+        this(FORMAT_PROPERTIES);
+    }
+
+    /**
+     * Constructs an {@code AbstractResourceBundleProvider} with the specified
+     * {@code formats}. The {@link #getBundle(String, Locale)} method looks up
+     * resource bundles for the given {@code formats}. {@code formats} must
+     * be "java.class" or "java.properties".
+     *
+     * @param formats the formats to be used for loading resource bundles
+     * @throws NullPointerException if the given {@code formats} is null
+     * @throws IllegalArgumentException if the given {@code formats} is not
+     *         "java.class" or "java.properties".
+     */
+    protected AbstractResourceBundleProvider(String... formats) {
+        this.formats = formats.clone();  // defensive copy
+        if (this.formats.length == 0) {
+            throw new IllegalArgumentException("empty formats");
+        }
+        for (String f : this.formats) {
+            if (!FORMAT_CLASS.equals(f) && !FORMAT_PROPERTIES.equals(f)) {
+                throw new IllegalArgumentException(f);
+            }
+        }
+    }
+
+    /**
+     * Returns the bundle name for the given {@code baseName} and {@code
+     * locale}.  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
+     * implementation of
+     * {@link java.util.ResourceBundle.Control#toBundleName(String, Locale)}.
+     *
+     * @param baseName the base name of the resource bundle, a fully qualified
+     *                 class name
+     * @param locale   the locale for which a resource bundle should be loaded
+     * @return the bundle name for the resource bundle
+     */
+    protected String toBundleName(String baseName, Locale locale) {
+        return ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT)
+                   .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.
+     *
+     * @implNote
+     * The default implementation of this method will find the resource bundle
+     * local to the module of this provider.
+     *
+     * @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
+     * @throws UncheckedIOException if any IO exception occurred during resource
+     *         bundle loading
+     */
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        Module module = this.getClass().getModule();
+        String bundleName = toBundleName(baseName, locale);
+        ResourceBundle bundle = null;
+        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);
+                } else if (FORMAT_PROPERTIES.equals(format)) {
+                    bundle = ResourceBundleProviderSupport
+                                 .loadPropertyResourceBundle(module, bundleName);
+                }
+                if (bundle != null) {
+                    break;
+                }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+        return bundle;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java b/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
index a215e86..3005df4 100644
--- a/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
+++ b/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
@@ -42,6 +42,8 @@
  * ResourceBundleControlProvider} implementations are loaded using {@link
  * java.util.ServiceLoader} at the {@code ResourceBundle} class loading time.
  *
+ * <p>All {@code ResourceBundleControlProvider}s are ignored in named modules.
+ *
  * @author Masayoshi Okutsu
  * @since 1.8
  * @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
diff --git a/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java b/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java
new file mode 100644
index 0000000..714ae62
--- /dev/null
+++ b/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.spi;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * {@code ResourceBundleProvider} is a provider interface that is used for
+ * loading resource bundles. Implementation classes of this interface are loaded
+ * with {@link java.util.ServiceLoader ServiceLoader} during a call to the
+ * {@link ResourceBundle#getBundle(String, Locale, ClassLoader)
+ * ResourceBundle.getBundle} method. The provider service type is determined by
+ * {@code basename+"Provider"}. For example, if the base name is
+ * "com.example.app.MyResources", {@code com.example.app.MyResourcesProvider}
+ * will be the provider service type.
+ * <p>
+ * This providers's {@link #getBundle(String, Locale) getBundle} method is called
+ * through the resource bundle loading process instead of {@link
+ * java.util.ResourceBundle.Control#newBundle(String, Locale, String, ClassLoader, boolean)
+ * ResourceBundle.Control.newBundle()}. Refer to {@link ResourceBundle} for
+ * details.
+ *
+ * @since 9
+ */
+public interface ResourceBundleProvider {
+    /**
+     * Returns a {@code ResourceBundle} for the given bundle name and locale.
+     * This method returns null if there is no {@code ResourceBundle} found
+     * for the given parameters.
+     *
+     *
+     * @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 loaded
+     * @return the ResourceBundle created for the given parameters, or null if no
+     *         {@code ResourceBundle} for the given parameters is found
+     */
+    public ResourceBundle getBundle(String baseName, Locale locale);
+}
diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java
index 338aa12..d4fffac 100644
--- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java
+++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java
@@ -251,11 +251,8 @@
 
         File exportJar = new File(pathToPolicyJar, "US_export_policy.jar");
         File importJar = new File(pathToPolicyJar, "local_policy.jar");
-        URL jceCipherURL = ClassLoader.getSystemResource
-                ("javax/crypto/Cipher.class");
 
-        if ((jceCipherURL == null) ||
-                !exportJar.exists() || !importJar.exists()) {
+        if (!exportJar.exists() || !importJar.exists()) {
             throw new SecurityException
                                 ("Cannot locate policy or framework files!");
         }
diff --git a/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java b/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java
index 9cee4d0..743125b 100644
--- a/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java
+++ b/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java
@@ -453,9 +453,6 @@
 }
 
 final class extObjectInputStream extends ObjectInputStream {
-
-    private static ClassLoader systemClassLoader = null;
-
     extObjectInputStream(InputStream in)
         throws IOException, StreamCorruptedException {
         super(in);
@@ -478,10 +475,7 @@
              */
             ClassLoader loader = Thread.currentThread().getContextClassLoader();
             if (loader == null) {
-                if (systemClassLoader == null) {
-                    systemClassLoader = ClassLoader.getSystemClassLoader();
-                }
-                loader = systemClassLoader;
+                loader = ClassLoader.getSystemClassLoader();
                 if (loader == null) {
                     throw new ClassNotFoundException(v.getName());
                 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/Archive.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/Archive.java
deleted file mode 100644
index 96f5e25..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/Archive.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.stream.Stream;
-
-/**
- * An Archive of all content, classes, resources, configuration files, and
- * other, for a module.
- */
-public interface Archive {
-
-    /**
-     * Entry is contained in an Archive
-     */
-    public abstract class Entry {
-
-        public static enum EntryType {
-
-            MODULE_NAME,
-            CLASS_OR_RESOURCE,
-            NATIVE_LIB,
-            NATIVE_CMD,
-            CONFIG,
-            SERVICE;
-        }
-
-        private final String name;
-        private final EntryType type;
-        private final Archive archive;
-        private final String path;
-
-        public Entry(Archive archive, String path, String name, EntryType type) {
-            this.archive = archive;
-            this.path = path;
-            this.name = name;
-            this.type = type;
-        }
-
-        public Archive archive() {
-            return archive;
-        }
-
-        public String path() {
-            return path;
-        }
-
-        public EntryType type() {
-            return type;
-        }
-
-        /**
-         * Returns the name of this entry.
-         */
-        public String name() {
-            return name;
-        }
-
-        @Override
-        public String toString() {
-            return "type " + type.name() + " path " + path;
-        }
-
-        /**
-         * Returns the number of uncompressed bytes for this entry.
-         */
-        public abstract long size();
-
-        public abstract InputStream stream() throws IOException;
-    }
-
-    /**
-     * The module name.
-     */
-    String moduleName();
-
-    /**
-     * Stream of Entry.
-     * The stream of entries needs to be closed after use
-     * since it might cover lazy I/O based resources.
-     * So callers need to use a try-with-resources block.
-     */
-    Stream<Entry> entries();
-
-    /**
-     * Open the archive
-     */
-    void open() throws IOException;
-
-    /**
-     * Close the archive
-     */
-    void close() throws IOException;
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
index 731f36e..15c888d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.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,183 +26,288 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.File;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.IntBuffer;
-import java.util.Comparator;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Objects;
 import java.util.stream.IntStream;
+import jdk.internal.jimage.decompressor.Decompressor;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 public class BasicImageReader implements AutoCloseable {
-    private final String imagePath;
-    private final ImageSubstrate substrate;
-    private final ByteOrder byteOrder;
-    private final ImageStringsReader strings;
-
-    protected BasicImageReader(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        this.imagePath = imagePath;
-        this.substrate = openImageSubstrate(imagePath, byteOrder);
-        this.byteOrder = byteOrder;
-        this.strings = new ImageStringsReader(this);
+    private static boolean isSystemProperty(String key, String value, String def) {
+        // No lambdas during bootstrap
+        return AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                @Override
+                public Boolean run() {
+                    return value.equals(System.getProperty(key, def));
+                }
+            });
     }
 
-    protected BasicImageReader(String imagePath) throws IOException {
+    static private final boolean IS_64_BIT =
+            isSystemProperty("sun.arch.data.model", "64", "32");
+    static private final boolean USE_JVM_MAP =
+            isSystemProperty("jdk.image.use.jvm.map", "true", "true");
+    static private final boolean MAP_ALL =
+            isSystemProperty("jdk.image.map.all", "true", IS_64_BIT ? "true" : "false");
+
+    private final String name;
+    private final ByteOrder byteOrder;
+    private final Path imagePath;
+    private final ByteBuffer memoryMap;
+    private final FileChannel channel;
+    private final ImageHeader header;
+    private final long indexSize;
+    private final IntBuffer redirect;
+    private final IntBuffer offsets;
+    private final ByteBuffer locations;
+    private final ByteBuffer strings;
+    private final ImageStringsReader stringsReader;
+    private final Decompressor decompressor;
+
+    protected BasicImageReader(Path path, ByteOrder byteOrder)
+            throws IOException {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(byteOrder);
+        this.name = path.toString();
+        this.byteOrder = byteOrder;
+        imagePath = path;
+
+        ByteBuffer map;
+
+        if (USE_JVM_MAP && BasicImageReader.class.getClassLoader() == null) {
+            // Check to see if the jvm has opened the file using libjimage
+            // native entry when loading the image for this runtime
+            map = NativeImageBuffer.getNativeMap(name);
+         } else {
+            map = null;
+        }
+
+        // Open the file only if no memory map yet or is 32 bit jvm
+        channel = map != null && MAP_ALL ? null :
+                  FileChannel.open(imagePath, StandardOpenOption.READ);
+
+        // If no memory map yet and 64 bit jvm then memory map entire file
+        if (MAP_ALL && map == null) {
+            map = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+        }
+
+        // Assume we have a memory map to read image file header
+        ByteBuffer headerBuffer = map;
+        int headerSize = ImageHeader.getHeaderSize();
+
+        // If no memory map then read header from image file
+        if (map == null) {
+            headerBuffer = ByteBuffer.allocateDirect(headerSize);
+            channel.read(headerBuffer, 0L);
+            headerBuffer.rewind();
+        }
+
+        // Interpret the image file header
+        header = readHeader(intBuffer(headerBuffer, 0, headerSize));
+        indexSize = header.getIndexSize();
+
+        // If no memory map yet then must be 32 bit jvm not previously mapped
+        if (map == null) {
+            // Just map the image index
+            map = channel.map(FileChannel.MapMode.READ_ONLY, 0, indexSize);
+        }
+
+        memoryMap = map.asReadOnlyBuffer();
+
+        // Interpret the image index
+        redirect = intBuffer(memoryMap, header.getRedirectOffset(), header.getRedirectSize());
+        offsets = intBuffer(memoryMap, header.getOffsetsOffset(), header.getOffsetsSize());
+        locations = slice(memoryMap, header.getLocationsOffset(), header.getLocationsSize());
+        strings = slice(memoryMap, header.getStringsOffset(), header.getStringsSize());
+
+        stringsReader = new ImageStringsReader(this);
+        decompressor = new Decompressor();
+    }
+
+    protected BasicImageReader(Path imagePath) throws IOException {
         this(imagePath, ByteOrder.nativeOrder());
     }
 
-    private static ImageSubstrate openImageSubstrate(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        ImageSubstrate substrate;
-
-        try {
-            substrate = ImageNativeSubstrate.openImage(imagePath, byteOrder);
-        } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) {
-            substrate = ImageJavaSubstrate.openImage(imagePath, byteOrder);
-        }
-
-        return substrate;
+    public static BasicImageReader open(Path imagePath) throws IOException {
+        return new BasicImageReader(imagePath, ByteOrder.nativeOrder());
     }
 
-    public static BasicImageReader open(String imagePath) throws IOException {
-        return new BasicImageReader(imagePath, ByteOrder.nativeOrder());
+    public ImageHeader getHeader() {
+        return header;
+    }
+
+    private ImageHeader readHeader(IntBuffer buffer) throws IOException {
+        ImageHeader result = ImageHeader.readFrom(buffer);
+
+        if (result.getMagic() != ImageHeader.MAGIC) {
+            throw new IOException("\"" + name + "\" is not an image file");
+        }
+
+        if (result.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
+            result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
+            throw new IOException("The image file \"" + name + "\" is not the correct version");
+        }
+
+        return result;
+    }
+
+    private static ByteBuffer slice(ByteBuffer buffer, int position, int capacity) {
+        // Note that this is the only limit and position manipulation of
+        // BasicImageReader private ByteBuffers.  The synchronize could be avoided
+        // by cloning the buffer to make a local copy, but at the cost of creating
+        // a new object.
+        synchronized(buffer) {
+            buffer.limit(position + capacity);
+            buffer.position(position);
+            return buffer.slice();
+        }
+    }
+
+    private IntBuffer intBuffer(ByteBuffer buffer, int offset, int size) {
+        return slice(buffer, offset, size).order(byteOrder).asIntBuffer();
     }
 
     public static void releaseByteBuffer(ByteBuffer buffer) {
         ImageBufferCache.releaseBuffer(buffer);
     }
 
+    public String getName() {
+        return name;
+    }
+
     public ByteOrder getByteOrder() {
         return byteOrder;
     }
 
-    public String imagePath() {
+    public Path getImagePath() {
         return imagePath;
     }
 
-    public String imagePathName() {
-        int slash = imagePath().lastIndexOf(File.separator);
-
-        if (slash != -1) {
-            return imagePath().substring(slash + 1);
-        }
-
-        return imagePath();
-    }
-
-    public boolean isOpen() {
-        return true;
-    }
-
+    @Override
     public void close() throws IOException {
-        substrate.close();
-    }
-
-    public ImageHeader getHeader() throws IOException {
-        return ImageHeader.readFrom(
-                getIndexIntBuffer(0, ImageHeader.getHeaderSize()));
+        if (channel != null) {
+            channel.close();
+        }
     }
 
     public ImageStringsReader getStrings() {
-        return strings;
+        return stringsReader;
     }
 
-    public ImageLocation findLocation(String name) {
-        return findLocation(new UTF8String(name));
+    public ImageLocation findLocation(String mn, String rn) {
+        return findLocation("/" + mn + "/" + rn);
     }
 
-    public ImageLocation findLocation(byte[] name) {
-        return findLocation(new UTF8String(name));
-    }
+    public synchronized ImageLocation findLocation(String name) {
+        // Details of the algorithm used here can be found in
+        // jdk.tools.jlink.internal.PerfectHashBuilder.
+        byte[] bytes = ImageStringsReader.mutf8FromString(name);
+        int count = header.getTableLength();
+        int index = redirect.get(ImageStringsReader.hashCode(bytes) % count);
 
-    public synchronized ImageLocation findLocation(UTF8String name) {
-        return substrate.findLocation(name, strings);
+        if (index < 0) {
+            // index is twos complement of location attributes index.
+            index = -index - 1;
+        } else if (index > 0) {
+            // index is hash seed needed to compute location attributes index.
+            index = ImageStringsReader.hashCode(bytes, index) % count;
+        } else {
+            // No entry.
+            return null;
+        }
+
+        long[] attributes = getAttributes(offsets.get(index));
+
+        ImageLocation imageLocation = new ImageLocation(attributes, stringsReader);
+
+        if (!imageLocation.verify(name)) {
+            return null;
+        }
+
+        return imageLocation;
     }
 
     public String[] getEntryNames() {
-        return IntStream.of(substrate.attributeOffsets())
+        int[] attributeOffsets = new int[offsets.capacity()];
+        offsets.get(attributeOffsets);
+        return IntStream.of(attributeOffsets)
                         .filter(o -> o != 0)
-                        .mapToObj(o -> ImageLocation.readFrom(this, o).getFullNameString())
+                        .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
                         .sorted()
                         .toArray(String[]::new);
     }
 
-    protected ImageLocation[] getAllLocations(boolean sorted) {
-        return IntStream.of(substrate.attributeOffsets())
-                        .filter(o -> o != 0)
-                        .mapToObj(o -> ImageLocation.readFrom(this, o))
-                        .sorted(Comparator.comparing(ImageLocation::getFullNameString))
-                        .toArray(ImageLocation[]::new);
-    }
-
-    private IntBuffer getIndexIntBuffer(long offset, long size)
-            throws IOException {
-        ByteBuffer buffer = substrate.getIndexBuffer(offset, size);
-        buffer.order(byteOrder);
-
-        return buffer.asIntBuffer();
-    }
-
     ImageLocation getLocation(int offset) {
         return ImageLocation.readFrom(this, offset);
     }
 
     public long[] getAttributes(int offset) {
-        return substrate.getAttributes(offset);
+        ByteBuffer buffer = slice(locations, offset, locations.limit() - offset);
+        return ImageLocation.decompress(buffer);
     }
 
     public String getString(int offset) {
-        return getUTF8String(offset).toString();
+        ByteBuffer buffer = slice(strings, offset, strings.limit() - offset);
+        return ImageStringsReader.stringFromByteBuffer(buffer);
     }
 
-    public UTF8String getUTF8String(int offset) {
-        return new UTF8String(substrate.getStringBytes(offset));
-    }
-
-    private byte[] getBufferBytes(ByteBuffer buffer, long size) {
-        assert size < Integer.MAX_VALUE;
-        byte[] bytes = new byte[(int)size];
+    private byte[] getBufferBytes(ByteBuffer buffer) {
+        byte[] bytes = new byte[buffer.limit()];
         buffer.get(bytes);
 
         return bytes;
     }
 
-    private byte[] getBufferBytes(long offset, long size) {
-        ByteBuffer buffer = substrate.getDataBuffer(offset, size);
-
-        return getBufferBytes(buffer, size);
-    }
-
-    public byte[] getResource(ImageLocation loc) {
-        long offset = loc.getContentOffset();
-        long compressedSize = loc.getCompressedSize();
-        long uncompressedSize = loc.getUncompressedSize();
-        assert compressedSize < Integer.MAX_VALUE;
-        assert uncompressedSize < Integer.MAX_VALUE;
-
-        if (substrate.supportsDataBuffer() && compressedSize == 0) {
-            return getBufferBytes(offset, uncompressedSize);
+    private ByteBuffer readBuffer(long offset, long size) {
+        if (offset < 0 || Integer.MAX_VALUE <= offset) {
+            throw new IndexOutOfBoundsException("offset");
         }
 
-        ByteBuffer uncompressedBuffer = ImageBufferCache.getBuffer(uncompressedSize);
-        boolean isRead;
+        if (size < 0 || Integer.MAX_VALUE <= size) {
+            throw new IndexOutOfBoundsException("size");
+        }
 
-        if (compressedSize != 0) {
-            ByteBuffer compressedBuffer = ImageBufferCache.getBuffer(compressedSize);
-            isRead = substrate.read(offset, compressedBuffer, compressedSize,
-                                          uncompressedBuffer, uncompressedSize);
-            ImageBufferCache.releaseBuffer(compressedBuffer);
+        if (MAP_ALL) {
+            ByteBuffer buffer = slice(memoryMap, (int)offset, (int)size);
+            buffer.order(ByteOrder.BIG_ENDIAN);
+
+            return buffer;
         } else {
-            isRead = substrate.read(offset, uncompressedBuffer, uncompressedSize);
+            ByteBuffer buffer = ImageBufferCache.getBuffer(size);
+            int read = 0;
+
+            try {
+                if (channel == null) {
+                    throw new InternalError("Image file channel not open");
+                }
+
+                read = channel.read(buffer, offset);
+                buffer.rewind();
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+
+            if (read != size) {
+                ImageBufferCache.releaseBuffer(buffer);
+            }
+
+            return buffer;
         }
-
-        byte[] bytes = isRead ? getBufferBytes(uncompressedBuffer,
-                                               uncompressedSize) : null;
-
-        ImageBufferCache.releaseBuffer(uncompressedBuffer);
-
-        return bytes;
     }
 
     public byte[] getResource(String name) {
@@ -211,42 +316,54 @@
         return location != null ? getResource(location) : null;
     }
 
-    public ByteBuffer getResourceBuffer(ImageLocation loc) {
-        long offset = loc.getContentOffset();
-        long compressedSize = loc.getCompressedSize();
-        long uncompressedSize = loc.getUncompressedSize();
-        assert compressedSize < Integer.MAX_VALUE;
-        assert uncompressedSize < Integer.MAX_VALUE;
+    public byte[] getResource(ImageLocation loc) {
+        ByteBuffer buffer = getResourceBuffer(loc);
 
-        if (substrate.supportsDataBuffer() && compressedSize == 0) {
-            return substrate.getDataBuffer(offset, uncompressedSize);
+        if (buffer != null) {
+            byte[] bytes = getBufferBytes(buffer);
+            ImageBufferCache.releaseBuffer(buffer);
+
+            return bytes;
         }
 
-        ByteBuffer uncompressedBuffer = ImageBufferCache.getBuffer(uncompressedSize);
-        boolean isRead;
-
-        if (compressedSize != 0) {
-            ByteBuffer compressedBuffer = ImageBufferCache.getBuffer(compressedSize);
-            isRead = substrate.read(offset, compressedBuffer, compressedSize,
-                                          uncompressedBuffer, uncompressedSize);
-            ImageBufferCache.releaseBuffer(compressedBuffer);
-        } else {
-            isRead = substrate.read(offset, uncompressedBuffer, uncompressedSize);
-        }
-
-        if (isRead) {
-            return uncompressedBuffer;
-        } else {
-            ImageBufferCache.releaseBuffer(uncompressedBuffer);
-
-            return null;
-        }
+        return null;
     }
 
-    public ByteBuffer getResourceBuffer(String name) {
-        ImageLocation location = findLocation(name);
+    public ByteBuffer getResourceBuffer(ImageLocation loc) {
+        long offset = loc.getContentOffset() + indexSize;
+        long compressedSize = loc.getCompressedSize();
+        long uncompressedSize = loc.getUncompressedSize();
 
-        return location != null ? getResourceBuffer(location) : null;
+        if (compressedSize < 0 || Integer.MAX_VALUE < compressedSize) {
+            throw new IndexOutOfBoundsException("Compressed size");
+        }
+
+        if (uncompressedSize < 0 || Integer.MAX_VALUE < uncompressedSize) {
+            throw new IndexOutOfBoundsException("Uncompressed size");
+        }
+
+        if (compressedSize == 0) {
+            return readBuffer(offset, uncompressedSize);
+        } else {
+            ByteBuffer buffer = readBuffer(offset, compressedSize);
+
+            if (buffer != null) {
+                byte[] bytesIn = getBufferBytes(buffer);
+                ImageBufferCache.releaseBuffer(buffer);
+                byte[] bytesOut;
+
+                try {
+                    bytesOut = decompressor.decompressResource(byteOrder,
+                            (int strOffset) -> getString(strOffset), bytesIn);
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+
+                return ByteBuffer.wrap(bytesOut);
+            }
+        }
+
+        return null;
     }
 
     public InputStream getResourceStream(ImageLocation loc) {
@@ -254,10 +371,4 @@
 
         return new ByteArrayInputStream(bytes);
     }
-
-    public InputStream getResourceStream(String name) {
-        ImageLocation location = findLocation(name);
-
-        return location != null ? getResourceStream(location) : null;
-    }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java
deleted file mode 100644
index 60a5cd1..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
-*/
-
-package jdk.internal.jimage;
-
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.List;
-
-public final class BasicImageWriter {
-
-    public static final String IMAGE_EXT = ".jimage";
-    public static final String BOOT_NAME = "bootmodules";
-    public static final String BOOT_IMAGE_NAME = BOOT_NAME + IMAGE_EXT;
-
-    private static final int RETRY_LIMIT = 1000;
-
-    private ByteOrder byteOrder;
-    private ImageStringsWriter strings;
-    private int length;
-    private int[] redirect;
-    private ImageLocationWriter[] locations;
-    private List<ImageLocationWriter> input;
-    private ImageStream headerStream;
-    private ImageStream redirectStream;
-    private ImageStream locationOffsetStream;
-    private ImageStream locationStream;
-    private ImageStream allIndexStream;
-
-    public BasicImageWriter() {
-        this(ByteOrder.nativeOrder());
-    }
-
-    public BasicImageWriter(ByteOrder byteOrder) {
-        this.byteOrder = byteOrder;
-        this.input = new ArrayList<>();
-        this.strings = new ImageStringsWriter();
-        this.headerStream = new ImageStream(byteOrder);
-        this.redirectStream = new ImageStream(byteOrder);
-        this.locationOffsetStream = new ImageStream(byteOrder);
-        this.locationStream = new ImageStream(byteOrder);
-        this.allIndexStream = new ImageStream(byteOrder);
-    }
-
-    public ByteOrder getByteOrder() {
-        return byteOrder;
-    }
-
-    public int addString(String string) {
-        return addString(new UTF8String(string));
-    }
-
-    public int addString(UTF8String string) {
-        return strings.add(string);
-    }
-
-    public String getString(int offset) {
-        UTF8String utf8 = strings.get(offset);
-        return utf8 != null? utf8.toString() : null;
-    }
-
-    public void addLocation(String fullname, long contentOffset,
-            long compressedSize, long uncompressedSize) {
-        ImageLocationWriter location =
-                ImageLocationWriter.newLocation(new UTF8String(fullname), strings,
-                        contentOffset, compressedSize, uncompressedSize);
-        input.add(location);
-        length++;
-    }
-
-    ImageLocationWriter[] getLocations() {
-        return locations;
-    }
-
-    int getLocationsCount() {
-        return input.size();
-    }
-
-    private void generatePerfectHash() {
-        PerfectHashBuilder<ImageLocationWriter> builder =
-            new PerfectHashBuilder<>(
-                new PerfectHashBuilder.Entry<ImageLocationWriter>().getClass(),
-                new PerfectHashBuilder.Bucket<ImageLocationWriter>().getClass());
-
-        input.forEach((location) -> {
-            builder.put(location.getFullName(), location);
-        });
-
-        builder.generate();
-
-        length = builder.getCount();
-        redirect = builder.getRedirect();
-        PerfectHashBuilder.Entry<ImageLocationWriter>[] order = builder.getOrder();
-        locations = new ImageLocationWriter[length];
-
-        for (int i = 0; i < length; i++) {
-            locations[i] = order[i].getValue();
-        }
-    }
-
-    private void prepareStringBytes() {
-        strings.getStream().align(2);
-    }
-
-    private void prepareRedirectBytes() {
-        for (int i = 0; i < length; i++) {
-            redirectStream.putInt(redirect[i]);
-        }
-    }
-
-    private void prepareLocationBytes() {
-        // Reserve location offset zero for empty locations
-        locationStream.put(ImageLocationWriter.ATTRIBUTE_END << 3);
-
-        for (int i = 0; i < length; i++) {
-            ImageLocationWriter location = locations[i];
-
-            if (location != null) {
-                location.writeTo(locationStream);
-            }
-        }
-
-        locationStream.align(2);
-    }
-
-    private void prepareOffsetBytes() {
-        for (int i = 0; i < length; i++) {
-            ImageLocationWriter location = locations[i];
-            int offset = location != null ? location.getLocationOffset() : 0;
-            locationOffsetStream.putInt(offset);
-        }
-    }
-
-    private void prepareHeaderBytes() {
-        ImageHeader header = new ImageHeader(input.size(), length,
-                locationStream.getSize(), strings.getSize());
-        header.writeTo(headerStream);
-    }
-
-    private void prepareTableBytes() {
-        allIndexStream.put(headerStream);
-        allIndexStream.put(redirectStream);
-        allIndexStream.put(locationOffsetStream);
-        allIndexStream.put(locationStream);
-        allIndexStream.put(strings.getStream());
-    }
-
-    public byte[] getBytes() {
-        if (allIndexStream.getSize() == 0) {
-            generatePerfectHash();
-            prepareStringBytes();
-            prepareRedirectBytes();
-            prepareLocationBytes();
-            prepareOffsetBytes();
-            prepareHeaderBytes();
-            prepareTableBytes();
-        }
-
-        return allIndexStream.toArray();
-    }
-
-    ImageLocationWriter find(UTF8String key) {
-        int index = redirect[key.hashCode() % length];
-
-        if (index < 0) {
-            index = -index - 1;
-        } else {
-            index = key.hashCode(index) % length;
-        }
-
-        return locations[index];
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ExternalFilesWriter.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ExternalFilesWriter.java
deleted file mode 100644
index 2287043..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ExternalFilesWriter.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.nio.file.FileAlreadyExistsException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.function.Consumer;
-import jdk.internal.jimage.Archive.Entry;
-
-/**
- * A Consumer suitable for processing non resources Archive Entry and writing it to the
- * appropriate location.
- */
-class ExternalFilesWriter implements Consumer<Entry> {
-    private final Path root;
-
-    ExternalFilesWriter(Path root) {
-        this.root = root;
-    }
-
-    @Override
-    public void accept(Entry entry) {
-        String name = entry.path();
-        try {
-            String filename = entry.path();
-            try (InputStream in = entry.stream()) {
-                switch (entry.type()) {
-                    case NATIVE_LIB:
-                        writeEntry(in, destFile(nativeDir(filename), filename));
-                        break;
-                    case NATIVE_CMD:
-                        Path path = destFile("bin", filename);
-                        writeEntry(in, path);
-                        path.toFile().setExecutable(true, false);
-                        break;
-                    case CONFIG:
-                        writeEntry(in, destFile("conf", filename));
-                        break;
-                    case MODULE_NAME:
-                        // skip
-                        break;
-                    case SERVICE:
-                        //throw new UnsupportedOperationException(name + " in " + zipfile.toString()); //TODO
-                        throw new UnsupportedOperationException(name + " in " + name);
-                    default:
-                        //throw new InternalError("unexpected entry: " + name + " " + zipfile.toString()); //TODO
-                        throw new InternalError("unexpected entry: " + name + " " + name);
-                }
-            }
-        } catch (FileAlreadyExistsException x) {
-            System.err.println("File already exists (skipped) " + name);
-        } catch (IOException x) {
-            throw new UncheckedIOException(x);
-        }
-    }
-
-    private Path destFile(String dir, String filename) {
-        return root.resolve(dir).resolve(filename);
-    }
-
-    private void writeEntry(InputStream in, Path dstFile) throws IOException {
-        Files.createDirectories(dstFile.getParent());
-        Files.copy(in, dstFile);
-    }
-
-    private static String nativeDir(String filename) {
-        if (System.getProperty("os.name").startsWith("Windows")) {
-            if (filename.endsWith(".dll") || filename.endsWith(".diz")
-                || filename.endsWith(".pdb") || filename.endsWith(".map")) {
-                return "bin";
-            } else {
-                return "lib";
-            }
-        } else {
-            return "lib";
-        }
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageBufferCache.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageBufferCache.java
index 6929f74..c9efbe1 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageBufferCache.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageBufferCache.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
@@ -27,6 +27,13 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 class ImageBufferCache {
     private static final int MAX_FREE_BUFFERS = 3;
     private static final int LARGE_BUFFER = 0x10000;
@@ -37,7 +44,10 @@
     private boolean isUsed;
 
     static ByteBuffer getBuffer(long size) {
-        assert size < Integer.MAX_VALUE;
+        if (size < 0 || Integer.MAX_VALUE < size) {
+            throw new IndexOutOfBoundsException("size");
+        }
+
         ByteBuffer buffer = null;
 
         if (size > LARGE_BUFFER) {
@@ -84,7 +94,7 @@
     static void releaseBuffer(ByteBuffer buffer) {
         ArrayList<ImageBufferCache> buffers = threadLocal.get();
 
-        if (buffers == null ) {
+        if (buffers == null) {
             return;
         }
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java
deleted file mode 100644
index 78915e5..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageFileCreator.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import jdk.internal.jimage.Archive.Entry;
-import jdk.internal.jimage.Archive.Entry.EntryType;
-import static jdk.internal.jimage.BasicImageWriter.BOOT_NAME;
-import static jdk.internal.jimage.BasicImageWriter.IMAGE_EXT;
-
-/**
- * An image (native endian.)
- * <pre>{@code
- * {
- *   u4 magic;
- *   u2 major_version;
- *   u2 minor_version;
- *   u4 resource_count;
- *   u4 table_length;
- *   u4 location_attributes_size;
- *   u4 strings_size;
- *   u4 redirect[table_length];
- *   u4 offsets[table_length];
- *   u1 location_attributes[location_attributes_size];
- *   u1 strings[strings_size];
- *   u1 content[if !EOF];
- * }
- * }</pre>
- */
-public final class ImageFileCreator {
-    private final Path root;
-    private final Path mdir;
-    private final Map<String, List<Entry>> entriesForModule = new HashMap<>();
-    private ImageFileCreator(Path path) {
-        this.root = path;
-        this.mdir = root.resolve(path.getFileSystem().getPath("lib", "modules"));
-    }
-
-    public static ImageFileCreator create(Path output,
-            Set<Archive> archives)
-            throws IOException {
-        return create(output, BOOT_NAME, archives, ByteOrder.nativeOrder());
-    }
-
-    public static ImageFileCreator create(Path output,
-            Set<Archive> archives,
-            ByteOrder byteOrder)
-            throws IOException {
-        return create(output, BOOT_NAME, archives, byteOrder);
-    }
-
-    public static ImageFileCreator create(Path output,
-                                   String fileName,
-                                   Set<Archive> archives,
-                                   ByteOrder byteOrder)
-        throws IOException
-    {
-        ImageFileCreator image = new ImageFileCreator(output);
-        // get all entries
-        Map<String, Set<String>> modulePackagesMap = new HashMap<>();
-        image.readAllEntries(modulePackagesMap, archives);
-        // write to modular image
-        image.writeImage(fileName, modulePackagesMap, archives, byteOrder);
-        return image;
-    }
-
-    private void readAllEntries(Map<String, Set<String>> modulePackagesMap,
-                                  Set<Archive> archives) {
-        archives.stream().forEach((archive) -> {
-            Map<Boolean, List<Entry>> es;
-            try(Stream<Entry> entries = archive.entries()) {
-                es = entries.collect(Collectors.partitioningBy(n -> n.type()
-                        == EntryType.CLASS_OR_RESOURCE));
-            }
-            String mn = archive.moduleName();
-            List<Entry> all = new ArrayList<>();
-            all.addAll(es.get(false));
-            all.addAll(es.get(true));
-            entriesForModule.put(mn, all);
-            // Extract package names
-            Set<String> pkgs = es.get(true).stream().map(Entry::name)
-                    .filter(n -> isClassPackage(n))
-                    .map(ImageFileCreator::toPackage)
-                    .collect(Collectors.toSet());
-            modulePackagesMap.put(mn, pkgs);
-        });
-    }
-
-    public static boolean isClassPackage(String path) {
-        return path.endsWith(".class");
-    }
-
-    public static boolean isResourcePackage(String path) {
-        path = path.substring(1);
-        path = path.substring(path.indexOf("/")+1);
-        return !path.startsWith("META-INF/");
-    }
-
-    public static void recreateJimage(Path jimageFile,
-            String jdataName,
-            Set<Archive> archives,
-            Map<String, Set<String>> modulePackages)
-            throws IOException {
-        Map<String, List<Entry>> entriesForModule
-                = archives.stream().collect(Collectors.toMap(
-                                Archive::moduleName,
-                                a -> {
-                                    try(Stream<Entry> entries = a.entries()) {
-                                        return entries.collect(Collectors.toList());
-                                    }
-                                }));
-        Map<String, Archive> nameToArchive
-                = archives.stream()
-                .collect(Collectors.toMap(Archive::moduleName, Function.identity()));
-        ByteOrder order = ByteOrder.nativeOrder();
-        ResourcePoolImpl resources = createResources(modulePackages, nameToArchive,
-                (Entry t) -> {
-            throw new UnsupportedOperationException("Not supported, no external file "
-                    + "in a jimage file");
-        }, entriesForModule, order);
-        generateJImage(jimageFile, jdataName, resources, order);
-    }
-
-    private void writeImage(String fileName,
-            Map<String, Set<String>> modulePackagesMap,
-            Set<Archive> archives,
-            ByteOrder byteOrder)
-            throws IOException {
-        Files.createDirectories(mdir);
-        ExternalFilesWriter filesWriter = new ExternalFilesWriter(root);
-        // name to Archive file
-        Map<String, Archive> nameToArchive
-                = archives.stream()
-                .collect(Collectors.toMap(Archive::moduleName, Function.identity()));
-        ResourcePoolImpl resources = createResources(modulePackagesMap,
-                nameToArchive, filesWriter,
-                entriesForModule, byteOrder);
-        generateJImage(mdir.resolve(fileName + IMAGE_EXT), fileName, resources,
-                byteOrder);
-    }
-
-    private static void generateJImage(Path img,
-            String fileName,
-            ResourcePoolImpl resources,
-            ByteOrder byteOrder
-    ) throws IOException {
-        BasicImageWriter writer = new BasicImageWriter(byteOrder);
-
-        Map<String, Set<String>> modulePackagesMap = resources.getModulePackages();
-
-        try (OutputStream fos = Files.newOutputStream(img);
-                BufferedOutputStream bos = new BufferedOutputStream(fos);
-                DataOutputStream out = new DataOutputStream(bos)) {
-            Set<String> duplicates = new HashSet<>();
-            ImageModuleDataWriter moduleData =
-            ImageModuleDataWriter.buildModuleData(writer, modulePackagesMap);
-            moduleData.addLocation(fileName, writer);
-            long offset = moduleData.size();
-
-            List<ResourcePool.Resource> content = new ArrayList<>();
-            List<String> paths = new ArrayList<>();
-                 // the order of traversing the resources and the order of
-            // the module content being written must be the same
-            for (ResourcePool.Resource res : resources.getResources()) {
-                String path = res.getPath();
-                int index = path.indexOf("/META-INF/");
-                if (index != -1) {
-                    path = path.substring(index + 1);
-                }
-
-                content.add(res);
-                long uncompressedSize = res.getLength();
-                long compressedSize = 0;
-                if (res instanceof ResourcePool.CompressedResource) {
-                    ResourcePool.CompressedResource comp =
-                            (ResourcePool.CompressedResource) res;
-                    compressedSize = res.getLength();
-                    uncompressedSize = comp.getUncompressedSize();
-                }
-                long onFileSize = res.getLength();
-
-                if (duplicates.contains(path)) {
-                    System.err.format("duplicate resource \"%s\", skipping%n",
-                            path);
-                     // TODO Need to hang bytes on resource and write
-                    // from resource not zip.
-                    // Skipping resource throws off writing from zip.
-                    offset += onFileSize;
-                    continue;
-                }
-                duplicates.add(path);
-                writer.addLocation(path, offset, compressedSize, uncompressedSize);
-                paths.add(path);
-                offset += onFileSize;
-            }
-
-            ImageResourcesTree tree = new ImageResourcesTree(offset, writer, paths);
-
-            // write header and indices
-            byte[] bytes = writer.getBytes();
-            out.write(bytes, 0, bytes.length);
-
-            // write module meta data
-            moduleData.writeTo(out);
-
-            // write module content
-            for(ResourcePool.Resource res : content) {
-                byte[] buf = res.getByteArray();
-                out.write(buf, 0, buf.length);
-            }
-
-            tree.addContent(out);
-        }
-    }
-
-    private static ResourcePoolImpl createResources(Map<String, Set<String>> modulePackagesMap,
-            Map<String, Archive> nameToArchive,
-            Consumer<Entry> externalFileHandler,
-            Map<String, List<Entry>> entriesForModule,
-            ByteOrder byteOrder) throws IOException {
-        ResourcePoolImpl resources = new ResourcePoolImpl(byteOrder);
-        // Doesn't contain META-INF
-        Set<String> mods = modulePackagesMap.keySet();
-        for (String mn : mods) {
-            for (Entry entry : entriesForModule.get(mn)) {
-                String path = entry.name();
-                if (entry.type() == EntryType.CLASS_OR_RESOURCE) {
-                    if (!entry.path().endsWith(BOOT_NAME)) {
-                        try (InputStream stream = entry.stream()) {
-                            byte[] bytes = readAllBytes(stream);
-                            path = "/" + mn + "/" + path;
-                            try {
-                                resources.addResource(new ResourcePool.Resource(path,
-                                        ByteBuffer.wrap(bytes)));
-                            } catch (Exception ex) {
-                                throw new IOException(ex);
-                            }
-                        }
-                    }
-                } else {
-                    externalFileHandler.accept(entry);
-                }
-            }
-            // Done with this archive, close it.
-            Archive archive = nameToArchive.get(mn);
-            archive.close();
-        }
-        // Fix for 8136365. Do we have an archive with module name "META-INF"?
-        // If yes, we are recreating a jimage.
-        // This is a workaround for META-INF being at the top level of resource path
-        String mn = "META-INF";
-        Archive archive = nameToArchive.get(mn);
-        if (archive != null) {
-            try {
-                for (Entry entry : entriesForModule.get(mn)) {
-                    String path = entry.name();
-                    try (InputStream stream = entry.stream()) {
-                        byte[] bytes = readAllBytes(stream);
-                        path = mn + "/" + path;
-                        try {
-                            resources.addResource(new ResourcePool.Resource(path,
-                                    ByteBuffer.wrap(bytes)));
-                        } catch (Exception ex) {
-                            throw new IOException(ex);
-                        }
-                    }
-                }
-            } finally {
-                // Done with this archive, close it.
-                archive.close();
-            }
-        }
-        return resources;
-    }
-
-    private static final int BUF_SIZE = 8192;
-
-    private static byte[] readAllBytes(InputStream is) throws IOException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] buf = new byte[BUF_SIZE];
-        while (true) {
-            int n = is.read(buf);
-            if (n < 0) {
-                break;
-            }
-            baos.write(buf, 0, n);
-        }
-        return baos.toByteArray();
-    }
-
-    /**
-     * Helper method that splits a Resource path onto 3 items: module, parent
-     * and resource name.
-     *
-     * @param path
-     * @return An array containing module, parent and name.
-     */
-    public static String[] splitPath(String path) {
-        Objects.requireNonNull(path);
-        String noRoot = path.substring(1);
-        int pkgStart = noRoot.indexOf("/");
-        String module = noRoot.substring(0, pkgStart);
-        List<String> result = new ArrayList<>();
-        result.add(module);
-        String pkg = noRoot.substring(pkgStart + 1);
-        String resName;
-        int pkgEnd = pkg.lastIndexOf("/");
-        if (pkgEnd == -1) { // No package.
-            resName = pkg;
-        } else {
-            resName = pkg.substring(pkgEnd + 1);
-        }
-
-        pkg = toPackage(pkg, false);
-        result.add(pkg);
-        result.add(resName);
-
-        String[] array = new String[result.size()];
-        return result.toArray(array);
-    }
-
-    private static String toPackage(String name) {
-        String pkg = toPackage(name, true);
-        return pkg;
-    }
-
-    private static String toPackage(String name, boolean log) {
-        int index = name.lastIndexOf('/');
-        if (index > 0) {
-            return name.substring(0, index).replace('/', '.');
-        } else {
-            // ## unnamed package
-            if (log) {
-                System.err.format("Warning: %s in unnamed package%n", name);
-            }
-            return "";
-        }
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
index f55ef34..094f8dd 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.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,11 +28,18 @@
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 public final class ImageHeader {
     public static final int MAGIC = 0xCAFEDADA;
-    public static final int BADMAGIC = 0xDADAFECA;
     public static final int MAJOR_VERSION = 1;
     public static final int MINOR_VERSION = 0;
+    private static final int HEADER_SLOTS = 7;
 
     private final int magic;
     private final int majorVersion;
@@ -64,10 +71,14 @@
     }
 
     public static int getHeaderSize() {
-       return 7 * 4;
+       return HEADER_SLOTS * 4;
     }
 
     static ImageHeader readFrom(IntBuffer buffer) {
+        if (buffer.capacity() != HEADER_SLOTS) {
+            throw new InternalError("jimage header not the correct size");
+        }
+
         int magic = buffer.get(0);
         int version = buffer.get(1);
         int majorVersion = version >>> 16;
@@ -82,7 +93,7 @@
             resourceCount, tableLength, locationsSize, stringsSize);
     }
 
-    void writeTo(ImageStream stream) {
+    public void writeTo(ImageStream stream) {
         stream.ensure(getHeaderSize());
         writeTo(stream.getBuffer());
     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageJavaSubstrate.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageJavaSubstrate.java
deleted file mode 100644
index 96a7f23..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageJavaSubstrate.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Paths;
-import static java.nio.file.StandardOpenOption.READ;
-import jdk.internal.jimage.decompressor.Decompressor;
-
-final class ImageJavaSubstrate implements ImageSubstrate {
-
-    private final String imagePath;
-    private final ByteOrder byteOrder;
-    private final FileChannel channel;
-    private final ImageHeader header;
-    private final long indexSize;
-    private final int[] redirect;
-    private final int[] offsets;
-    private final byte[] locations;
-    private final byte[] strings;
-
-    private final Decompressor decompressor = new Decompressor();
-
-  private ImageJavaSubstrate(String imagePath, ByteOrder byteOrder)
-          throws IOException {
-        this.imagePath = imagePath;
-        this.byteOrder = byteOrder;
-        channel = FileChannel.open(Paths.get(imagePath), READ);
-
-        int headerSize = ImageHeader.getHeaderSize();
-        ByteBuffer buffer = getIndexBuffer(0, headerSize);
-        header = ImageHeader.readFrom(buffer.asIntBuffer());
-
-        if (header.getMagic() != ImageHeader.MAGIC ||
-            header.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
-            header.getMinorVersion() != ImageHeader.MINOR_VERSION) {
-            throw new IOException("Image not found \"" + imagePath + "\"");
-        }
-
-        indexSize = header.getIndexSize();
-
-        redirect = readIntegers(header.getRedirectOffset(),
-                                header.getRedirectSize());
-        offsets = readIntegers(header.getOffsetsOffset(),
-                               header.getOffsetsSize());
-        locations = readBytes(header.getLocationsOffset(),
-                              header.getLocationsSize());
-        strings = readBytes(header.getStringsOffset(),
-                            header.getStringsSize());
-    }
-
-    static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        return new ImageJavaSubstrate(imagePath, byteOrder);
-    }
-
-    @Override
-    public void close() {
-        try {
-            channel.close();
-        } catch (IOException ex) {
-            // Mostly harmless
-        }
-    }
-
-    @Override
-    public boolean supportsDataBuffer() {
-        return false;
-    }
-
-    private int[] readIntegers(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        IntBuffer buffer = readBuffer(offset, size).asIntBuffer();
-        int[] integers = new int[(int)size / 4];
-        buffer.get(integers);
-
-        return integers;
-    }
-
-    private byte[] readBytes(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        ByteBuffer buffer = readBuffer(offset, size);
-        byte[] bytes = new byte[(int)size];
-        buffer.get(bytes);
-
-        return bytes;
-    }
-
-    private ByteBuffer readBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        ByteBuffer buffer = ByteBuffer.allocate((int)size);
-        buffer.order(byteOrder);
-
-        if (!readBuffer(buffer, offset, size)) {
-            return null;
-        }
-
-        return buffer;
-    }
-
-    private boolean readBuffer(ByteBuffer buffer, long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        assert buffer.limit() == size;
-        int read = 0;
-
-        try {
-            read = channel.read(buffer, offset);
-            buffer.rewind();
-        } catch (IOException ex) {
-            // fall thru
-        }
-
-        return read == size;
-    }
-
-    @Override
-    public ByteBuffer getIndexBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        return readBuffer(offset, size);
-    }
-
-    @Override
-    public ByteBuffer getDataBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        return getIndexBuffer(indexSize + offset, size);
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer compressedBuffer, long compressedSize,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        assert compressedSize < Integer.MAX_VALUE;
-        assert uncompressedSize < Integer.MAX_VALUE;
-        boolean isRead = readBuffer(compressedBuffer,
-                                    indexSize + offset, compressedSize);
-        if (isRead) {
-            byte[] bytesIn = new byte[(int)compressedSize];
-            compressedBuffer.get(bytesIn);
-            byte[] bytesOut;
-            try {
-                bytesOut = decompressor.decompressResource(byteOrder, (int strOffset) -> {
-                    return new UTF8String(getStringBytes(strOffset)).toString();
-                }, bytesIn);
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            }
-            uncompressedBuffer.put(bytesOut);
-            uncompressedBuffer.rewind();
-        }
-
-        return isRead;
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        assert uncompressedSize < Integer.MAX_VALUE;
-        boolean isRead = readBuffer(uncompressedBuffer,
-                                    indexSize + offset, uncompressedSize);
-
-        return isRead;
-    }
-
-    @Override
-    public byte[] getStringBytes(int offset) {
-        if (offset == 0) {
-            return new byte[0];
-        }
-
-        int length = strings.length - offset;
-
-        for (int i = offset; i < strings.length; i++) {
-            if (strings[i] == 0) {
-                length = i - offset;
-                break;
-            }
-        }
-
-        byte[] bytes = new byte[length];
-        System.arraycopy(strings, offset, bytes, 0, length);
-
-        return bytes;
-    }
-
-    @Override
-    public long[] getAttributes(int offset) {
-        return ImageLocationBase.decompress(locations, offset);
-    }
-
-    @Override
-    public ImageLocation findLocation(UTF8String name, ImageStringsReader strings) {
-        int count = header.getTableLength();
-        int index = redirect[name.hashCode() % count];
-
-        if (index < 0) {
-            index = -index - 1;
-        } else {
-            index = name.hashCode(index) % count;
-        }
-
-        long[] attributes = getAttributes(offsets[index]);
-
-        ImageLocation imageLocation = new ImageLocation(attributes, strings);
-
-        if (!imageLocation.verify(name)) {
-            return null;
-        }
-
-        return imageLocation;
-   }
-
-    @Override
-    public int[] attributeOffsets() {
-        return offsets;
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
index 148debd..a8147d2 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.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
@@ -25,9 +25,228 @@
 
 package jdk.internal.jimage;
 
-public final class ImageLocation  extends ImageLocationBase {
-    ImageLocation(long[] attributes, ImageStringsReader strings) {
-        super(attributes, strings);
+import java.nio.ByteBuffer;
+
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class ImageLocation {
+    public static final int ATTRIBUTE_END = 0;
+    public static final int ATTRIBUTE_MODULE = 1;
+    public static final int ATTRIBUTE_PARENT = 2;
+    public static final int ATTRIBUTE_BASE = 3;
+    public static final int ATTRIBUTE_EXTENSION = 4;
+    public static final int ATTRIBUTE_OFFSET = 5;
+    public static final int ATTRIBUTE_COMPRESSED = 6;
+    public static final int ATTRIBUTE_UNCOMPRESSED = 7;
+    public static final int ATTRIBUTE_COUNT = 8;
+
+    protected final long[] attributes;
+
+    protected final ImageStrings strings;
+
+    public ImageLocation(long[] attributes, ImageStrings strings) {
+        this.attributes = attributes;
+        this.strings = strings;
+    }
+
+    ImageStrings getStrings() {
+        return strings;
+    }
+
+    private static int attributeLength(int data) {
+        return (data & 0x7) + 1;
+    }
+
+    private static int attributeKind(int data) {
+        return data >>> 3;
+    }
+
+    static long[] decompress(ByteBuffer bytes) {
+        long[] attributes = new long[ATTRIBUTE_COUNT];
+
+        if (bytes != null) {
+            while (bytes.hasRemaining()) {
+                int data = bytes.get() & 0xFF;
+                int kind = attributeKind(data);
+
+                if (kind == ATTRIBUTE_END) {
+                    break;
+                }
+
+                if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
+                    throw new InternalError("Invalid jimage attribute kind");
+                }
+
+                int length = attributeLength(data);
+                long value = 0;
+
+                for (int j = 0; j < length; j++) {
+                    value <<= 8;
+
+                    if (!bytes.hasRemaining()) {
+                        throw new InternalError("\"Missing jimage attribute datad");
+                    }
+
+                    value |= bytes.get() & 0xFF;
+                }
+
+                 attributes[kind] = value;
+            }
+        }
+
+        return attributes;
+    }
+
+    public static byte[] compress(long[] attributes) {
+        ImageStream stream = new ImageStream(16);
+
+        for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) {
+            long value = attributes[kind];
+
+            if (value != 0) {
+                int n = (63 - Long.numberOfLeadingZeros(value)) >> 3;
+                stream.put((kind << 3) | n);
+
+                for (int i = n; i >= 0; i--) {
+                    stream.put((int)(value >> (i << 3)));
+                }
+            }
+        }
+
+        stream.put(ATTRIBUTE_END << 3);
+
+        return stream.toArray();
+     }
+
+    public boolean verify(String name) {
+        return name.equals(getFullName());
+    }
+
+    long getAttribute(int kind) {
+        if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
+            throw new InternalError("Invalid jimage attribute kind");
+        }
+
+        return attributes[kind];
+    }
+
+    String getAttributeString(int kind) {
+        if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
+            throw new InternalError("Invalid jimage attribute kind");
+        }
+
+        return getStrings().get((int)attributes[kind]);
+    }
+
+    public String getModule() {
+        return getAttributeString(ATTRIBUTE_MODULE);
+    }
+
+    public int getModuleOffset() {
+        return (int)getAttribute(ATTRIBUTE_MODULE);
+    }
+
+    public String getBase() {
+        return getAttributeString(ATTRIBUTE_BASE);
+    }
+
+    public int getBaseOffset() {
+        return (int)getAttribute(ATTRIBUTE_BASE);
+    }
+
+    public String getParent() {
+        return getAttributeString(ATTRIBUTE_PARENT);
+    }
+
+    public int getParentOffset() {
+        return (int)getAttribute(ATTRIBUTE_PARENT);
+    }
+
+    public String getExtension() {
+        return getAttributeString(ATTRIBUTE_EXTENSION);
+    }
+
+    public int getExtensionOffset() {
+        return (int)getAttribute(ATTRIBUTE_EXTENSION);
+    }
+
+    public String getFullName() {
+        return getFullName(false);
+    }
+
+    public String getFullName(boolean modulesPrefix) {
+        StringBuilder builder = new StringBuilder();
+
+        if (getModuleOffset() != 0) {
+            if (modulesPrefix) {
+                builder.append("/modules");
+            }
+
+            builder.append('/');
+            builder.append(getModule());
+            builder.append('/');
+        }
+
+        if (getParentOffset() != 0) {
+            builder.append(getParent());
+            builder.append('/');
+        }
+
+        builder.append(getBase());
+
+        if (getExtensionOffset() != 0) {
+            builder.append('.');
+            builder.append(getExtension());
+        }
+
+        return builder.toString();
+    }
+
+    String buildName(boolean includeModule, boolean includeParent,
+            boolean includeName) {
+        StringBuilder builder = new StringBuilder();
+
+        if (includeModule && getModuleOffset() != 0) {
+            builder.append("/modules/");
+            builder.append(getModule());
+         }
+
+        if (includeParent && getParentOffset() != 0) {
+            builder.append('/');
+            builder.append(getParent());
+        }
+
+        if (includeName) {
+            if (includeModule || includeParent) {
+                builder.append('/');
+            }
+
+            builder.append(getBase());
+
+            if (getExtensionOffset() != 0) {
+                builder.append('.');
+                builder.append(getExtension());
+            }
+        }
+
+        return builder.toString();
+   }
+
+    public long getContentOffset() {
+        return getAttribute(ATTRIBUTE_OFFSET);
+    }
+
+    public long getCompressedSize() {
+        return getAttribute(ATTRIBUTE_COMPRESSED);
+    }
+
+    public long getUncompressedSize() {
+        return getAttribute(ATTRIBUTE_UNCOMPRESSED);
     }
 
     static ImageLocation readFrom(BasicImageReader reader, int offset) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java
deleted file mode 100644
index 461db37..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-public class ImageLocationBase {
-    static final int ATTRIBUTE_END = 0;
-    static final int ATTRIBUTE_MODULE = 1;
-    static final int ATTRIBUTE_PARENT = 2;
-    static final int ATTRIBUTE_BASE = 3;
-    static final int ATTRIBUTE_EXTENSION = 4;
-    static final int ATTRIBUTE_OFFSET = 5;
-    static final int ATTRIBUTE_COMPRESSED = 6;
-    static final int ATTRIBUTE_UNCOMPRESSED = 7;
-    static final int ATTRIBUTE_COUNT = 8;
-
-    protected final long[] attributes;
-
-    protected final ImageStrings strings;
-
-    protected ImageLocationBase(long[] attributes, ImageStrings strings) {
-        this.attributes = attributes;
-        this.strings = strings;
-    }
-
-    ImageStrings getStrings() {
-        return strings;
-    }
-
-    private static int attributeLength(int data) {
-        return (data & 0x7) + 1;
-    }
-
-    private static int attributeKind(int data) {
-        return data >>> 3;
-    }
-
-    static long[] decompress(byte[] bytes) {
-        return decompress(bytes, 0);
-    }
-
-    static long[] decompress(byte[] bytes, int offset) {
-        long[] attributes = new long[ATTRIBUTE_COUNT];
-
-        if (bytes != null) {
-            for (int i = offset; i < bytes.length; ) {
-                int data = bytes[i++] & 0xFF;
-                int kind = attributeKind(data);
-
-                if (kind == ATTRIBUTE_END) {
-                    break;
-                }
-
-                assert ATTRIBUTE_END < kind &&
-                       kind < ATTRIBUTE_COUNT : "Invalid attribute kind";
-                int length = attributeLength(data);
-                long value = 0;
-
-                for (int j = 0; j < length; j++) {
-                    value <<= 8;
-                    value |= bytes[i++] & 0xFF;
-                }
-
-                 attributes[kind] = value;
-            }
-        }
-
-        return attributes;
-    }
-
-    static byte[] compress(long[] attributes) {
-        ImageStream stream = new ImageStream(16);
-
-        for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) {
-            long value = attributes[kind];
-
-            if (value != 0) {
-                int n = (63 - Long.numberOfLeadingZeros(value)) >> 3;
-                stream.put((kind << 3) | n);
-
-                for (int i = n; i >= 0; i--) {
-                    stream.put((int)(value >> (i << 3)));
-                }
-            }
-        }
-
-        stream.put(ATTRIBUTE_END << 3);
-
-        return stream.toArray();
-     }
-
-    public boolean verify(UTF8String name) {
-        return UTF8String.equals(getFullName(), name);
-    }
-
-    protected long getAttribute(int kind) {
-        assert ATTRIBUTE_END < kind &&
-               kind < ATTRIBUTE_COUNT : "Invalid attribute kind";
-
-        return attributes[kind];
-    }
-
-    protected UTF8String getAttributeUTF8String(int kind) {
-        assert ATTRIBUTE_END < kind &&
-               kind < ATTRIBUTE_COUNT : "Invalid attribute kind";
-
-        return getStrings().get((int)attributes[kind]);
-    }
-
-    protected String getAttributeString(int kind) {
-        return getAttributeUTF8String(kind).toString();
-    }
-
-    UTF8String getModule() {
-        return getAttributeUTF8String(ATTRIBUTE_MODULE);
-    }
-
-    public String getModuleString() {
-        return getModule().toString();
-    }
-
-    int getModuleOffset() {
-        return (int)getAttribute(ATTRIBUTE_MODULE);
-    }
-
-    UTF8String getBase() {
-        return getAttributeUTF8String(ATTRIBUTE_BASE);
-    }
-
-    public String getBaseString() {
-        return  getBase().toString();
-    }
-
-    int getBaseOffset() {
-        return (int)getAttribute(ATTRIBUTE_BASE);
-    }
-
-    UTF8String getParent() {
-        return getAttributeUTF8String(ATTRIBUTE_PARENT);
-    }
-
-    public String getParentString() {
-        return getParent().toString();
-    }
-
-    int getParentOffset() {
-        return (int)getAttribute(ATTRIBUTE_PARENT);
-    }
-
-    UTF8String getExtension() {
-        return getAttributeUTF8String(ATTRIBUTE_EXTENSION);
-    }
-
-    public String getExtensionString() {
-        return getExtension().toString();
-    }
-
-    int getExtensionOffset() {
-        return (int)getAttribute(ATTRIBUTE_EXTENSION);
-    }
-
-    UTF8String getFullName() {
-        return getFullName(false);
-    }
-
-    UTF8String getFullName(boolean modulesPrefix) {
-        // Note: Consider a UTF8StringBuilder.
-        UTF8String fullName = UTF8String.EMPTY_STRING;
-
-        if (getModuleOffset() != 0) {
-            fullName = fullName.concat(
-                // TODO The use of UTF8String.MODULES_STRING does not belong here.
-                modulesPrefix? UTF8String.MODULES_STRING :
-                               UTF8String.EMPTY_STRING,
-                UTF8String.SLASH_STRING,
-                getModule(),
-                UTF8String.SLASH_STRING);
-        }
-
-        if (getParentOffset() != 0) {
-            fullName = fullName.concat(getParent(),
-                                       UTF8String.SLASH_STRING);
-        }
-
-        fullName = fullName.concat(getBase());
-
-        if (getExtensionOffset() != 0) {
-                fullName = fullName.concat(UTF8String.DOT_STRING,
-                                           getExtension());
-        }
-
-        return fullName;
-    }
-
-    UTF8String buildName(boolean includeModule, boolean includeParent,
-            boolean includeName) {
-        // Note: Consider a UTF8StringBuilder.
-        UTF8String name = UTF8String.EMPTY_STRING;
-
-        if (includeModule && getModuleOffset() != 0) {
-            name = name.concat(UTF8String.MODULES_STRING,
-                               UTF8String.SLASH_STRING,
-                               getModule());
-        }
-
-        if (includeParent && getParentOffset() != 0) {
-            name = name.concat(UTF8String.SLASH_STRING,
-                                       getParent());
-        }
-
-        if (includeName) {
-            if (includeModule || includeParent) {
-                name = name.concat(UTF8String.SLASH_STRING);
-            }
-
-            name = name.concat(getBase());
-
-            if (getExtensionOffset() != 0) {
-                name = name.concat(UTF8String.DOT_STRING,
-                                           getExtension());
-            }
-        }
-
-        return name;
-    }
-
-    String getFullNameString() {
-        return getFullName().toString();
-    }
-
-    public long getContentOffset() {
-        return getAttribute(ATTRIBUTE_OFFSET);
-    }
-
-    public long getCompressedSize() {
-        return getAttribute(ATTRIBUTE_COMPRESSED);
-    }
-
-    public long getUncompressedSize() {
-        return getAttribute(ATTRIBUTE_UNCOMPRESSED);
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationWriter.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationWriter.java
deleted file mode 100644
index de7625b..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocationWriter.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-public final class ImageLocationWriter extends ImageLocationBase {
-    private int locationOffset;
-
-    private ImageLocationWriter(ImageStringsWriter strings) {
-        super(new long[ATTRIBUTE_COUNT], strings);
-    }
-
-    void writeTo(ImageStream stream) {
-        byte[] bytes = ImageLocation.compress(attributes);
-        locationOffset = stream.getPosition();
-        stream.put(bytes, 0, bytes.length);
-    }
-
-    private ImageLocationWriter addAttribute(int kind, long value) {
-        assert ATTRIBUTE_END < kind &&
-               kind < ATTRIBUTE_COUNT : "Invalid attribute kind";
-        attributes[kind] = value;
-        return this;
-    }
-
-    private ImageLocationWriter addAttribute(int kind, UTF8String value) {
-        return addAttribute(kind, strings.add(value));
-    }
-
-    static ImageLocationWriter newLocation(UTF8String fullName,
-            ImageStringsWriter strings,
-            long contentOffset, long compressedSize, long uncompressedSize) {
-        UTF8String moduleName = UTF8String.EMPTY_STRING;
-        UTF8String parentName = UTF8String.EMPTY_STRING;
-        UTF8String baseName;
-        UTF8String extensionName = UTF8String.EMPTY_STRING;
-
-        int offset = fullName.indexOf('/', 1);
-        if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) {
-            moduleName = fullName.substring(1, offset - 1);
-            fullName = fullName.substring(offset + 1);
-        }
-
-        offset = fullName.lastIndexOf('/');
-        if (offset != -1) {
-            parentName = fullName.substring(0, offset);
-            fullName = fullName.substring(offset + 1);
-        }
-
-        offset = fullName.lastIndexOf('.');
-        if (offset != -1) {
-            baseName = fullName.substring(0, offset);
-            extensionName = fullName.substring(offset + 1);
-        } else {
-            baseName = fullName;
-        }
-
-        return new ImageLocationWriter(strings)
-               .addAttribute(ATTRIBUTE_MODULE, moduleName)
-               .addAttribute(ATTRIBUTE_PARENT, parentName)
-               .addAttribute(ATTRIBUTE_BASE, baseName)
-               .addAttribute(ATTRIBUTE_EXTENSION, extensionName)
-               .addAttribute(ATTRIBUTE_OFFSET, contentOffset)
-               .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize)
-               .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize);
-    }
-
-    @Override
-    public int hashCode() {
-        return hashCode(UTF8String.HASH_MULTIPLIER);
-    }
-
-    int hashCode(int seed) {
-        int hash = seed;
-
-        if (getModuleOffset() != 0) {
-            hash = UTF8String.SLASH_STRING.hashCode(hash);
-            hash = getModule().hashCode(hash);
-            hash = UTF8String.SLASH_STRING.hashCode(hash);
-        }
-
-        if (getParentOffset() != 0) {
-            hash = getParent().hashCode(hash);
-            hash = UTF8String.SLASH_STRING.hashCode(hash);
-        }
-
-        hash = getBase().hashCode(hash);
-
-        if (getExtensionOffset() != 0) {
-            hash = UTF8String.DOT_STRING.hashCode(hash);
-            hash = getExtension().hashCode(hash);
-        }
-
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (!(obj instanceof ImageLocationWriter)) {
-            return false;
-        }
-
-        ImageLocation other = (ImageLocation)obj;
-
-        return getModuleOffset() == other.getModuleOffset() &&
-               getParentOffset() == other.getParentOffset() &&
-               getBaseOffset() == other.getBaseOffset() &&
-               getExtensionOffset() == other.getExtensionOffset();
-    }
-
-    int getLocationOffset() {
-        return locationOffset;
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleData.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleData.java
deleted file mode 100644
index c15ce73..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleData.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-
-/*
- * Manage module meta data.
- *
- * NOTE: needs revision.
- * Each loader requires set of module meta data to identify which modules and
- * packages are managed by that loader.  Currently, there is one image file per
- * loader, so only one  module meta data resource per file.
- *
- * Each element in the module meta data is a native endian 4 byte integer.  Note
- * that entries with zero offsets for string table entries should be ignored (
- * padding for hash table lookup.)
- *
- * Format:
- *    Count of package to module entries
- *    Count of module to package entries
- *    Perfect Hash redirect table[Count of package to module entries]
- *    Package to module entries[Count of package to module entries]
- *        Offset to package name in string table
- *        Offset to module name in string table
- *    Perfect Hash redirect table[Count of module to package entries]
- *    Module to package entries[Count of module to package entries]
- *        Offset to module name in string table
- *        Count of packages in module
- *        Offset to first package in packages table
- *    Packages[]
- *        Offset to package name in string table
- */
-
-public final class ImageModuleData {
-    public static final String META_DATA_EXTENSION = ".jdata";
-    public static final String SEPARATOR = "\t";
-    public static final int NOT_FOUND = -1;
-    private static final int ptmCountOffset = 0;
-    private static final int mtpCountOffset = 1;
-    private static final int ptmRedirectOffset = 2;
-    private static final int dataNameOffset = 0;
-    private static final int ptmDataWidth = 2;
-    private static final int ptmDataModuleOffset = 1;
-    private static final int mtpDataWidth = 3;
-    private static final int mtpDataCountOffset = 1;
-    private static final int mtpDataOffsetOffset = 2;
-
-    private final BasicImageReader reader;
-    private final IntBuffer intBuffer;
-    private final int ptmRedirectLength;
-    private final int mtpRedirectLength;
-    private final int ptmDataOffset;
-    private final int mtpRedirectOffset;
-    private final int mtpDataOffset;
-    private final int mtpPackagesOffset;
-
-    public ImageModuleData(BasicImageReader reader) {
-         this(reader, getBytes(reader));
-    }
-
-    public ImageModuleData(BasicImageReader reader, byte[] bytes) {
-        this.reader = reader;
-
-        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(reader.getByteOrder());
-        this.intBuffer = byteBuffer.asIntBuffer();
-
-        this.ptmRedirectLength = get(ptmCountOffset);
-        this.mtpRedirectLength = get(mtpCountOffset);
-
-        this.ptmDataOffset = ptmRedirectOffset + ptmRedirectLength;
-        this.mtpRedirectOffset = ptmDataOffset + ptmRedirectLength * ptmDataWidth;
-        this.mtpDataOffset = mtpRedirectOffset + mtpRedirectLength;
-        this.mtpPackagesOffset = mtpDataOffset + mtpRedirectLength * mtpDataWidth;
-    }
-
-    private static byte[] getBytes(BasicImageReader reader) {
-        String loaderName = reader.imagePathName();
-
-        if (loaderName.endsWith(BasicImageWriter.IMAGE_EXT)) {
-            loaderName = loaderName.substring(0, loaderName.length() -
-                    BasicImageWriter.IMAGE_EXT.length());
-        }
-
-        byte[] bytes = reader.getResource(getModuleDataName(loaderName));
-
-        if (bytes == null) {
-            throw new InternalError("module data missing");
-        }
-
-        return bytes;
-    }
-
-    public List<String> fromModulePackages() {
-        List<String> lines = new ArrayList<>();
-
-        for (int i = 0; i < mtpRedirectLength; i++) {
-            int index = mtpDataOffset + i * mtpDataWidth;
-            int offset = get(index + dataNameOffset);
-
-            if (offset != 0) {
-                StringBuilder sb = new StringBuilder();
-
-                sb.append(getString(offset));
-
-                int count = get(index + mtpDataCountOffset);
-                int base = get(index + mtpDataOffsetOffset) + mtpPackagesOffset;
-
-                for (int j = 0; j < count; j++) {
-                    sb.append(SEPARATOR);
-                    sb.append(stringAt(base + j));
-                }
-
-                lines.add(sb.toString());
-            }
-        }
-
-        return lines;
-    }
-
-    public static String getModuleDataName(String loaderName) {
-        return loaderName + META_DATA_EXTENSION;
-    }
-
-    private int get(int index) {
-        return intBuffer.get(index);
-    }
-
-    private String getString(int offset) {
-        return reader.getString(offset);
-    }
-
-    private String stringAt(int index) {
-        return reader.getString(get(index));
-    }
-
-    private UTF8String getUTF8String(int offset) {
-        return reader.getUTF8String(offset);
-    }
-
-    private UTF8String utf8StringAt(int index) {
-        return reader.getUTF8String(get(index));
-    }
-
-    private int find(UTF8String name, int baseOffset, int length, int width) {
-        if (length == 0) {
-            return NOT_FOUND;
-        }
-
-        int hashCode = name.hashCode();
-        int index = hashCode % length;
-        int value = get(baseOffset + index);
-
-        if (value > 0 ) {
-            hashCode = name.hashCode(value);
-            index = hashCode % length;
-        } else if (value < 0) {
-            index = -1 - value;
-        } else {
-            return NOT_FOUND;
-        }
-
-        index = baseOffset + length + index * width;
-
-        if (!utf8StringAt(index + dataNameOffset).equals(name)) {
-            return NOT_FOUND;
-        }
-
-        return index;
-    }
-
-    public String packageToModule(String packageName) {
-        UTF8String moduleName = packageToModule(new UTF8String(packageName));
-
-        return moduleName != null ? moduleName.toString() : null;
-    }
-
-    public UTF8String packageToModule(UTF8String packageName) {
-        int index = find(packageName, ptmRedirectOffset, ptmRedirectLength, ptmDataWidth);
-
-        if (index != NOT_FOUND) {
-            return utf8StringAt(index + ptmDataModuleOffset);
-        }
-
-        return null;
-    }
-
-    public List<String> moduleToPackages(String moduleName) {
-        int index = find(new UTF8String(moduleName), mtpRedirectOffset,
-                mtpRedirectLength, mtpDataWidth);
-
-        if (index != NOT_FOUND) {
-            int count = get(index + mtpDataCountOffset);
-            int base = get(index + mtpDataOffsetOffset) + mtpPackagesOffset;
-            List<String> packages = new ArrayList<>(count);
-
-            for (int i = 0; i < count; i++) {
-                packages.add(stringAt(base + i));
-            }
-
-            return packages;
-        }
-
-        return null;
-    }
-
-    public List<String> allPackageNames() {
-        List<String> packages = new ArrayList<>();
-
-        for (int i = 0; i < ptmRedirectLength; i++) {
-            int offset = get(ptmDataOffset + i * ptmDataWidth + dataNameOffset);
-
-            if (offset != 0) {
-                packages.add(getString(offset));
-            }
-        }
-
-        return packages;
-    }
-
-    public Set<String> allModuleNames() {
-        Set<String> modules = new HashSet<>();
-
-        for (int i = 0; i < mtpRedirectLength; i++) {
-            int index = mtpDataOffset + i * mtpDataWidth;
-            int offset = get(index + dataNameOffset);
-
-            if (offset != 0) {
-                modules.add(getString(offset));
-            }
-        }
-
-        return modules;
-    }
-
-    public Map<String, String> packageModuleMap() {
-        Map<String, String> map = new HashMap<>();
-
-        for (int i = 0; i < mtpRedirectLength; i++) {
-            int index = mtpDataOffset + i * mtpDataWidth;
-            int offset = get(index + dataNameOffset);
-
-            if (offset != 0) {
-                String moduleName = getString(offset);
-
-                int count = get(index + mtpDataCountOffset);
-                int base = get(index + mtpDataOffsetOffset) + mtpPackagesOffset;
-
-                for (int j = 0; j < count; j++) {
-                    map.put(stringAt(base + j), moduleName);
-                }
-            }
-        }
-
-        return map;
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleDataWriter.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleDataWriter.java
deleted file mode 100644
index 65c0de0..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageModuleDataWriter.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-public class ImageModuleDataWriter {
-    final byte[] bytes;
-
-    public ImageModuleDataWriter(BasicImageWriter writer,
-            Map<String, List<String>> modulePackages) {
-        PerfectHashBuilder<String> packageToModule = new PerfectHashBuilder<>(
-                new PerfectHashBuilder.Entry<String>().getClass(),
-                new PerfectHashBuilder.Bucket<String>().getClass());
-        PerfectHashBuilder<List<String>> moduleToPackages = new PerfectHashBuilder<>(
-                new PerfectHashBuilder.Entry<List<String>>().getClass(),
-                new PerfectHashBuilder.Bucket<List<String>>().getClass());
-
-        modulePackages.entrySet().stream().forEach((entry) -> {
-            String moduleName = entry.getKey();
-            List<String> packages = entry.getValue();
-            packages.stream().forEach((packageName) -> {
-                packageToModule.put(packageName, moduleName);
-            });
-
-            moduleToPackages.put(moduleName, packages);
-        });
-
-        packageToModule.generate();
-        moduleToPackages.generate();
-
-        bytes = getBytes(writer, packageToModule, moduleToPackages);
-    }
-
-    public static ImageModuleDataWriter buildModuleData(BasicImageWriter writer,
-            Map<String, Set<String>> modulePackagesMap) {
-        Set<String> modules = modulePackagesMap.keySet();
-
-        Map<String, List<String>> modulePackages = new LinkedHashMap<>();
-        modules.stream().sorted().forEach((moduleName) -> {
-            List<String> localPackages = modulePackagesMap.get(moduleName).stream()
-                    .map(pn -> pn.replace('.', '/'))
-                    .sorted()
-                    .collect(Collectors.toList());
-            modulePackages.put(moduleName, localPackages);
-        });
-
-        return new ImageModuleDataWriter(writer, modulePackages);
-    }
-
-    public static Map<String, List<String>> toModulePackages(List<String> lines) {
-        Map<String, List<String>> modulePackages = new LinkedHashMap<>();
-
-        for (String line : lines) {
-            String[] parts = line.split(ImageModuleData.SEPARATOR);
-            String moduleName = parts[0];
-            List<String> packages = Arrays.asList(Arrays.copyOfRange(parts, 1, parts.length));
-            modulePackages.put(moduleName, packages);
-        }
-
-        return modulePackages;
-    }
-
-    public void addLocation(String name, BasicImageWriter writer) {
-        writer.addLocation(ImageModuleData.getModuleDataName(name), 0, 0, bytes.length);
-    }
-
-    private byte[] getBytes(BasicImageWriter writer,
-            PerfectHashBuilder<String> packageToModule,
-            PerfectHashBuilder<List<String>> moduleToPackages) {
-        ImageStream stream = new ImageStream(writer.getByteOrder());
-
-        // Empty jimage
-        if (packageToModule.getCount() == 0) {
-            stream.putInt(0);
-            stream.putInt(0);
-            return stream.toArray();
-        }
-
-        int[] ptmRedirect = packageToModule.getRedirect();
-        int[] mtpRedirect = moduleToPackages.getRedirect();
-        PerfectHashBuilder.Entry<String>[] ptmOrder = packageToModule.getOrder();
-        PerfectHashBuilder.Entry<List<String>>[] mtpOrder = moduleToPackages.getOrder();
-
-        stream.putInt(ptmRedirect.length);
-        stream.putInt(mtpRedirect.length);
-
-        for (int value : ptmRedirect) {
-            stream.putInt(value);
-        }
-
-        for (PerfectHashBuilder.Entry<String> entry : ptmOrder) {
-            if (entry != null) {
-                stream.putInt(writer.addString(entry.getKey()));
-                stream.putInt(writer.addString(entry.getValue()));
-            } else {
-                stream.putInt(0);
-                stream.putInt(0);
-            }
-        }
-
-        for (int value : mtpRedirect) {
-            stream.putInt(value);
-        }
-
-        int index = 0;
-
-        for (PerfectHashBuilder.Entry<List<String>> entry : mtpOrder) {
-            if (entry != null) {
-                int count = entry.getValue().size();
-                stream.putInt(writer.addString(entry.getKey()));
-                stream.putInt(count);
-                stream.putInt(index);
-                index += count;
-            } else {
-                stream.putInt(0);
-                stream.putInt(0);
-                stream.putInt(0);
-            }
-        }
-
-        for (PerfectHashBuilder.Entry<List<String>> entry : mtpOrder) {
-            if (entry != null) {
-                List<String> value = entry.getValue();
-                value.stream().forEach((packageName) -> {
-                    stream.putInt(writer.addString(packageName));
-                });
-            }
-        }
-
-        return stream.toArray();
-    }
-
-    public void writeTo(DataOutputStream out) throws IOException {
-         out.write(bytes, 0, bytes.length);
-    }
-
-    public int size() {
-        return bytes.length;
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java
deleted file mode 100644
index a839595..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-public final class ImageNativeSubstrate implements ImageSubstrate {
-    static {
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                @Override
-                public Void run() {
-                    System.loadLibrary("jimage");
-                    return null;
-                }
-            });
-     }
-
-    // TODO: Reinstate when the class below, NIOACCESS, is removed.
-    //private static final JavaNioAccess NIOACCESS =
-    //        SharedSecrets.getJavaNioAccess();
-
-
-    private final long id;
-    private final long indexAddress;
-    private final long dataAddress;
-
-    static native long openImage(String imagePath, boolean bigEndian);
-    static native void closeImage(long id);
-    static native long getIndexAddress(long id);
-    static native long getDataAddress(long id);
-    static native boolean readCompressed(long id, long offset,
-            ByteBuffer compressedBuffer, long compressedSize,
-            ByteBuffer uncompressedBuffer, long uncompressedSize);
-    static native boolean read(long id, long offset,
-            ByteBuffer uncompressedBuffer, long uncompressedSize);
-    static native byte[] getStringBytes(long id, int offset);
-    static native long[] getAttributes(long id, int offset);
-    static native long[] findAttributes(long id, byte[] path);
-    static native int[] attributeOffsets(long id);
-
-    public static native long JIMAGE_Open(String path) throws IOException;
-    public static native void JIMAGE_Close(long jimageHandle);
-    public static native long JIMAGE_FindResource(long jimageHandle,
-                    String moduleName, String Version, String path,
-                    long[] size);
-    public static native long JIMAGE_GetResource(long jimageHandle,
-                    long locationHandle, byte[] buffer, long size);
-    // Get an array of names that match; return the count found upto array size
-    public static native int JIMAGE_Resources(long jimageHandle,
-                    String[] outputNames);
-    // Return the module name for the package
-    public static native String JIMAGE_PackageToModule(long imageHandle,
-                    String packageName);
-
-    static ByteBuffer newDirectByteBuffer(long address, long capacity) {
-        assert capacity < Integer.MAX_VALUE;
-        return NIOACCESS.newDirectByteBuffer(address, (int)capacity, null);
-    }
-
-    private ImageNativeSubstrate(long id) {
-        this.id = id;
-        this.indexAddress = getIndexAddress(id);
-        this.dataAddress = getDataAddress(id);
-    }
-
-    static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        long id = openImage(imagePath, byteOrder == ByteOrder.BIG_ENDIAN);
-
-        if (id == 0) {
-             throw new IOException("Image not found \"" + imagePath + "\"");
-        }
-
-        return new ImageNativeSubstrate(id);
-    }
-
-    @Override
-    public void close() {
-        closeImage(id);
-    }
-
-    @Override
-    public ByteBuffer getIndexBuffer(long offset, long size) {
-        return newDirectByteBuffer(indexAddress + offset, size);
-    }
-
-    @Override
-    public ByteBuffer getDataBuffer(long offset, long size) {
-        return dataAddress != 0 ?
-                newDirectByteBuffer(dataAddress + offset, size) : null;
-    }
-
-    @Override
-    public boolean supportsDataBuffer() {
-        return dataAddress != 0;
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer compressedBuffer, long compressedSize,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        return readCompressed(id, offset,
-                    compressedBuffer, compressedSize,
-                    uncompressedBuffer, uncompressedSize);
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        return read(id, offset, uncompressedBuffer, uncompressedSize);
-    }
-
-    @Override
-    public byte[] getStringBytes(int offset) {
-        byte[] ret = getStringBytes(id, offset);
-        if (ret == null) {
-            throw new OutOfMemoryError("Error accessing array at offset "
-                    + offset);
-        }
-        return ret;
-    }
-
-    @Override
-    public long[] getAttributes(int offset) {
-        return getAttributes(id, offset);
-    }
-
-    @Override
-    public ImageLocation findLocation(UTF8String name, ImageStringsReader strings) {
-        long[] attributes = findAttributes(id, name.getBytes());
-
-        return attributes != null ? new ImageLocation(attributes, strings) : null;
-    }
-
-    @Override
-    public int[] attributeOffsets() {
-        return attributeOffsets(id);
-    }
-
-    // TODO: Remove when JRT-FS no longer indirectly depends on ImageNativeSubstrate
-    /**
-     * Reflective wrapper around ShareSecrets JavaNioAccess.
-     *
-     * SharedSecrets and friend interfaces moved from 'sun.misc' to 'jdk.internal.misc'
-     * in 1.9. This class provides the runtime with access to the appropriate
-     * JavaNioAccess methods whether running on 1.9, or lower.
-     */
-    static class NIOACCESS {
-
-        private static final String PKG_PREFIX = "jdk.internal.misc";
-        private static final String LEGACY_PKG_PREFIX = "sun.misc";
-
-        private static final Object javaNioAccess;
-        private static final java.lang.reflect.Method newDirectByteBufferMethod;
-
-        static {
-            try {
-                Class<?> c = getJDKClass("JavaNioAccess");
-
-                java.lang.reflect.Method m =
-                        getJDKClass("SharedSecrets").getDeclaredMethod("getJavaNioAccess");
-                javaNioAccess = m.invoke(null);
-
-                newDirectByteBufferMethod = c.getDeclaredMethod("newDirectByteBuffer",
-                                                                long.class,
-                                                                int.class,
-                                                                Object.class);
-            } catch (ReflectiveOperationException x) {
-                throw new InternalError(x);
-            }
-        }
-
-        private static Class<?> getJDKClass(String name) throws ClassNotFoundException {
-            try {
-                return Class.forName(PKG_PREFIX + "." + name);
-            } catch (ClassNotFoundException x) {
-                try {
-                    return Class.forName(LEGACY_PKG_PREFIX + "." + name);
-                } catch (ClassNotFoundException ex) {
-                    x.addSuppressed(ex);
-                    throw x;
-                }
-            }
-        }
-
-        static ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
-            try {
-                return (ByteBuffer) newDirectByteBufferMethod.invoke(javaNioAccess, addr, cap, ob);
-            } catch (ReflectiveOperationException x) {
-                throw new InternalError(x);
-            }
-        }
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java
index d66621f..cb64fb0 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.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
@@ -32,19 +32,34 @@
 import java.nio.file.Files;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileTime;
-import java.nio.file.Paths;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Objects;
 import java.util.function.Consumer;
-import static jdk.internal.jimage.UTF8String.*;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 public class ImageReader extends BasicImageReader {
-    // well-known strings needed for image file system.
-    static final UTF8String ROOT_STRING = UTF8String.SLASH_STRING;
+
+    private static final int SIZE_OF_OFFSET = 4;
+
+    // Map of files opened as LITTLE_ENDIAN
+    private static final HashMap<Path, ImageReader> OPEN_LE_FILES
+            = new HashMap<>();
+
+    // Map of files opened as BIG_ENDIAN
+    private static final HashMap<Path, ImageReader> OPEN_BE_FILES
+            = new HashMap<>();
+
+    private int openCount;
 
     // attributes of the .jimage file. jimage file does not contain
     // attributes for the individual resources (yet). We use attributes
@@ -52,78 +67,60 @@
     // Iniitalized lazily, see {@link #imageFileAttributes()}.
     private BasicFileAttributes imageFileAttributes;
 
-    private final ImageModuleData moduleData;
-
     // directory management implementation
-    private final Map<UTF8String, Node> nodes;
+    private final HashMap<String, Node> nodes;
     private volatile Directory rootDir;
 
     private Directory packagesDir;
     private Directory modulesDir;
 
-    ImageReader(String imagePath, ByteOrder byteOrder) throws IOException {
+    private ImageReader(Path imagePath, ByteOrder byteOrder) throws IOException {
         super(imagePath, byteOrder);
-        this.moduleData = new ImageModuleData(this);
-        this.nodes = Collections.synchronizedMap(new HashMap<>());
+        this.nodes = new HashMap<>();
     }
 
-    ImageReader(String imagePath) throws IOException {
-        this(imagePath, ByteOrder.nativeOrder());
+    public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException {
+        HashMap<Path, ImageReader> openFiles = getOpenFilesMap(byteOrder);
+        ImageReader reader;
+        synchronized (openFiles) {
+            reader = openFiles.get(imagePath);
+            if (reader == null) {
+                reader = new ImageReader(imagePath, byteOrder);
+                ImageReader existingReader = openFiles.putIfAbsent(imagePath, reader);
+                assert (existingReader == null);
+            }
+            reader.openCount++;
+        }
+        return reader;
     }
 
-    public static ImageReader open(String imagePath, ByteOrder byteOrder) throws IOException {
-        return new ImageReader(imagePath, byteOrder);
+    private static HashMap<Path, ImageReader> getOpenFilesMap(ByteOrder byteOrder) {
+        return (byteOrder == ByteOrder.BIG_ENDIAN) ? OPEN_BE_FILES : OPEN_LE_FILES;
     }
 
     /**
      * Opens the given file path as an image file, returning an {@code ImageReader}.
      */
-    public static ImageReader open(String imagePath) throws IOException {
+    public static ImageReader open(Path imagePath) throws IOException {
         return open(imagePath, ByteOrder.nativeOrder());
     }
 
-    @Override
-    public synchronized void close() throws IOException {
-        super.close();
-        clearNodes();
-    }
-
-    @Override
-    public ImageLocation findLocation(UTF8String name) {
-        ImageLocation location = super.findLocation(name);
-
-        // NOTE: This should be removed when module system is up in full.
-        if (location == null) {
-            int index = name.lastIndexOf('/');
-
-            if (index != -1) {
-                UTF8String packageName = name.substring(0, index);
-                UTF8String moduleName = moduleData.packageToModule(packageName);
-
-                if (moduleName != null) {
-                    UTF8String fullName = UTF8String.SLASH_STRING.concat(moduleName,
-                            UTF8String.SLASH_STRING, name);
-                    location = super.findLocation(fullName);
-                }
-            } else {
-                // No package, try all modules.
-                for (String mod : moduleData.allModuleNames()) {
-                    location = super.findLocation("/" + mod + "/" + name);
-                    if (location != null) {
-                        break;
-                    }
-                }
+    private boolean canClose() {
+        HashMap<Path, ImageReader> openFiles = getOpenFilesMap(this.getByteOrder());
+        synchronized (openFiles) {
+            if (--this.openCount == 0) {
+                return openFiles.remove(this.getName(), this);
             }
         }
-
-        return location;
+        return false;
     }
 
-    /**
-     * Return the module name that contains the given package name.
-     */
-    public String getModule(String packageName) {
-        return moduleData.packageToModule(packageName);
+    @Override
+    public void close() throws IOException {
+        if (canClose()) {
+            super.close();
+            clearNodes();
+       }
     }
 
     // jimage file does not store directory structure. We build nodes
@@ -135,15 +132,13 @@
         private static final int MODULES_DIR = 0b0000_0000_0000_0100;
 
         private int flags;
-        private final UTF8String name;
+        private final String name;
         private final BasicFileAttributes fileAttrs;
         private boolean completed;
 
-        Node(UTF8String name, BasicFileAttributes fileAttrs) {
-            assert name != null;
-            assert fileAttrs != null;
-            this.name = name;
-            this.fileAttrs = fileAttrs;
+        Node(String name, BasicFileAttributes fileAttrs) {
+            this.name = Objects.requireNonNull(name);
+            this.fileAttrs = Objects.requireNonNull(fileAttrs);
         }
 
         /**
@@ -183,7 +178,7 @@
             return (flags & MODULES_DIR) != 0;
         }
 
-        public final UTF8String getName() {
+        public final String getName() {
             return name;
         }
 
@@ -250,7 +245,7 @@
         }
 
         public final String getNameString() {
-            return name.toString();
+            return name;
         }
 
         @Override
@@ -281,17 +276,17 @@
     static final class Directory extends Node {
         private final List<Node> children;
 
-        private Directory(Directory parent, UTF8String name, BasicFileAttributes fileAttrs) {
+        private Directory(String name, BasicFileAttributes fileAttrs) {
             super(name, fileAttrs);
             children = new ArrayList<>();
         }
 
-        static Directory create(Directory parent, UTF8String name, BasicFileAttributes fileAttrs) {
-            Directory dir = new Directory(parent, name, fileAttrs);
+        static Directory create(Directory parent, String name, BasicFileAttributes fileAttrs) {
+            Directory d = new Directory(name, fileAttrs);
             if (parent != null) {
-                parent.addChild(dir);
+                parent.addChild(d);
             }
-            return dir;
+            return d;
         }
 
         @Override
@@ -325,25 +320,15 @@
     static class Resource extends Node {
         private final ImageLocation loc;
 
-        private Resource(Directory parent, ImageLocation loc, BasicFileAttributes fileAttrs) {
-            this(parent, loc.getFullName(true), loc, fileAttrs);
-        }
-
-        private Resource(Directory parent, UTF8String name, ImageLocation loc, BasicFileAttributes fileAttrs) {
-            super(name, fileAttrs);
+        private Resource(ImageLocation loc, BasicFileAttributes fileAttrs) {
+            super(loc.getFullName(true), fileAttrs);
             this.loc = loc;
-         }
+        }
 
         static Resource create(Directory parent, ImageLocation loc, BasicFileAttributes fileAttrs) {
-            Resource resource = new Resource(parent, loc, fileAttrs);
-            parent.addChild(resource);
-            return resource;
-        }
-
-        static Resource create(Directory parent, UTF8String name, ImageLocation loc, BasicFileAttributes fileAttrs) {
-            Resource resource = new Resource(parent, name, loc, fileAttrs);
-            parent.addChild(resource);
-            return resource;
+            Resource rs = new Resource(loc, fileAttrs);
+            parent.addChild(rs);
+            return rs;
         }
 
         @Override
@@ -373,7 +358,7 @@
 
         @Override
         public String extension() {
-            return loc.getExtensionString();
+            return loc.getExtension();
         }
 
         @Override
@@ -386,15 +371,15 @@
     static class LinkNode extends Node {
         private final Node link;
 
-        private LinkNode(Directory parent, UTF8String name, Node link) {
+        private LinkNode(String name, Node link) {
             super(name, link.getFileAttributes());
             this.link = link;
         }
 
-        static LinkNode create(Directory parent, UTF8String name, Node link) {
-            LinkNode linkNode = new LinkNode(parent, name, link);
-            parent.addChild(linkNode);
-            return linkNode;
+        static LinkNode create(Directory parent, String name, Node link) {
+            LinkNode ln = new LinkNode(name, link);
+            parent.addChild(ln);
+            return ln;
         }
 
         @Override
@@ -418,14 +403,6 @@
         return buildRootDirectory();
     }
 
-    public Node findNode(String name) {
-        return findNode(new UTF8String(name));
-    }
-
-    public Node findNode(byte[] name) {
-        return findNode(new UTF8String(name));
-    }
-
     /**
      * To visit sub tree resources.
      */
@@ -436,142 +413,178 @@
 
     /**
      * Lazily build a node from a name.
-     */
-    private final class NodeBuilder {
+    */
+    private Node buildNode(String name) {
+        Node n;
+        boolean isPackages = name.startsWith("/packages");
+        boolean isModules = !isPackages && name.startsWith("/modules");
 
-        private static final int SIZE_OF_OFFSET = 4;
-
-        private final UTF8String name;
-
-        private NodeBuilder(UTF8String name) {
-            this.name = name;
+        if (!(isModules || isPackages)) {
+            return null;
         }
 
-        private Node buildNode() {
-            Node n = null;
-            boolean isPackages = false;
-            boolean isModules = false;
-            String strName = name.toString();
-            if (strName.startsWith("" + PACKAGES_STRING)) {
-                isPackages = true;
+        ImageLocation loc = findLocation(name);
+
+        if (loc != null) { // A sub tree node
+            if (isPackages) {
+                n = handlePackages(name, loc);
+            } else { // modules sub tree
+                n = handleModulesSubTree(name, loc);
+            }
+        } else { // Asking for a resource? /modules/java.base/java/lang/Object.class
+            if (isModules) {
+                n = handleResource(name);
             } else {
-                if (strName.startsWith("" + MODULES_STRING)) {
-                    isModules = true;
-                }
-            }
-            if (!isModules && !isPackages) {
-                return null;
-            }
-
-            ImageLocation loc = findLocation(name);
-
-            if (loc != null) { // A sub tree node
-                if (isPackages) {
-                    n = handlePackages(strName, loc);
-                } else { // modules sub tree
-                    n = handleModulesSubTree(strName, loc);
-                }
-            } else { // Asking for a resource? /modules/java.base/java/lang/Object.class
-                if (isModules) {
-                    n = handleResource(strName, loc);
-                }
-            }
-            return n;
-        }
-
-        private void visitLocation(ImageLocation loc, LocationVisitor visitor) {
-            byte[] offsets = getResource(loc);
-            ByteBuffer buffer = ByteBuffer.wrap(offsets);
-            buffer.order(getByteOrder());
-            IntBuffer intBuffer = buffer.asIntBuffer();
-            for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) {
-                int offset = intBuffer.get(i);
-                ImageLocation pkgLoc = getLocation(offset);
-                visitor.visit(pkgLoc);
+                // Possibly ask for /packages/java.lang/java.base
+                // although /packages/java.base not created
+                n = handleModuleLink(name);
             }
         }
+        return n;
+    }
 
-        private Node handlePackages(String name, ImageLocation loc) {
-            long size = loc.getUncompressedSize();
-            Node n = null;
-            // Only possiblities are /packages, /packages/package/module
-            if (name.equals("" + PACKAGES_STRING)) {
-                visitLocation(loc, (childloc) -> {
-                    findNode(childloc.getFullName());
-                });
-                packagesDir.setCompleted(true);
-                n = packagesDir;
-            } else {
-                if (size != 0) { // children are links to module
-                    String pkgName = getBaseExt(loc);
-                    Directory pkgDir = newDirectory(packagesDir,
-                            packagesDir.getName().concat(SLASH_STRING, new UTF8String(pkgName)));
-                    visitLocation(loc, (childloc) -> {
-                        findNode(childloc.getFullName());
-                    });
-                    pkgDir.setCompleted(true);
-                    n = pkgDir;
-                } else { // Link to module
-                    String pkgName = loc.getParentString();
-                    String modName = getBaseExt(loc);
-                    Node targetNode = findNode(MODULES_STRING + "/" + modName);
-                    if (targetNode != null) {
-                        UTF8String pkgDirName = packagesDir.getName().concat(SLASH_STRING, new UTF8String(pkgName));
-                        Directory pkgDir = (Directory) nodes.get(pkgDirName);
-                        Node linkNode = newLinkNode(pkgDir,
-                                pkgDir.getName().concat(SLASH_STRING, new UTF8String(modName)), targetNode);
-                        n = linkNode;
-                    }
-                }
-            }
-            return n;
-        }
-
-        private Node handleModulesSubTree(String name, ImageLocation loc) {
-            Node n;
-            Directory dir = makeDirectories(loc.getFullName());
-            visitLocation(loc, (childloc) -> {
-                String path = childloc.getFullNameString();
-                if (path.startsWith(MODULES_STRING.toString())) { // a package
-                    makeDirectories(childloc.getFullName());
-                } else { // a resource
-                    makeDirectories(childloc.buildName(true, true, false));
-                    newResource(dir, childloc);
-                }
-            });
-            dir.setCompleted(true);
-            n = dir;
-            return n;
-        }
-
-        private Node handleResource(String name, ImageLocation loc) {
-            Node n = null;
-            String locationPath = name.substring((MODULES_STRING).length());
-            ImageLocation resourceLoc = findLocation(locationPath);
-            if (resourceLoc != null) {
-                Directory dir = makeDirectories(resourceLoc.buildName(true, true, false));
-                Resource res = newResource(dir, resourceLoc);
-                n = res;
-            }
-            return n;
-        }
-
-        private String getBaseExt(ImageLocation loc) {
-            String base = loc.getBaseString();
-            String ext = loc.getExtensionString();
-            if (ext != null && !ext.isEmpty()) {
-                base = base + "." + ext;
-            }
-            return base;
+    private void visitLocation(ImageLocation loc, LocationVisitor visitor) {
+        byte[] offsets = getResource(loc);
+        ByteBuffer buffer = ByteBuffer.wrap(offsets);
+        buffer.order(getByteOrder());
+        IntBuffer intBuffer = buffer.asIntBuffer();
+        for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) {
+            int offset = intBuffer.get(i);
+            ImageLocation pkgLoc = getLocation(offset);
+            visitor.visit(pkgLoc);
         }
     }
 
-    public synchronized Node findNode(UTF8String name) {
+    private void visitPackageLocation(ImageLocation loc) {
+        // Retrieve package name
+        String pkgName = getBaseExt(loc);
+        // Content is array of offsets in Strings table
+        byte[] stringsOffsets = getResource(loc);
+        ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets);
+        buffer.order(getByteOrder());
+        IntBuffer intBuffer = buffer.asIntBuffer();
+        // For each module, create a link node.
+        for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) {
+            // skip empty state, useless.
+            intBuffer.get(i);
+            i++;
+            int offset = intBuffer.get(i);
+            String moduleName = getString(offset);
+            Node targetNode = findNode("/modules/" + moduleName);
+            if (targetNode != null) {
+                String pkgDirName = packagesDir.getName() + "/" + pkgName;
+                Directory pkgDir = (Directory) nodes.get(pkgDirName);
+                newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode);
+            }
+        }
+    }
+
+    private Node handlePackages(String name, ImageLocation loc) {
+        long size = loc.getUncompressedSize();
+        Node n = null;
+        // Only possiblities are /packages, /packages/package/module
+        if (name.equals("/packages")) {
+            visitLocation(loc, (childloc) -> {
+                findNode(childloc.getFullName());
+            });
+            packagesDir.setCompleted(true);
+            n = packagesDir;
+        } else {
+            if (size != 0) { // children are offsets to module in StringsTable
+                String pkgName = getBaseExt(loc);
+                Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName);
+                visitPackageLocation(loc);
+                pkgDir.setCompleted(true);
+                n = pkgDir;
+            } else { // Link to module
+                String pkgName = loc.getParent();
+                String modName = getBaseExt(loc);
+                Node targetNode = findNode("/modules/" + modName);
+                if (targetNode != null) {
+                    String pkgDirName = packagesDir.getName() + "/" + pkgName;
+                    Directory pkgDir = (Directory) nodes.get(pkgDirName);
+                    Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode);
+                    n = linkNode;
+                }
+            }
+        }
+        return n;
+    }
+
+    // Asking for /packages/package/module although
+    // /packages/<pkg>/ not yet created, need to create it
+    // prior to return the link to module node.
+    private Node handleModuleLink(String name) {
+        // eg: unresolved /packages/package/module
+        // Build /packages/package node
+        Node ret = null;
+        String radical = "/packages/";
+        String path = name;
+        if (path.startsWith(radical)) {
+            int start = radical.length();
+            int pkgEnd = path.indexOf('/', start);
+            if (pkgEnd != -1) {
+                String pkg = path.substring(start, pkgEnd);
+                String pkgPath = radical + pkg;
+                Node n = findNode(pkgPath);
+                // If not found means that this is a symbolic link such as:
+                // /packages/java.util/java.base/java/util/Vector.class
+                // and will be done by a retry of the filesystem
+                for (Node child : n.getChildren()) {
+                    if (child.name.equals(name)) {
+                        ret = child;
+                        break;
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
+    private Node handleModulesSubTree(String name, ImageLocation loc) {
+        Node n;
+        assert (name.equals(loc.getFullName()));
+        Directory dir = makeDirectories(name);
+        visitLocation(loc, (childloc) -> {
+            String path = childloc.getFullName();
+            if (path.startsWith("/modules")) { // a package
+                makeDirectories(path);
+            } else { // a resource
+                makeDirectories(childloc.buildName(true, true, false));
+                newResource(dir, childloc);
+            }
+        });
+        dir.setCompleted(true);
+        n = dir;
+        return n;
+    }
+
+    private Node handleResource(String name) {
+        Node n = null;
+        String locationPath = name.substring("/modules".length());
+        ImageLocation resourceLoc = findLocation(locationPath);
+        if (resourceLoc != null) {
+            Directory dir = makeDirectories(resourceLoc.buildName(true, true, false));
+            Resource res = newResource(dir, resourceLoc);
+            n = res;
+        }
+        return n;
+    }
+
+    private String getBaseExt(ImageLocation loc) {
+        String base = loc.getBase();
+        String ext = loc.getExtension();
+        if (ext != null && !ext.isEmpty()) {
+            base = base + "." + ext;
+        }
+        return base;
+    }
+
+    public synchronized Node findNode(String name) {
         buildRootDirectory();
         Node n = nodes.get(name);
         if (n == null || !n.isCompleted()) {
-            NodeBuilder builder = new NodeBuilder(name);
-            n = builder.buildNode();
+            n = buildNode(name);
         }
         return n;
     }
@@ -588,7 +601,7 @@
         BasicFileAttributes attrs = imageFileAttributes;
         if (attrs == null) {
             try {
-                Path file = Paths.get(imagePath());
+                Path file = getImagePath();
                 attrs = Files.readAttributes(file, BasicFileAttributes.class);
             } catch (IOException ioe) {
                 throw new UncheckedIOException(ioe);
@@ -598,30 +611,38 @@
         return attrs;
     }
 
-    private synchronized Directory buildRootDirectory() {
-        if (rootDir != null) {
-            return rootDir;
+    private Directory buildRootDirectory() {
+        Directory root = rootDir; // volatile read
+        if (root != null) {
+            return root;
         }
 
-        // FIXME no time information per resource in jimage file (yet?)
-        // we use file attributes of jimage itself.
-        // root directory
-        rootDir = newDirectory(null, ROOT_STRING);
-        rootDir.setIsRootDir();
+        synchronized (this) {
+            root = rootDir;
+            if (root != null) {
+                return root;
+            }
 
-        // /packages dir
-        packagesDir = newDirectory(rootDir, PACKAGES_STRING);
-        packagesDir.setIsPackagesDir();
+            // FIXME no time information per resource in jimage file (yet?)
+            // we use file attributes of jimage itself.
+            // root directory
+            root = newDirectory(null, "/");
+            root.setIsRootDir();
 
-        // /modules dir
-        modulesDir = newDirectory(rootDir, MODULES_STRING);
-        modulesDir.setIsModulesDir();
+            // /packages dir
+            packagesDir = newDirectory(root, "/packages");
+            packagesDir.setIsPackagesDir();
 
-        rootDir.setCompleted(true);
-        return rootDir;
+            // /modules dir
+            modulesDir = newDirectory(root, "/modules");
+            modulesDir.setIsModulesDir();
+
+            root.setCompleted(true);
+            return rootDir = root;
+        }
     }
 
-    private Directory newDirectory(Directory parent, UTF8String name) {
+    private Directory newDirectory(Directory parent, String name) {
         Directory dir = Directory.create(parent, name, imageFileAttributes());
         nodes.put(dir.getName(), dir);
         return dir;
@@ -633,39 +654,30 @@
         return res;
     }
 
-    private LinkNode newLinkNode(Directory dir, UTF8String name, Node link) {
+    private LinkNode newLinkNode(Directory dir, String name, Node link) {
         LinkNode linkNode = LinkNode.create(dir, name, link);
         nodes.put(linkNode.getName(), linkNode);
         return linkNode;
     }
 
-    private List<UTF8String> dirs(UTF8String parent) {
-        List<UTF8String> splits = new ArrayList<>();
-
-        for (int i = 1; i < parent.length(); i++) {
-            if (parent.byteAt(i) == '/') {
-                splits.add(parent.substring(0, i));
-            }
+    private Directory makeDirectories(String parent) {
+        Directory last = rootDir;
+        for (int offset = parent.indexOf('/', 1);
+                offset != -1;
+                offset = parent.indexOf('/', offset + 1)) {
+            String dir = parent.substring(0, offset);
+            last = makeDirectory(dir, last);
         }
+        return makeDirectory(parent, last);
 
-        splits.add(parent);
-
-        return splits;
     }
 
-    private Directory makeDirectories(UTF8String parent) {
-        Directory last = rootDir;
-        List<UTF8String> dirs = dirs(parent);
-
-        for (UTF8String dir : dirs) {
-            Directory nextDir = (Directory) nodes.get(dir);
-            if (nextDir == null) {
-                nextDir = newDirectory(last, dir);
-            }
-            last = nextDir;
+    private Directory makeDirectory(String dir, Directory last) {
+        Directory nextDir = (Directory) nodes.get(dir);
+        if (nextDir == null) {
+            nextDir = newDirectory(last, dir);
         }
-
-        return last;
+        return nextDir;
     }
 
     public byte[] getResource(Node node) throws IOException {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java
index 5f9a219..23be8fa 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.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
@@ -34,13 +34,19 @@
 
 /**
  * Factory to get ImageReader
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public class ImageReaderFactory {
     private ImageReaderFactory() {}
 
     private static final String JAVA_HOME = System.getProperty("java.home");
     private static final Path BOOT_MODULES_JIMAGE =
-        Paths.get(JAVA_HOME, "lib", "modules", "bootmodules.jimage");
+        Paths.get(JAVA_HOME, "lib", "modules");
 
     private static final Map<Path, ImageReader> readers = new ConcurrentHashMap<>();
 
@@ -52,7 +58,7 @@
         if (reader != null) {
             return reader;
         }
-        reader = ImageReader.open(jimage.toString());
+        reader = ImageReader.open(jimage);
         // potential race with other threads opening the same URL
         ImageReader r = readers.putIfAbsent(jimage, reader);
         if (r == null) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageResourcesTree.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageResourcesTree.java
deleted file mode 100644
index e93e249..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageResourcesTree.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-/**
- * A class to build a sorted tree of Resource paths as a tree of ImageLocation.
- *
- */
-// XXX Public only due to the JImageTask / JImageTask code duplication
-public final class ImageResourcesTree {
-
-    private static final String MODULES = "modules";
-    private static final String PACKAGES = "packages";
-    public static final String MODULES_STRING = UTF8String.MODULES_STRING.toString();
-    public static final String PACKAGES_STRING = UTF8String.PACKAGES_STRING.toString();
-
-    public static boolean isTreeInfoResource(String path) {
-        return path.startsWith(PACKAGES_STRING) || path.startsWith(MODULES_STRING);
-    }
-
-    /**
-     * Path item tree node.
-     */
-    private static final class Node {
-
-        private final String name;
-        private final Map<String, Node> children = new TreeMap<>();
-        private final Node parent;
-        private ImageLocationWriter loc;
-        private boolean isResource;
-
-        private Node(String name, Node parent) {
-            this.name = name;
-            this.parent = parent;
-
-            if (parent != null) {
-                parent.children.put(name, this);
-            }
-        }
-
-        public String getPath() {
-            if (parent == null) {
-                return "/";
-            }
-            return buildPath(this);
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public Node getChildren(String name) {
-            Node item = children.get(name);
-            return item;
-        }
-
-        private static String buildPath(Node item) {
-            if (item == null) {
-                return null;
-            }
-            String path = buildPath(item.parent);
-            if (path == null) {
-                return item.getName();
-            } else {
-                return path + "/" + item.getName();
-            }
-        }
-    }
-
-    /**
-     * Tree of nodes.
-     */
-    private static final class Tree {
-
-        private final Map<String, Node> directAccess = new HashMap<>();
-        private final List<String> paths;
-        private final Node root;
-        private Node modules;
-        private Node packages;
-
-        private Tree(List<String> paths) {
-            this.paths = paths;
-            root = new Node("", null);
-            buildTree();
-        }
-
-        private void buildTree() {
-            modules = new Node(MODULES, root);
-            directAccess.put(modules.getPath(), modules);
-
-            Map<String, Set<String>> moduleToPackage = new TreeMap<>();
-            Map<String, Set<String>> packageToModule = new TreeMap<>();
-
-            for (String p : paths) {
-                if (!p.startsWith("/")) {
-                    continue;
-                }
-                String[] split = p.split("/");
-                Node current = modules;
-                String module = null;
-                for (int i = 0; i < split.length; i++) {
-                    String s = split[i];
-                    if (!s.isEmpty()) {
-                        if (module == null) {
-                            module = s;
-                        }
-                        Node n = current.children.get(s);
-                        if (n == null) {
-                            n = new Node(s, current);
-                            if (i == split.length - 1) { // Leaf
-                                n.isResource = true;
-                                String pkg = toPackageName(n.parent);
-                                if (pkg != null && !pkg.startsWith("META-INF")) {
-                                    Set<String> pkgs = moduleToPackage.get(module);
-                                    if (pkgs == null) {
-                                        pkgs = new TreeSet<>();
-                                        moduleToPackage.put(module, pkgs);
-                                    }
-                                    pkgs.add(pkg);
-                                }
-                            } else { // put only sub trees, no leaf
-                                directAccess.put(n.getPath(), n);
-                                String pkg = toPackageName(n);
-                                if (pkg != null && !pkg.startsWith("META-INF")) {
-                                    Set<String> mods = packageToModule.get(pkg);
-                                    if (mods == null) {
-                                        mods = new TreeSet<>();
-                                        packageToModule.put(pkg, mods);
-                                    }
-                                    mods.add(module);
-
-                                }
-                            }
-                        }
-                        current = n;
-                    }
-                }
-            }
-            packages = new Node(PACKAGES, root);
-            directAccess.put(packages.getPath(), packages);
-            for (Map.Entry<String, Set<String>> entry : moduleToPackage.entrySet()) {
-                for (String pkg : entry.getValue()) {
-                    Node pkgNode = new Node(pkg, packages);
-                    directAccess.put(pkgNode.getPath(), pkgNode);
-
-                    Node modNode = new Node(entry.getKey(), pkgNode);
-                    directAccess.put(modNode.getPath(), modNode);
-                }
-            }
-            for (Map.Entry<String, Set<String>> entry : packageToModule.entrySet()) {
-                Node pkgNode = new Node(entry.getKey(), packages);
-                directAccess.put(pkgNode.getPath(), pkgNode);
-                for (String module : entry.getValue()) {
-                    Node modNode = new Node(module, pkgNode);
-                    directAccess.put(modNode.getPath(), modNode);
-                }
-            }
-        }
-
-        public String toResourceName(Node node) {
-            if (!node.children.isEmpty()) {
-                throw new RuntimeException("Node is not a resource");
-            }
-            return removeRadical(node);
-        }
-
-        public String getModule(Node node) {
-            if (node.parent == null || node.getName().equals(MODULES) ||
-                node.getName().startsWith(PACKAGES)) {
-                return null;
-            }
-            String path = removeRadical(node);
-            // "/xxx/...";
-            path = path.substring(1);
-            int i = path.indexOf("/");
-            if (i == -1) {
-                return path;
-            } else {
-                return path.substring(0, i);
-            }
-        }
-
-        public String toPackageName(Node node) {
-            if (node.parent == null) {
-                return null;
-            }
-            String path = removeRadical(node.getPath(), "/" + MODULES + "/");
-            String module = getModule(node);
-            if (path.equals(module)) {
-                return null;
-            }
-            String pkg = removeRadical(path, module + "/");
-            return pkg.replaceAll("/", ".");
-        }
-
-        public String removeRadical(Node node) {
-            String s = node.getPath();
-            return removeRadical(node.getPath(), "/" + MODULES);
-        }
-
-        private String removeRadical(String path, String str) {
-            return path.substring(str.length());
-        }
-
-        public Node getRoot() {
-            return root;
-        }
-
-        public Map<String, Node> getMap() {
-            return directAccess;
-        }
-    }
-
-    private static final class LocationsAdder {
-
-        private long offset;
-        private final List<byte[]> content = new ArrayList<>();
-        private final BasicImageWriter writer;
-        private final Tree tree;
-
-        LocationsAdder(Tree tree, long offset, BasicImageWriter writer) {
-            this.tree = tree;
-            this.offset = offset;
-            this.writer = writer;
-            addLocations(tree.getRoot());
-        }
-
-        private int addLocations(Node current) {
-            int[] ret = new int[current.children.size()];
-            int i = 0;
-            for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
-                ret[i] = addLocations(entry.getValue());
-                i += 1;
-            }
-            if (current != tree.getRoot() && !current.isResource) {
-                int size = ret.length * 4;
-                writer.addLocation(current.getPath(), offset, 0, size);
-                offset += size;
-            }
-            return 0;
-        }
-
-        private List<byte[]> computeContent() {
-            // Map used to associate Tree item with locations offset.
-            Map<String, ImageLocationWriter> outLocations = new HashMap<>();
-            for (ImageLocationWriter wr : writer.getLocations()) {
-                outLocations.put(wr.getFullNameString(), wr);
-            }
-            // Attach location to node
-            for (Map.Entry<String, ImageLocationWriter> entry : outLocations.entrySet()) {
-                Node item = tree.getMap().get(entry.getKey());
-                if (item != null) {
-                    item.loc = entry.getValue();
-                }
-            }
-            computeContent(tree.getRoot(), outLocations);
-            return content;
-        }
-
-        private int computeContent(Node current, Map<String, ImageLocationWriter> outLocations) {
-            int[] ret = new int[current.children.size()];
-            int i = 0;
-            for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
-                ret[i] = computeContent(entry.getValue(), outLocations);
-                i += 1;
-            }
-            if (ret.length > 0) {
-                int size = ret.length * 4;
-                ByteBuffer buff = ByteBuffer.allocate(size);
-                buff.order(writer.getByteOrder());
-                for (int val : ret) {
-                    buff.putInt(val);
-                }
-                byte[] arr = buff.array();
-                content.add(arr);
-            } else {
-                if (current.isResource) {
-                    // A resource location, remove "/modules"
-                    String s = tree.toResourceName(current);
-                    current.loc = outLocations.get(s);
-                } else {
-                    // "/packages" leaf node, empty "/packages" or empty "/modules" paths
-                    current.loc = outLocations.get(current.getPath());
-                }
-            }
-            return current == tree.getRoot() ? 0 : current.loc.getLocationOffset();
-        }
-    }
-
-    private final List<String> paths;
-    private final LocationsAdder adder;
-
-    public ImageResourcesTree(long offset, BasicImageWriter writer, List<String> paths) {
-        this.paths = new ArrayList<>();
-        this.paths.addAll(paths);
-        Collections.sort(this.paths);
-        Tree tree = new Tree(this.paths);
-        adder = new LocationsAdder(tree, offset, writer);
-    }
-
-    public void addContent(DataOutputStream out) throws IOException {
-        List<byte[]> content = adder.computeContent();
-        for (byte[] c : content) {
-            out.write(c, 0, c.length);
-        }
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
index dd7709c..6abe1e6 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.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
@@ -29,40 +29,47 @@
 import java.nio.ByteOrder;
 import java.util.Arrays;
 
-class ImageStream {
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class ImageStream {
     private ByteBuffer buffer;
 
-    ImageStream() {
+    public ImageStream() {
         this(1024, ByteOrder.nativeOrder());
     }
 
-    ImageStream(int size) {
+    public ImageStream(int size) {
         this(size, ByteOrder.nativeOrder());
     }
 
-    ImageStream(byte[] bytes) {
+    public ImageStream(byte[] bytes) {
        this(bytes, ByteOrder.nativeOrder());
     }
 
-    ImageStream(ByteOrder byteOrder) {
+    public ImageStream(ByteOrder byteOrder) {
         this(1024, byteOrder);
     }
 
-    ImageStream(int size, ByteOrder byteOrder) {
+    public ImageStream(int size, ByteOrder byteOrder) {
         buffer = ByteBuffer.allocate(size);
         buffer.order(byteOrder);
     }
 
-    ImageStream(byte[] bytes, ByteOrder byteOrder) {
+    public ImageStream(byte[] bytes, ByteOrder byteOrder) {
         buffer = ByteBuffer.wrap(bytes);
         buffer.order(byteOrder);
     }
 
-    ImageStream(ByteBuffer buffer) {
+    public ImageStream(ByteBuffer buffer) {
         this.buffer = buffer;
     }
 
-    ImageStream align(int alignment) {
+    public ImageStream align(int alignment) {
         int padding = (getSize() - 1) & ((1 << alignment) - 1);
 
         for (int i = 0; i < padding; i++) {
@@ -72,8 +79,10 @@
         return this;
     }
 
-    void ensure(int needs) {
-        assert 0 <= needs : "Negative needs";
+    public void ensure(int needs) {
+        if (needs < 0) {
+            throw new IndexOutOfBoundsException("needs");
+        }
 
         if (needs > buffer.remaining()) {
             byte[] bytes = buffer.array();
@@ -86,109 +95,112 @@
         }
     }
 
-    boolean hasByte() {
+    public boolean hasByte() {
         return buffer.remaining() != 0;
     }
 
-    boolean hasBytes(int needs) {
+    public boolean hasBytes(int needs) {
         return needs <= buffer.remaining();
     }
 
-    void skip(int n) {
-        assert 0 <= n : "Negative offset";
+    public void skip(int n) {
+        if (n < 0) {
+            throw new IndexOutOfBoundsException("n");
+        }
+
         buffer.position(buffer.position() + n);
     }
 
-    int get() {
+    public int get() {
         return buffer.get() & 0xFF;
     }
 
-    void get(byte bytes[], int offset, int size) {
+    public void get(byte bytes[], int offset, int size) {
         buffer.get(bytes, offset, size);
     }
 
-    int getShort() {
+    public int getShort() {
         return buffer.getShort();
     }
 
-    int getInt() {
+    public int getInt() {
         return buffer.getInt();
     }
 
-    long getLong() {
+    public long getLong() {
         return buffer.getLong();
     }
 
-    ImageStream put(byte byt) {
+    public ImageStream put(byte byt) {
         ensure(1);
         buffer.put(byt);
 
         return this;
     }
 
-    ImageStream put(int byt) {
+    public ImageStream put(int byt) {
         return put((byte)byt);
     }
 
-    ImageStream put(byte bytes[], int offset, int size) {
+    public ImageStream put(byte bytes[], int offset, int size) {
         ensure(size);
         buffer.put(bytes, offset, size);
 
         return this;
     }
 
-    ImageStream put(ImageStream stream) {
+    public ImageStream put(ImageStream stream) {
         put(stream.buffer.array(), 0, stream.buffer.position());
 
         return this;
     }
 
-    ImageStream putShort(short value) {
+    public ImageStream putShort(short value) {
         ensure(2);
         buffer.putShort(value);
 
         return this;
     }
 
-    ImageStream putShort(int value) {
+    public ImageStream putShort(int value) {
         return putShort((short)value);
     }
 
-    ImageStream putInt(int value) {
+    public ImageStream putInt(int value) {
         ensure(4);
         buffer.putInt(value);
 
         return this;
     }
 
-    ImageStream putLong(long value) {
+    public ImageStream putLong(long value) {
         ensure(8);
         buffer.putLong(value);
 
         return this;
     }
 
-    ByteBuffer getBuffer() {
+    public ByteBuffer getBuffer() {
         return buffer;
     }
 
-    int getPosition() {
+    public int getPosition() {
         return buffer.position();
     }
 
-    int getSize() {
+    public int getSize() {
         return buffer.position();
     }
 
-    byte[] getBytes() {
+    public byte[] getBytes() {
         return buffer.array();
     }
 
-    void setPosition(int offset) {
+    public void setPosition(int offset) {
         buffer.position(offset);
     }
 
-    byte[] toArray() {
+    public byte[] toArray() {
         return Arrays.copyOf(buffer.array(), buffer.position());
     }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java
index d4470d9..6e7d76a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.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
@@ -25,8 +25,15 @@
 
 package jdk.internal.jimage;
 
-interface ImageStrings {
-    public UTF8String get(int offset);
+/**
+ * @implNote This interface needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public interface ImageStrings {
+    public String get(int offset);
 
-    public int add(final UTF8String string);
+    public int add(final String string);
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
index e4ee6c3..7a6ad7b 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.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
@@ -25,7 +25,18 @@
 
 package jdk.internal.jimage;
 
-class ImageStringsReader implements ImageStrings {
+import java.io.UTFDataFormatException;
+import java.nio.ByteBuffer;
+
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class ImageStringsReader implements ImageStrings {
+    public static final int HASH_MULTIPLIER = 0x01000193;
     private final BasicImageReader reader;
 
     ImageStringsReader(BasicImageReader reader) {
@@ -33,12 +44,239 @@
     }
 
     @Override
-    public UTF8String get(int offset) {
-        return reader.getUTF8String(offset);
+    public String get(int offset) {
+        return reader.getString(offset);
     }
 
     @Override
-    public int add(final UTF8String string) {
+    public int add(final String string) {
         throw new InternalError("Can not add strings at runtime");
     }
+
+    private static int hashCode(byte[] bytes, int offset, int count, int seed) {
+        for (int i = offset, limit = offset + count; i < limit; i++) {
+            seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
+        }
+
+        return seed & 0x7FFFFFFF;
+    }
+
+    public static int hashCode(byte[] bytes, int seed) {
+        return hashCode(bytes, 0, bytes.length, seed);
+    }
+
+    public static int hashCode(byte[] bytes) {
+        return hashCode(bytes, 0, bytes.length, HASH_MULTIPLIER);
+    }
+
+    public static int hashCode(String string, int seed) {
+        return hashCode(mutf8FromString(string), seed);
+    }
+
+    public static int hashCode(String string) {
+        return hashCode(mutf8FromString(string), HASH_MULTIPLIER);
+    }
+
+    static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
+        int length = 0;
+
+        for (int i = offset; i < offset + count; i++) {
+            byte ch = bytes[i];
+
+            if (ch == 0) {
+                break;
+            }
+
+            if ((ch & 0xC0) != 0x80) {
+                length++;
+            }
+        }
+
+        return length;
+    }
+
+    static void charsFromMUTF8(char[] chars, byte[] bytes, int offset, int count) throws UTFDataFormatException {
+        int j = 0;
+
+        for (int i = offset; i < offset + count; i++) {
+            byte ch = bytes[i];
+
+            if (ch == 0) {
+                break;
+            }
+
+            boolean is_unicode = (ch & 0x80) != 0;
+            int uch = ch & 0x7F;
+
+            if (is_unicode) {
+                int mask = 0x40;
+
+                while ((uch & mask) != 0) {
+                    ch = bytes[++i];
+
+                    if ((ch & 0xC0) != 0x80) {
+                        throw new UTFDataFormatException("bad continuation 0x" + Integer.toHexString(ch));
+                    }
+
+                    uch = ((uch & ~mask) << 6) | (ch & 0x3F);
+                    mask <<= 6 - 1;
+                }
+
+                if ((uch & 0xFFFF) != uch) {
+                    throw new UTFDataFormatException("character out of range \\u" + Integer.toHexString(uch));
+                }
+            }
+
+            chars[j++] = (char)uch;
+        }
+    }
+
+    public static String stringFromMUTF8(byte[] bytes, int offset, int count) {
+        int length = charsFromMUTF8Length(bytes, offset, count);
+        char[] chars = new char[length];
+
+        try {
+            charsFromMUTF8(chars, bytes, offset, count);
+        } catch (UTFDataFormatException ex) {
+            throw new InternalError("Attempt to convert non modified UTF-8 byte sequence");
+        }
+
+        return new String(chars);
+    }
+
+    public static String stringFromMUTF8(byte[] bytes) {
+        return stringFromMUTF8(bytes, 0, bytes.length);
+    }
+
+    static int charsFromByteBufferLength(ByteBuffer buffer) {
+        int length = 0;
+
+        while(buffer.hasRemaining()) {
+            byte ch = buffer.get();
+
+            if (ch == 0) {
+                return length;
+            }
+
+            if ((ch & 0xC0) != 0x80) {
+                length++;
+            }
+        }
+
+        throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
+    }
+
+    static void charsFromByteBuffer(char chars[], ByteBuffer buffer) {
+        int j = 0;
+
+        while(buffer.hasRemaining()) {
+            byte ch = buffer.get();
+
+            if (ch == 0) {
+                return;
+            }
+
+            boolean is_unicode = (ch & 0x80) != 0;
+            int uch = ch & 0x7F;
+
+            if (is_unicode) {
+                int mask = 0x40;
+
+                while ((uch & mask) != 0) {
+                    ch = buffer.get();
+
+                    if ((ch & 0xC0) != 0x80) {
+                        throw new InternalError("Bad continuation in modified UTF-8 byte sequence");
+                    }
+
+                    uch = ((uch & ~mask) << 6) | (ch & 0x3F);
+                    mask <<= 6 - 1;
+                }
+            }
+
+            if ((uch & 0xFFFF) != uch) {
+                throw new InternalError("UTF-32 char in modified UTF-8 byte sequence");
+            }
+
+            chars[j++] = (char)uch;
+        }
+
+        throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
+    }
+
+    public static String stringFromByteBuffer(ByteBuffer buffer) {
+        int length = charsFromByteBufferLength(buffer);
+        buffer.rewind();
+        char[] chars = new char[length];
+        charsFromByteBuffer(chars, buffer);
+
+        return new String(chars);
+    }
+
+    static int mutf8FromCharsLength(char chars[]) {
+        int length = 0;
+
+        for (char ch : chars) {
+            int uch = ch & 0xFFFF;
+
+            if ((uch & ~0x7F) != 0) {
+                int mask = ~0x3F;
+                int n = 0;
+
+                do {
+                    n++;
+                    uch >>= 6;
+                    mask >>= 1;
+                } while ((uch & mask) != 0);
+
+                length += n + 1;
+            } else if (uch == 0) {
+                length += 2;
+            } else {
+                length++;
+            }
+        }
+
+        return length;
+    }
+
+    static void mutf8FromChars(byte[] bytes, int offset, char chars[]) {
+        int j = offset;
+        byte[] buffer = new byte[8];
+
+        for (char ch : chars) {
+            int uch = ch & 0xFFFF;
+
+            if ((uch & ~0x7F) != 0) {
+                int mask = ~0x3F;
+                int n = 0;
+
+                do {
+                    buffer[n++] = (byte)(0x80 | (uch & 0x3F));
+                    uch >>= 6;
+                    mask >>= 1;
+                } while ((uch & mask) != 0);
+
+                buffer[n] = (byte)((mask << 1) | uch);
+
+                do {
+                    bytes[j++] = buffer[n--];
+                } while (0 <= n);
+            } else if (uch == 0) {
+                bytes[j++] = (byte)0xC0;
+                bytes[j++] = (byte)0x80;
+            } else {
+                bytes[j++] = (byte)uch;
+            }
+        }
+    }
+
+    public static byte[] mutf8FromString(String string) {
+        char[] chars = string.toCharArray();
+        int length = mutf8FromCharsLength(chars);
+        byte[] bytes = new byte[length];
+        mutf8FromChars(bytes, 0, chars);
+
+        return bytes;
+    }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsWriter.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsWriter.java
deleted file mode 100644
index 9c00f66..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsWriter.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-
-class ImageStringsWriter implements ImageStrings {
-    private static final int NOT_FOUND = -1;
-    static final int EMPTY_OFFSET = 0;
-    static final UTF8String CLASS_STRING = new UTF8String("class");
-
-    private final HashMap<UTF8String, Integer> stringToOffsetMap;
-    private final ImageStream stream;
-
-    ImageStringsWriter() {
-        this.stringToOffsetMap = new HashMap<>();
-        this.stream = new ImageStream();
-
-        // Reserve 0 offset for empty string.
-        int offset = addString(UTF8String.EMPTY_STRING);
-        assert offset == 0 : "Empty string not zero offset";
-        // Reserve 1 offset for frequently used ".class".
-        addString(CLASS_STRING);
-    }
-
-    private int addString(final UTF8String string) {
-        int offset = stream.getPosition();
-        string.writeTo(stream);
-        stream.put('\0');
-        stringToOffsetMap.put(string, offset);
-
-        return offset;
-    }
-
-    @Override
-    public int add(final UTF8String string) {
-        int offset = find(string);
-
-        return offset == NOT_FOUND ? addString(string) : offset;
-    }
-
-    int find(final UTF8String string) {
-        Integer offset = stringToOffsetMap.get(string);
-
-        return offset != null ? offset : NOT_FOUND;
-    }
-
-    @Override
-    public UTF8String get(int offset) {
-        ByteBuffer buffer = stream.getBuffer();
-        assert 0 <= offset && offset < buffer.capacity() : "String buffer offset out of range";
-        int zero = NOT_FOUND;
-        for (int i = offset; i < buffer.capacity(); i++) {
-            if (buffer.get(i) == '\0') {
-                zero = i;
-                break;
-            }
-        }
-        assert zero != UTF8String.NOT_FOUND;
-        int length = zero - offset;
-        byte[] bytes = new byte[length];
-        int mark = buffer.position();
-        buffer.position(offset);
-        buffer.get(bytes);
-        buffer.position(mark);
-
-        return new UTF8String(bytes, 0, length);
-    }
-
-    ImageStream getStream() {
-        return stream;
-    }
-
-    int getSize() {
-        return stream.getSize();
-    }
-
-    int getCount() {
-        return stringToOffsetMap.size();
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageSubstrate.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageSubstrate.java
deleted file mode 100644
index 9d5b09d..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageSubstrate.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.Closeable;
-import java.nio.ByteBuffer;
-
-interface ImageSubstrate extends Closeable {
-    @Override
-    void close();
-    boolean supportsDataBuffer();
-    ByteBuffer getIndexBuffer(long offset, long size);
-    ByteBuffer getDataBuffer(long offset, long size);
-    boolean read(long offset,
-                          ByteBuffer compressedBuffer, long compressedSize,
-                          ByteBuffer uncompressedBuffer, long uncompressedSize);
-    boolean read(long offset,
-                          ByteBuffer uncompressedBuffer, long uncompressedSize);
-    byte[] getStringBytes(int offset);
-    long[] getAttributes(int offset);
-    ImageLocation findLocation(UTF8String name, ImageStringsReader strings);
-    int[] attributeOffsets();
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java
new file mode 100644
index 0000000..b379078
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/NativeImageBuffer.java
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * 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.jimage;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+class NativeImageBuffer {
+    static {
+        java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        System.loadLibrary("jimage");
+                        return null;
+                    }
+                });
+    }
+
+    native static ByteBuffer getNativeMap(String imagePath);
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/PerfectHashBuilder.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/PerfectHashBuilder.java
deleted file mode 100644
index c3ff39c..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/PerfectHashBuilder.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
-*/
-
-package jdk.internal.jimage;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class PerfectHashBuilder<E> {
-    private static final int RETRY_LIMIT = 1000;
-
-    private Class<?> entryComponent;
-    private Class<?> bucketComponent;
-
-    private final Map<UTF8String, Entry<E>> map = new LinkedHashMap<>();
-    private int[] redirect;
-    private Entry<E>[] order;
-    private int count = 0;
-
-    @SuppressWarnings("EqualsAndHashcode")
-    public static class Entry<E> {
-        private final UTF8String key;
-        private final E value;
-
-        Entry() {
-            this("", null);
-        }
-
-        Entry(String key, E value) {
-            this(new UTF8String(key), value);
-        }
-
-        Entry(UTF8String key, E value) {
-            this.key = key;
-            this.value = value;
-        }
-
-        UTF8String getKey() {
-            return key;
-        }
-
-        E getValue() {
-            return value;
-        }
-
-        int hashCode(int seed) {
-            return key.hashCode(seed);
-        }
-
-        @Override
-        public int hashCode() {
-            return key.hashCode();
-        }
-    }
-
-    static class Bucket<E> implements Comparable<Bucket<E>> {
-        final List<Entry<E>> list = new ArrayList<>();
-
-        void add(Entry<E> entry) {
-            list.add(entry);
-        }
-
-        int getSize() {
-            return list.size();
-        }
-
-        List<Entry<E>> getList() {
-            return list;
-        }
-
-        Entry<E> getFirst() {
-            assert !list.isEmpty() : "bucket should never be empty";
-            return list.get(0);
-        }
-
-        @Override
-        public int hashCode() {
-            return getFirst().hashCode();
-        }
-
-        @Override
-        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
-        public boolean equals(Object obj) {
-            return this == obj;
-        }
-
-        @Override
-        public int compareTo(Bucket<E> o) {
-            return o.getSize() - getSize();
-        }
-    }
-
-    public PerfectHashBuilder(Class<?> entryComponent, Class<?> bucketComponent) {
-        this.entryComponent = entryComponent;
-        this.bucketComponent = bucketComponent;
-    }
-
-    public int getCount() {
-        return map.size();
-    }
-
-    public int[] getRedirect() {
-        return redirect;
-    }
-
-    public Entry<E>[] getOrder() {
-        return order;
-    }
-
-    public Entry<E> put(String key, E value) {
-        return put(new UTF8String(key), value);
-    }
-
-    public Entry<E> put(UTF8String key, E value) {
-        return put(new Entry<>(key, value));
-    }
-
-    public Entry<E> put(Entry<E> entry) {
-        Entry<E> old = map.put(entry.key, entry);
-
-        if (old == null) {
-            count++;
-        }
-
-        return old;
-    }
-
-    @SuppressWarnings("unchecked")
-    public void generate() {
-        boolean redo = count != 0;
-        while (redo) {
-            redo = false;
-            redirect = new int[count];
-            order = (Entry<E>[])Array.newInstance(entryComponent, count);
-
-            Bucket<E>[] sorted = createBuckets();
-            int free = 0;
-
-            for (Bucket<E> bucket : sorted) {
-                if (bucket.getSize() != 1) {
-                    if (!collidedEntries(bucket, count)) {
-                        redo = true;
-                        break;
-                    }
-                } else {
-                    for ( ; free < count && order[free] != null; free++) {}
-
-                    if (free >= count) {
-                        redo = true;
-                        break;
-                    }
-
-                    order[free] = bucket.getFirst();
-                    redirect[bucket.hashCode() % count] = -1 - free;
-                    free++;
-                }
-            }
-
-            if (redo) {
-                count = (count + 1) | 1;
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private Bucket<E>[] createBuckets() {
-        Bucket<E>[] buckets = (Bucket<E>[])Array.newInstance(bucketComponent, count);
-
-        map.values().stream().forEach((entry) -> {
-            int index = entry.hashCode() % count;
-            Bucket<E> bucket = buckets[index];
-
-            if (bucket == null) {
-                buckets[index] = bucket = new Bucket<>();
-            }
-
-            bucket.add(entry);
-        });
-
-        Bucket<E>[] sorted = Arrays.asList(buckets).stream()
-                .filter((bucket) -> (bucket != null))
-                .sorted()
-                .toArray((length) -> {
-                    return (Bucket<E>[])Array.newInstance(bucketComponent, length);
-                });
-
-        return sorted;
-    }
-
-    private boolean collidedEntries(Bucket<E> bucket, int count) {
-        List<Integer> undo = new ArrayList<>();
-        int seed = UTF8String.HASH_MULTIPLIER + 1;
-        int retry = 0;
-
-        redo:
-        while (true) {
-            for (Entry<E> entry : bucket.getList()) {
-                int index = entry.hashCode(seed) % count;
-                if (order[index] != null) {
-                    if (++retry > RETRY_LIMIT) {
-                        return false;
-                    }
-
-                    undo.stream().forEach((i) -> {
-                        order[i] = null;
-                    });
-
-                    undo.clear();
-                    seed++;
-
-                    if (seed == 0) {
-                        seed = 1;
-                    }
-
-                    continue redo;
-                }
-
-                order[index] = entry;
-                undo.add(index);
-            }
-
-            redirect[bucket.hashCode() % count] = seed;
-
-            break;
-        }
-
-        return true;
-    }
- }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePool.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePool.java
deleted file mode 100644
index 89c1012..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePool.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import jdk.internal.jimage.decompressor.CompressedResourceHeader;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Pool of resources. This class contain the content of a jimage file in the
- * matter of Resource.
- */
-public interface ResourcePool {
-
-    /**
-     * Resources visitor
-     */
-    public interface Visitor {
-
-        /**
-         * Called for each visited Resource.
-         *
-         * @param resource The resource to deal with.
-         * @param order Byte order
-         * @param strings
-         * @return A resource or null if the passed resource is to be removed
-         * from the jimage.
-         * @throws Exception
-         */
-        public Resource visit(Resource resource, ByteOrder order,
-                StringTable strings) throws Exception;
-    }
-
-    /**
-     * A JImage Resource. Fully identified by its path.
-     */
-    public static class Resource {
-
-        private final String path;
-        private final ByteBuffer content;
-
-        private final String module;
-
-        public Resource(String path, ByteBuffer content) {
-            Objects.requireNonNull(path);
-            Objects.requireNonNull(content);
-            this.path = path;
-            this.content = content.asReadOnlyBuffer();
-            String[] split = ImageFileCreator.splitPath(path);
-            module = split[0];
-        }
-
-        public String getPath() {
-            return path;
-        }
-
-        public String getModule() {
-            return module;
-        }
-
-        /**
-         * The resource content.
-         *
-         * @return A read only buffer.
-         */
-        public ByteBuffer getContent() {
-            return content;
-        }
-
-        public int getLength() {
-            return content.limit();
-        }
-
-        public byte[] getByteArray() {
-            content.rewind();
-            byte[] array = new byte[content.remaining()];
-            content.get(array);
-            return array;
-        }
-
-        @Override
-        public String toString() {
-            return getPath();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof Resource)) {
-                return false;
-            }
-            Resource res = (Resource) obj;
-            return res.path.equals(path);
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 7;
-            hash = 53 * hash + Objects.hashCode(this.path);
-            return hash;
-        }
-    }
-
-    /**
-     * A resource that has been compressed.
-     */
-    public static final class CompressedResource extends Resource {
-
-        private final long uncompressed_size;
-
-        private CompressedResource(String path, ByteBuffer content,
-                long uncompressed_size) {
-            super(path, content);
-            this.uncompressed_size = uncompressed_size;
-        }
-
-        public long getUncompressedSize() {
-            return uncompressed_size;
-        }
-
-        public static CompressedResource newCompressedResource(Resource original,
-                ByteBuffer compressed,
-                String plugin, String pluginConfig, StringTable strings,
-                ByteOrder order) throws Exception {
-            Objects.requireNonNull(original);
-            Objects.requireNonNull(compressed);
-            Objects.requireNonNull(plugin);
-
-            boolean isTerminal = !(original instanceof CompressedResource);
-            long uncompressed_size = original.getLength();
-            if (original instanceof CompressedResource) {
-                CompressedResource comp = (CompressedResource) original;
-                uncompressed_size = comp.getUncompressedSize();
-            }
-            int nameOffset = strings.addString(plugin);
-            int configOffset = -1;
-            if (pluginConfig != null) {
-                configOffset = strings.addString(plugin);
-            }
-            CompressedResourceHeader rh =
-                    new CompressedResourceHeader(compressed.limit(), original.getLength(),
-                    nameOffset, configOffset, isTerminal);
-            // Merge header with content;
-            byte[] h = rh.getBytes(order);
-            ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
-            bb.order(order);
-            bb.put(h);
-            bb.put(compressed);
-            ByteBuffer contentWithHeader = ByteBuffer.wrap(bb.array());
-
-            CompressedResource compressedResource =
-                    new CompressedResource(original.getPath(),
-                    contentWithHeader, uncompressed_size);
-            return compressedResource;
-        }
-    }
-
-    /**
-     * Read only state.
-     *
-     * @return true if readonly false otherwise.
-     */
-    public boolean isReadOnly();
-
-    /**
-     * The byte order
-     *
-     * @return
-     */
-    public ByteOrder getByteOrder();
-
-    /**
-     * Add a resource.
-     *
-     * @param resource The Resource to add.
-     * @throws java.lang.Exception If the pool is read only.
-     */
-    public void addResource(Resource resource) throws Exception;
-
-    /**
-     * Check if a resource is contained in the pool.
-     *
-     * @param res The resource to check.
-     * @return true if res is contained, false otherwise.
-     */
-    public boolean contains(Resource res);
-
-    /**
-     * Get all resources contained in this pool instance.
-     *
-     * @return The collection of resources;
-     */
-    public Collection<Resource> getResources();
-
-    /**
-     * Get the resource for the passed path.
-     *
-     * @param path A resource path
-     * @return A Resource instance or null if the resource is not found
-     */
-    public Resource getResource(String path);
-
-    /**
-     * The Image modules. It is computed based on the resources contained by
-     * this ResourcePool instance.
-     *
-     * @return The Image Modules.
-     */
-    public Map<String, Set<String>> getModulePackages();
-
-    /**
-     * Check if this pool contains some resources.
-     *
-     * @return True if contains some resources.
-     */
-    public boolean isEmpty();
-
-    /**
-     * Visit the resources contained in this ResourcePool.
-     *
-     * @param visitor The visitor
-     * @param output The pool to store resources.
-     * @param strings
-     * @throws Exception
-     */
-    public void visit(Visitor visitor, ResourcePool output, StringTable strings)
-            throws Exception;
-
-    public void addTransformedResource(Resource original, ByteBuffer transformed)
-            throws Exception;
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePoolImpl.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePoolImpl.java
deleted file mode 100644
index b54ff09..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ResourcePoolImpl.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Pool of resources. This class contain the content of a jimage file in the
- * matter of Resource.
- */
-public class ResourcePoolImpl implements ResourcePool {
-
-    private final Map<String, Resource> resources = new LinkedHashMap<>();
-
-    private final ByteOrder order;
-    private boolean isReadOnly;
-
-    public ResourcePoolImpl(ByteOrder order) {
-        Objects.requireNonNull(order);
-        this.order = order;
-    }
-
-    /**
-     * Make this Resources instance read-only. No resource can be added.
-     */
-    public void setReadOnly() {
-        isReadOnly = true;
-    }
-
-    /**
-     * Read only state.
-     *
-     * @return true if readonly false otherwise.
-     */
-    @Override
-    public boolean isReadOnly() {
-        return isReadOnly;
-    }
-
-    /**
-     * The byte order
-     *
-     * @return
-     */
-    @Override
-    public ByteOrder getByteOrder() {
-        return order;
-    }
-
-    /**
-     * Add a resource.
-     *
-     * @param resource The Resource to add.
-     * @throws java.lang.Exception If the pool is read only.
-     */
-    @Override
-    public void addResource(Resource resource) throws Exception {
-        if (isReadOnly()) {
-            throw new Exception("pool is readonly");
-        }
-        Objects.requireNonNull(resource);
-        if (resources.get(resource.getPath()) != null) {
-            throw new Exception("Resource" + resource.getPath() +
-                    " already present");
-        }
-        resources.put(resource.getPath(), resource);
-    }
-
-    /**
-     * Check if a resource is contained in the pool.
-     *
-     * @param res The resource to check.
-     * @return true if res is contained, false otherwise.
-     */
-    @Override
-    public boolean contains(Resource res) {
-        Objects.requireNonNull(res);
-        try {
-            getResource(res.getPath());
-            return true;
-        } catch (Exception ex) {
-            return false;
-        }
-    }
-
-    /**
-     * Get all resources contained in this pool instance.
-     *
-     * @return The collection of resources;
-     */
-    @Override
-    public Collection<Resource> getResources() {
-        return Collections.unmodifiableCollection(resources.values());
-    }
-
-/**
-     * Get the resource for the passed path.
-     *
-     * @param path A resource path
-     * @return A Resource instance or null if the resource is not found
-     */
-    @Override
-    public Resource getResource(String path) {
-        Objects.requireNonNull(path);
-        return resources.get(path);
-    }
-
-    /**
-     * The Image modules. It is computed based on the resources contained by
-     * this ResourcePool instance.
-     *
-     * @return The Image Modules.
-     */
-    @Override
-    public Map<String, Set<String>> getModulePackages() {
-        Map<String, Set<String>> moduleToPackage = new LinkedHashMap<>();
-        retrieveModulesPackages(moduleToPackage);
-        return moduleToPackage;
-    }
-
-    /**
-     * Check if this pool contains some resources.
-     *
-     * @return True if contains some resources.
-     */
-    @Override
-    public boolean isEmpty() {
-        return resources.isEmpty();
-    }
-
-    /**
-     * Visit the resources contained in this ResourcePool.
-     *
-     * @param visitor The visitor
-     * @param strings
-     * @throws Exception
-     */
-    @Override
-    public void visit(Visitor visitor, ResourcePool output, StringTable strings)
-            throws Exception {
-        for (Resource resource : getResources()) {
-            Resource res = visitor.visit(resource, order, strings);
-            if (res != null) {
-                output.addResource(res);
-            }
-        }
-    }
-
-    @Override
-    public void addTransformedResource(Resource original, ByteBuffer transformed)
-            throws Exception {
-        if (isReadOnly()) {
-            throw new Exception("Pool is readonly");
-        }
-        Objects.requireNonNull(original);
-        Objects.requireNonNull(transformed);
-        if (resources.get(original.getPath()) != null) {
-            throw new Exception("Resource already present");
-        }
-        Resource res = new Resource(original.getPath(), transformed);
-        addResource(res);
-    }
-
-    private void retrieveModulesPackages(Map<String, Set<String>> moduleToPackage) {
-        for (Resource res : resources.values()) {
-            Set<String> pkgs = moduleToPackage.get(res.getModule());
-            if (pkgs == null) {
-                pkgs = new HashSet<>();
-                moduleToPackage.put(res.getModule(), pkgs);
-            }
-            // Module metadata only contains packages with resource files
-            if (ImageFileCreator.isResourcePackage(res.getPath())) {
-                String[] split = ImageFileCreator.splitPath(res.getPath());
-                String pkg = split[1];
-                if (pkg != null && !pkg.isEmpty()) {
-                    pkgs.add(pkg);
-                }
-            }
-        }
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/StringTable.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/StringTable.java
deleted file mode 100644
index a5f7967..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/StringTable.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-/**
-* Added strings are stored in the jimage strings table.
-*/
-public interface StringTable {
-    /**
-     * Add a string to the jimage strings table.
-     * @param str The string to add.
-     * @return a String identifier.
-     */
-    public int addString(String str);
-
-    /**
-     * Retrieve a string from the passed id.
-     * @param id The string id.
-     * @return The string referenced by the passed id.
-     */
-    public String getString(int id);
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/UTF8String.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/UTF8String.java
deleted file mode 100644
index 531c0ba..0000000
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/UTF8String.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jimage;
-
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-public final class UTF8String implements CharSequence {
-    // Same as StandardCharsets.UTF_8 without loading all of the standard charsets
-    static final Charset UTF_8 = Charset.forName("UTF-8");
-
-    static final int NOT_FOUND = -1;
-    static final int HASH_MULTIPLIER = 0x01000193;
-    static final UTF8String EMPTY_STRING = new UTF8String("");
-    static final UTF8String SLASH_STRING = new UTF8String("/");
-    static final UTF8String DOT_STRING = new UTF8String(".");
-
-    // TODO This strings are implementation specific and should be defined elsewhere.
-    static final UTF8String MODULES_STRING = new UTF8String("/modules");
-    static final UTF8String PACKAGES_STRING = new UTF8String("/packages");
-
-    final byte[] bytes;
-    final int offset;
-    final int count;
-    int hashcode;
-
-    public UTF8String(byte[] bytes, int offset, int count) {
-        if (offset < 0 || count < 0 || (offset + count) > bytes.length) {
-            throw new IndexOutOfBoundsException("offset/count out of range");
-        }
-        this.bytes = bytes;
-        this.offset = offset;
-        this.count = count;
-        this.hashcode = -1;
-    }
-
-    public UTF8String(byte[] bytes, int offset) {
-        this(bytes, offset, bytes.length - offset);
-    }
-
-    public UTF8String(byte[] bytes) {
-        this(bytes, 0, bytes.length);
-    }
-
-    public UTF8String(String string) {
-        this(stringToBytes(string));
-    }
-
-    @Override
-    public int length() {
-        return count;
-    }
-
-    public boolean isEmpty() {
-        return count == 0;
-    }
-
-    public int byteAt(int index) {
-        return bytes[offset + index] & 0xFF;
-    }
-
-    public UTF8String concat(UTF8String s) {
-        int total = count + s.count;
-        byte[] combined = new byte[total];
-        System.arraycopy(bytes, offset, combined, 0, count);
-        System.arraycopy(s.bytes, s.offset, combined, count, s.count);
-
-        return new UTF8String(combined, 0, total);
-    }
-
-    public UTF8String concat(UTF8String... s) {
-        int total = count;
-
-        for (UTF8String i : s) {
-            total += i.count;
-        }
-
-        byte[] combined = new byte[total];
-        System.arraycopy(bytes, offset, combined, 0, count);
-        int next = count;
-
-        for (UTF8String i : s) {
-            System.arraycopy(i.bytes, i.offset, combined, next, i.count);
-            next += i.count;
-        }
-
-        return new UTF8String(combined, 0, total);
-    }
-
-    public UTF8String substring(int offset) {
-        return substring(offset, this.count - offset);
-    }
-
-    public UTF8String substring(int offset, int count) {
-        int newOffset = this.offset + offset;
-        return new UTF8String(bytes, newOffset, count);
-    }
-
-    public UTF8String trimToSize() {
-        return offset == 0 && bytes.length == count ? this :
-               new UTF8String(Arrays.copyOfRange(bytes, offset, offset + count));
-    }
-
-    public int indexOf(int ch) {
-        return indexOf(ch, 0);
-    }
-
-    public int indexOf(int ch, int start) {
-        for (int i = Math.max(start, 0); i < count; i++) {
-            if (byteAt(i) == ch) {
-                return i;
-            }
-        }
-
-        return NOT_FOUND;
-    }
-
-    public int lastIndexOf(int ch) {
-        return lastIndexOf(ch, count - 1);
-    }
-
-    public int lastIndexOf(int ch, int start) {
-        for (int i = Math.min(start, count); i > 0; i--) {
-            if (byteAt(i) == ch) {
-                return i;
-            }
-        }
-
-        return NOT_FOUND;
-    }
-
-    void writeTo(ImageStream buffer) {
-        buffer.put(bytes, offset, count);
-    }
-
-    static int hashCode(int seed, byte[] bytes, int offset, int count) {
-        for (int i = offset, limit = offset + count; i < limit; i++) {
-            seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
-        }
-
-        return seed & 0x7FFFFFFF;
-    }
-
-    int hashCode(int seed) {
-        return hashCode(seed, bytes, offset, count);
-    }
-
-    @Override
-    public int hashCode() {
-        if (hashcode < 0) {
-            hashcode = hashCode(HASH_MULTIPLIER, bytes, offset, count);
-        }
-
-        return hashcode;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-
-        return equals(this, (UTF8String)obj);
-    }
-
-    public static boolean equals(UTF8String a, UTF8String b) {
-        if (a == b) {
-            return true;
-        }
-
-        int count = a.count;
-
-        if (count != b.count) {
-            return false;
-        }
-
-        byte[] aBytes = a.bytes;
-        byte[] bBytes = b.bytes;
-        int aOffset = a.offset;
-        int bOffset = b.offset;
-
-        for (int i = 0; i < count; i++) {
-            if (aBytes[aOffset + i] != bBytes[bOffset + i]) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public byte[] getBytesCopy() {
-        return Arrays.copyOfRange(bytes, offset, offset + count);
-    }
-
-    byte[] getBytes() {
-        if (offset != 0 || bytes.length != count) {
-            return Arrays.copyOfRange(bytes, offset, offset + count);
-        }
-
-        return bytes;
-    }
-
-    private static byte[] stringToBytes(String string) {
-        return string.getBytes(UTF_8);
-    }
-
-    @Override
-    public String toString() {
-        return new String(bytes, offset, count, UTF_8);
-    }
-
-    @Override
-    public char charAt(int index) {
-        int ch = byteAt(index);
-
-        return (ch & 0x80) == 0 ? (char)ch : '\0';
-    }
-
-    @Override
-    public CharSequence subSequence(int start, int end) {
-        return (CharSequence)substring(start, end - start);
-    }
-}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressIndexes.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressIndexes.java
new file mode 100644
index 0000000..bcc9513
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressIndexes.java
@@ -0,0 +1,148 @@
+/*
+ * 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
+ * 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.jimage.decompressor;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Index compressor. Use the minimal amount of bytes required to store
+ * an integer.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class CompressIndexes {
+    private static final int INTEGER_SIZE = 4;
+
+    public static List<Integer> decompressFlow(byte[] values) {
+        List<Integer> lst = new ArrayList<>();
+        for (int i = 0; i < values.length;) {
+            byte b = values[i];
+            int length = isCompressed(b) ? getLength(b) : INTEGER_SIZE;
+            int decompressed = decompress(values, i);
+            lst.add(decompressed);
+            i += length;
+        }
+        return lst;
+    }
+
+    public static int readInt(DataInputStream cr) throws IOException {
+        byte[] b = new byte[1];
+        cr.readFully(b);
+        byte firstByte = b[0];
+        boolean compressed = CompressIndexes.isCompressed(firstByte);
+        int toRead = 4;
+        if(compressed) {
+            toRead = CompressIndexes.getLength(firstByte);
+        }
+        byte[] content = new byte[toRead-1];
+        cr.readFully(content);
+        ByteBuffer bb = ByteBuffer.allocate(content.length+1);
+        bb.put(firstByte);
+        bb.put(content);
+        int index = CompressIndexes.decompress(bb.array(), 0);
+        return index;
+    }
+
+    public static int getLength(byte b) {
+        return ((byte) (b & 0x60) >> 5);
+    }
+
+    public static boolean isCompressed(byte b) {
+        return b < 0;
+    }
+
+    public static int decompress(byte[] value, int offset) {
+        byte b1 = value[offset];
+        ByteBuffer buffer = ByteBuffer.allocate(INTEGER_SIZE);
+        if (isCompressed(b1)) { // compressed
+            int length = getLength(b1);
+            byte clearedValue = (byte) (b1 & 0x1F);
+
+            int start = INTEGER_SIZE - length;
+            buffer.put(start, clearedValue);
+            for (int i = offset + 1; i < offset + length; i++) {
+                buffer.put(++start, value[i]);
+            }
+        } else {
+            buffer.put(value, offset, INTEGER_SIZE);
+        }
+        return buffer.getInt(0);
+    }
+
+    public static byte[] compress(int val) {
+        ByteBuffer result = ByteBuffer.allocate(4).putInt(val);
+        byte[] array = result.array();
+
+        if ((val & 0xFF000000) == 0) { // nothing on 4th
+            if ((val & 0x00FF0000) == 0) { // nothing on 3rd
+                if ((val & 0x0000FF00) == 0) { // nothing on 2nd
+                    if ((val & 0x000000E0) == 0) { // only in 1st, encode length in the byte.
+                        //sign bit and size 1 ==> 101X
+                        result = ByteBuffer.allocate(1);
+                        result.put((byte) (0xA0 | array[3]));
+                    } else { // add a byte for size
+                        //sign bit and size 2 ==> 110X
+                        result = ByteBuffer.allocate(2);
+                        result.put((byte) 0xC0);
+                        result.put(array[3]);
+                    }
+                } else { // content in 2nd
+                    if ((val & 0x0000E000) == 0) {// encode length in the byte.
+                        //sign bit and size 2 ==> 110X
+                        result = ByteBuffer.allocate(2);
+                        result.put((byte) (0xC0 | array[2]));
+                        result.put(array[3]);
+                    } else { // add a byte for size
+                        //sign bit and size 3 ==> 111X
+                        result = ByteBuffer.allocate(3);
+                        result.put((byte) 0xE0);
+                        result.put(array[2]);
+                        result.put(array[3]);
+                    }
+                }
+            } else {// content in 3rd
+                if ((val & 0x00E00000) == 0) {// encode length in the byte.
+                    //sign bit and size 3 ==> 111X
+                    result = ByteBuffer.allocate(3);
+                    result.put((byte) (0xE0 | array[1]));
+                    result.put(array[2]);
+                    result.put(array[3]);
+                } else { // add a byte, useless
+                    //
+                }
+            }
+        }
+        return result.array();
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressedResourceHeader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressedResourceHeader.java
index 66afd33..006e754 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressedResourceHeader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/CompressedResourceHeader.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
@@ -34,19 +34,25 @@
  * A resource header for compressed resource. This class is handled internally,
  * you don't have to add header to the resource, headers are added automatically
  * for compressed resources.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public final class CompressedResourceHeader {
 
-    private static final int SIZE = 21;
+    private static final int SIZE = 29;
     public static final int MAGIC = 0xCAFEFAFA;
-    private final int uncompressedSize;
-    private final int compressedSize;
+    private final long uncompressedSize;
+    private final long compressedSize;
     private final int decompressorNameOffset;
     private final int contentOffset;
     private final boolean isTerminal;
 
-    public CompressedResourceHeader(int compressedSize,
-            int uncompressedSize, int decompressorNameOffset, int contentOffset,
+    public CompressedResourceHeader(long compressedSize,
+            long uncompressedSize, int decompressorNameOffset, int contentOffset,
             boolean isTerminal) {
         this.compressedSize = compressedSize;
         this.uncompressedSize = uncompressedSize;
@@ -68,18 +74,18 @@
     }
 
     public String getStoredContent(StringsProvider provider) {
-        Objects.nonNull(provider);
+        Objects.requireNonNull(provider);
         if(contentOffset == -1) {
             return null;
         }
         return provider.getString(contentOffset);
     }
 
-    public int getUncompressedSize() {
+    public long getUncompressedSize() {
         return uncompressedSize;
     }
 
-    public int getResourceSize() {
+    public long getResourceSize() {
         return compressedSize;
     }
 
@@ -88,8 +94,8 @@
         ByteBuffer buffer = ByteBuffer.allocate(SIZE);
         buffer.order(order);
         buffer.putInt(MAGIC);
-        buffer.putInt(compressedSize);
-        buffer.putInt(uncompressedSize);
+        buffer.putLong(compressedSize);
+        buffer.putLong(uncompressedSize);
         buffer.putInt(decompressorNameOffset);
         buffer.putInt(contentOffset);
         buffer.put(isTerminal ? (byte)1 : (byte)0);
@@ -113,8 +119,8 @@
         if(magic != MAGIC) {
             return null;
         }
-        int size = buffer.getInt();
-        int uncompressedSize = buffer.getInt();
+        long size = buffer.getLong();
+        long uncompressedSize = buffer.getLong();
         int decompressorNameOffset = buffer.getInt();
         int contentIndex = buffer.getInt();
         byte isTerminal = buffer.get();
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/Decompressor.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/Decompressor.java
index 0c640e0..3fb934c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/Decompressor.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/Decompressor.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,6 +27,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -35,6 +36,12 @@
 
 /**
  * Entry point to decompress resources.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public final class Decompressor {
 
@@ -71,8 +78,9 @@
                     String storedContent = header.getStoredContent(provider);
                     Properties props = new Properties();
                     if (storedContent != null) {
-                        try (ByteArrayInputStream stream =
-                                new ByteArrayInputStream(storedContent.getBytes());) {
+                        try (ByteArrayInputStream stream
+                                = new ByteArrayInputStream(storedContent.
+                                        getBytes(StandardCharsets.UTF_8));) {
                             props.loadFromXML(stream);
                         }
                     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressor.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressor.java
index 1e1e99e..3e4e32d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressor.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressor.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,13 @@
 
 /**
  *
- * JImage Decompressor.
+ * JLink Image Decompressor.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public interface ResourceDecompressor {
 
@@ -49,5 +55,5 @@
      * @throws Exception
      */
     public byte[] decompress(StringsProvider strings, byte[] content, int offset,
-            int originalSize) throws Exception;
+            long originalSize) throws Exception;
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorFactory.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorFactory.java
index 4a517a0..77b0cd4 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorFactory.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorFactory.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
@@ -29,18 +29,19 @@
 
 /**
  *
- * JImage Resource Decompressor factory
+ * JLink Resource Decompressor factory
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public abstract class ResourceDecompressorFactory {
     private final String name;
-    private final String description;
-    private final String arguments;
 
-    protected ResourceDecompressorFactory(String name, String description,
-            String arguments) {
+    protected ResourceDecompressorFactory(String name) {
         this.name = name;
-        this.description = description;
-        this.arguments = arguments;
     }
 
     /**
@@ -52,22 +53,6 @@
     }
 
     /**
-     * The Factory description.
-     * @return The description.
-     */
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * The Factory arguments description.
-     * @return The arguments description.
-     */
-    public String getArgumentsDescription() {
-        return arguments;
-    }
-
-    /**
      * To build a new decompressor.
      * @param properties Contains configuration.
      * @return A new decompressor.
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorRepository.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorRepository.java
index 9080035..a07c7fd 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorRepository.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ResourceDecompressorRepository.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
@@ -31,8 +31,14 @@
 
 /**
  *
- * JImage Decompressors. All decompressors must be registered in the static
+ * JLink Decompressors. All decompressors must be registered in the static
  * initializer of this class.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public final class ResourceDecompressorRepository {
 
@@ -43,6 +49,7 @@
 
     static {
         registerReaderProvider(new ZipDecompressorFactory());
+        registerReaderProvider(new StringSharingDecompressorFactory());
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/SignatureParser.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/SignatureParser.java
new file mode 100644
index 0000000..a9a1df2
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/SignatureParser.java
@@ -0,0 +1,129 @@
+/*
+ * 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 jdk.internal.jimage.decompressor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * A descriptor parser used to extract java type strings from
+ * UTF_8 descriptors.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class SignatureParser {
+
+   public static class ParseResult {
+
+        public final List<String> types = new ArrayList<>();
+        public String formatted;
+        private ParseResult() {}
+    }
+
+    private SignatureParser() {}
+
+    public static String reconstruct(String formatted, List<String> arguments) {
+        int arg_index = 0;
+        char[] chars = formatted.toCharArray();
+        StringBuilder out = new StringBuilder();
+
+        for (int i = 0; i < chars.length; i++) {
+            char c = chars[i];
+            out.append(c);
+            switch (c) {
+                case 'L': {
+                    String pkg = arguments.get(arg_index);
+                    if(pkg.length() > 0) {
+                        out.append(pkg).append("/");
+                    }
+                    arg_index+=1;
+                    out.append(arguments.get(arg_index));
+                    arg_index+=1;
+                    break;
+                }
+                default: {
+                    break;
+                }
+            }
+        }
+        return out.toString();
+    }
+
+    public static ParseResult parseSignatureDescriptor(String str) {
+        ParseResult res = new ParseResult();
+        char[] chars = str.toCharArray();
+        StringBuilder type = null;
+        StringBuilder formatted = new StringBuilder();
+        for (int i = 0; i < chars.length; i++) {
+            char c = chars[i];
+            switch (c) {
+                case ';':
+                case ':':
+                case '<': {
+                    if(type != null) {
+                        String fullName = type.toString();
+                        int endIndex = fullName.lastIndexOf("/");
+                        String clazz = fullName;
+                        String pkg = "";
+                        if(endIndex != -1) {
+                            pkg = fullName.substring(0, endIndex);
+                            clazz = fullName.substring(endIndex+1);
+                        }
+                        res.types.add(pkg);
+                        res.types.add(clazz);
+                    }
+                    formatted.append(c);
+
+                    type = null;
+                    break;
+                }
+                case 'L': {
+                    if(type == null) {
+                        type = new StringBuilder();
+                        formatted.append(c);
+                    } else {
+                        type.append(c);
+                    }
+                    break;
+                }
+                default: {
+                    if(type == null) {
+                        formatted.append(c);
+                    } else {
+                        type.append(c);
+                    }
+                    break;
+                }
+            }
+        }
+        res.formatted = formatted.toString();
+        return res;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java
new file mode 100644
index 0000000..d979f98
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressor.java
@@ -0,0 +1,236 @@
+/*
+ * 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 jdk.internal.jimage.decompressor;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ *
+ * A Decompressor that reconstructs the constant pool of classes.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class StringSharingDecompressor implements ResourceDecompressor {
+
+    public static final int EXTERNALIZED_STRING = 23;
+    public static final int EXTERNALIZED_STRING_DESCRIPTOR = 25;
+
+    private static final int CONSTANT_Utf8 = 1;
+    private static final int CONSTANT_Integer = 3;
+    private static final int CONSTANT_Float = 4;
+    private static final int CONSTANT_Long = 5;
+    private static final int CONSTANT_Double = 6;
+    private static final int CONSTANT_Class = 7;
+    private static final int CONSTANT_String = 8;
+    private static final int CONSTANT_Fieldref = 9;
+    private static final int CONSTANT_Methodref = 10;
+    private static final int CONSTANT_InterfaceMethodref = 11;
+    private static final int CONSTANT_NameAndType = 12;
+    private static final int CONSTANT_MethodHandle = 15;
+    private static final int CONSTANT_MethodType = 16;
+    private static final int CONSTANT_InvokeDynamic = 18;
+
+    private static final int[] SIZES = new int[20];
+
+    static {
+
+        //SIZES[CONSTANT_Utf8] = XXX;
+        SIZES[CONSTANT_Integer] = 4;
+        SIZES[CONSTANT_Float] = 4;
+        SIZES[CONSTANT_Long] = 8;
+        SIZES[CONSTANT_Double] = 8;
+        SIZES[CONSTANT_Class] = 2;
+        SIZES[CONSTANT_String] = 2;
+        SIZES[CONSTANT_Fieldref] = 4;
+        SIZES[CONSTANT_Methodref] = 4;
+        SIZES[CONSTANT_InterfaceMethodref] = 4;
+        SIZES[CONSTANT_NameAndType] = 4;
+        SIZES[CONSTANT_MethodHandle] = 3;
+        SIZES[CONSTANT_MethodType] = 2;
+        SIZES[CONSTANT_InvokeDynamic] = 4;
+    }
+
+    public static int[] getSizes() {
+        return SIZES.clone();
+    }
+
+    @SuppressWarnings("fallthrough")
+    public static byte[] normalize(StringsProvider provider, byte[] transformed,
+            int offset) throws IOException {
+        DataInputStream stream = new DataInputStream(new ByteArrayInputStream(transformed,
+                offset, transformed.length - offset));
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream(transformed.length);
+        DataOutputStream out = new DataOutputStream(outStream);
+        byte[] header = new byte[8]; //maginc/4, minor/2, major/2
+        stream.readFully(header);
+        out.write(header);
+        int count = stream.readUnsignedShort();
+        out.writeShort(count);
+        for (int i = 1; i < count; i++) {
+            int tag = stream.readUnsignedByte();
+            byte[] arr;
+            switch (tag) {
+                case CONSTANT_Utf8: {
+                    out.write(tag);
+                    String utf = stream.readUTF();
+                    out.writeUTF(utf);
+                    break;
+                }
+
+                case EXTERNALIZED_STRING: {
+                    int index = CompressIndexes.readInt(stream);
+                    String orig = provider.getString(index);
+                    out.write(CONSTANT_Utf8);
+                    out.writeUTF(orig);
+                    break;
+                }
+
+                case EXTERNALIZED_STRING_DESCRIPTOR: {
+                    String orig = reconstruct(provider, stream);
+                    out.write(CONSTANT_Utf8);
+                    out.writeUTF(orig);
+                    break;
+                }
+                case CONSTANT_Long:
+                case CONSTANT_Double: {
+                    i++;
+                }
+                default: {
+                    out.write(tag);
+                    int size = SIZES[tag];
+                    arr = new byte[size];
+                    stream.readFully(arr);
+                    out.write(arr);
+                }
+            }
+        }
+        out.write(transformed, transformed.length - stream.available(),
+                stream.available());
+        out.flush();
+
+        return outStream.toByteArray();
+    }
+
+    private static String reconstruct(StringsProvider reader, DataInputStream cr)
+            throws IOException {
+        int descIndex = CompressIndexes.readInt(cr);
+        String desc = reader.getString(descIndex);
+        byte[] encodedDesc = getEncoded(desc);
+        int indexes_length = CompressIndexes.readInt(cr);
+        byte[] bytes = new byte[indexes_length];
+        cr.readFully(bytes);
+        List<Integer> indices = CompressIndexes.decompressFlow(bytes);
+        ByteBuffer buffer = ByteBuffer.allocate(encodedDesc.length * 2);
+        buffer.order(ByteOrder.BIG_ENDIAN);
+        int argIndex = 0;
+        for (byte c : encodedDesc) {
+            if (c == 'L') {
+                buffer = safeAdd(buffer, c);
+                int index = indices.get(argIndex);
+                argIndex += 1;
+                String pkg = reader.getString(index);
+                if (pkg.length() > 0) {
+                    pkg = pkg + "/";
+                    byte[] encoded = getEncoded(pkg);
+                    buffer = safeAdd(buffer, encoded);
+                }
+                int classIndex = indices.get(argIndex);
+                argIndex += 1;
+                String clazz = reader.getString(classIndex);
+                byte[] encoded = getEncoded(clazz);
+                buffer = safeAdd(buffer, encoded);
+            } else {
+                buffer = safeAdd(buffer, c);
+            }
+        }
+
+        byte[] encoded = buffer.array();
+        ByteBuffer result = ByteBuffer.allocate(encoded.length + 2);
+        result.order(ByteOrder.BIG_ENDIAN);
+        result.putShort((short) buffer.position());
+        result.put(encoded, 0, buffer.position());
+        ByteArrayInputStream stream = new ByteArrayInputStream(result.array());
+        DataInputStream inStream = new DataInputStream(stream);
+        String str = inStream.readUTF();
+        return str;
+    }
+
+    public static byte[] getEncoded(String pre) throws IOException {
+        ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
+        DataOutputStream resultOut = new DataOutputStream(resultStream);
+        resultOut.writeUTF(pre);
+        byte[] content = resultStream.toByteArray();
+        // first 2 items are length;
+        if (content.length <= 2) {
+            return new byte[0];
+        }
+        return Arrays.copyOfRange(content, 2, content.length);
+    }
+
+    private static ByteBuffer safeAdd(ByteBuffer current, byte b) {
+        byte[] bytes = {b};
+        return safeAdd(current, bytes);
+    }
+
+    private static ByteBuffer safeAdd(ByteBuffer current, byte[] bytes) {
+        if (current.remaining() < bytes.length) {
+            ByteBuffer newBuffer = ByteBuffer.allocate((current.capacity()
+                    + bytes.length) * 2);
+            newBuffer.order(ByteOrder.BIG_ENDIAN);
+            newBuffer.put(current.array(), 0, current.position());
+            current = newBuffer;
+        }
+        current.put(bytes);
+        return current;
+    }
+
+    @Override
+    public String getName() {
+        return StringSharingDecompressorFactory.NAME;
+    }
+
+    public StringSharingDecompressor(Properties properties) {
+
+    }
+
+    @Override
+    public byte[] decompress(StringsProvider reader, byte[] content,
+            int offset, long originalSize) throws Exception {
+        return normalize(reader, content, offset);
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressorFactory.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressorFactory.java
new file mode 100644
index 0000000..654a8d6
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/StringSharingDecompressorFactory.java
@@ -0,0 +1,52 @@
+/*
+ * 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 jdk.internal.jimage.decompressor;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ *
+ * Constant Pool strings sharing Decompressor factory.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public class StringSharingDecompressorFactory extends ResourceDecompressorFactory {
+
+    public static final String NAME = "compact-cp";
+    public StringSharingDecompressorFactory() {
+        super(NAME);
+    }
+
+    @Override
+    public ResourceDecompressor newDecompressor(Properties properties)
+            throws IOException {
+        return new StringSharingDecompressor(properties);
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressor.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressor.java
index 18aeb9e..7f8f3fc 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressor.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressor.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
@@ -25,13 +25,17 @@
 package jdk.internal.jimage.decompressor;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.zip.DataFormatException;
 import java.util.zip.Inflater;
 
 /**
  *
  * ZIP Decompressor
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 final class ZipDecompressor implements ResourceDecompressor {
 
@@ -40,29 +44,18 @@
         return ZipDecompressorFactory.NAME;
     }
 
-    static byte[] decompress(byte[] bytesIn, int offset) {
+    static byte[] decompress(byte[] bytesIn, int offset) throws Exception {
         Inflater inflater = new Inflater();
         inflater.setInput(bytesIn, offset, bytesIn.length - offset);
         ByteArrayOutputStream stream = new ByteArrayOutputStream(bytesIn.length - offset);
         byte[] buffer = new byte[1024];
 
         while (!inflater.finished()) {
-            int count;
-
-            try {
-                count = inflater.inflate(buffer);
-            } catch (DataFormatException ex) {
-                return null;
-            }
-
+            int count = inflater.inflate(buffer);
             stream.write(buffer, 0, count);
         }
 
-        try {
-            stream.close();
-        } catch (IOException ex) {
-            return null;
-        }
+        stream.close();
 
         byte[] bytesOut = stream.toByteArray();
         inflater.end();
@@ -72,7 +65,7 @@
 
     @Override
     public byte[] decompress(StringsProvider reader, byte[] content, int offset,
-            int originalSize) throws Exception {
+            long originalSize) throws Exception {
         byte[] decompressed = decompress(content, offset);
         return decompressed;
     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressorFactory.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressorFactory.java
index cbdbcc6..eb822e0 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressorFactory.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/decompressor/ZipDecompressorFactory.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
@@ -30,11 +30,17 @@
 /**
  *
  * ZIP decompressor factory
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
 public final class ZipDecompressorFactory extends ResourceDecompressorFactory {
     public static final String NAME = "zip";
     public ZipDecompressorFactory() {
-        super(NAME, "ZIP Decompression", null);
+        super(NAME);
     }
 
     @Override
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileAttributes.java
new file mode 100644
index 0000000..ab7bd29
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileAttributes.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Formatter;
+
+/**
+ * Base class for file attributes supported by jrt file systems.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+public abstract class AbstractJrtFileAttributes implements BasicFileAttributes {
+
+    // jrt fs specific attributes
+    /**
+     * Compressed resource file. If not available or not applicable, 0L is
+     * returned.
+     *
+     * @return the compressed resource size for compressed resources.
+     */
+    public abstract long compressedSize();
+
+    /**
+     * "file" extension of a file resource.
+     *
+     * @return extension string for the file resource
+     */
+    public abstract String extension();
+
+    @Override
+    public final String toString() {
+        StringBuilder sb = new StringBuilder(1024);
+        try (Formatter fm = new Formatter(sb)) {
+            if (creationTime() != null) {
+                fm.format("    creationTime    : %tc%n", creationTime().toMillis());
+            } else {
+                fm.format("    creationTime    : null%n");
+            }
+
+            if (lastAccessTime() != null) {
+                fm.format("    lastAccessTime  : %tc%n", lastAccessTime().toMillis());
+            } else {
+                fm.format("    lastAccessTime  : null%n");
+            }
+            fm.format("    lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
+            fm.format("    isRegularFile   : %b%n", isRegularFile());
+            fm.format("    isDirectory     : %b%n", isDirectory());
+            fm.format("    isSymbolicLink  : %b%n", isSymbolicLink());
+            fm.format("    isOther         : %b%n", isOther());
+            fm.format("    fileKey         : %s%n", fileKey());
+            fm.format("    size            : %d%n", size());
+            fm.format("    compressedSize  : %d%n", compressedSize());
+            fm.format("    extension       : %s%n", extension());
+        }
+        return sb.toString();
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java
new file mode 100644
index 0000000..42004e6
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtFileSystem.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.file.ClosedFileSystemException;
+import java.nio.file.CopyOption;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.ReadOnlyFileSystemException;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * Base class for jrt file systems. jrt filesystem implementations are currently
+ * available on top of .jimage file and on top "exploded" build directories.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+abstract class AbstractJrtFileSystem extends FileSystem {
+
+    private final JrtFileSystemProvider provider;
+
+    AbstractJrtFileSystem(JrtFileSystemProvider provider, Map<String, ?> options) {
+        this.provider = provider;
+    }
+
+    private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+    // static utility methods
+    static ReadOnlyFileSystemException readOnly() {
+        return new ReadOnlyFileSystemException();
+    }
+
+    // if a Path does not exist, throw exception
+    static void checkExists(Path path) {
+        if (Files.notExists(path)) {
+            throw new FileSystemNotFoundException(path.toString());
+        }
+    }
+
+    static byte[] getBytes(String name) {
+        return name.getBytes(UTF_8);
+    }
+
+    static String getString(byte[] name) {
+        return new String(name, UTF_8);
+    }
+
+    // do the supplied options imply that we have to chase symlinks?
+    static boolean followLinks(LinkOption... options) {
+        if (options != null) {
+            for (LinkOption lo : options) {
+                if (lo == LinkOption.NOFOLLOW_LINKS) {
+                    return false;
+                } else if (lo == null) {
+                    throw new NullPointerException();
+                } else {
+                    throw new AssertionError("should not reach here");
+                }
+            }
+        }
+        return true;
+    }
+
+    // check that the options passed are supported by (read-only) jrt file system
+    static void checkOptions(Set<? extends OpenOption> options) {
+        // check for options of null type and option is an intance of StandardOpenOption
+        for (OpenOption option : options) {
+            if (option == null) {
+                throw new NullPointerException();
+            }
+            if (!(option instanceof StandardOpenOption)) {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        if (options.contains(StandardOpenOption.WRITE)
+                || options.contains(StandardOpenOption.APPEND)) {
+            throw readOnly();
+        }
+    }
+
+    // FileSystem method implementations
+    @Override
+    public FileSystemProvider provider() {
+        return provider;
+    }
+
+    @Override
+    public Iterable<Path> getRootDirectories() {
+        ArrayList<Path> pathArr = new ArrayList<>();
+        pathArr.add(getRootPath());
+        return pathArr;
+    }
+
+    @Override
+    public AbstractJrtPath getPath(String first, String... more) {
+        String path;
+        if (more.length == 0) {
+            path = first;
+        } else {
+            StringBuilder sb = new StringBuilder();
+            sb.append(first);
+            for (String segment : more) {
+                if (segment.length() > 0) {
+                    if (sb.length() > 0) {
+                        sb.append('/');
+                    }
+                    sb.append(segment);
+                }
+            }
+            path = sb.toString();
+        }
+        return getRootPath().newJrtPath(getBytes(path));
+    }
+
+    @Override
+    public final boolean isReadOnly() {
+        return true;
+    }
+
+    @Override
+    public final UserPrincipalLookupService getUserPrincipalLookupService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final WatchService newWatchService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final Iterable<FileStore> getFileStores() {
+        ArrayList<FileStore> list = new ArrayList<>(1);
+        list.add(getFileStore(getRootPath()));
+        return list;
+    }
+
+    private static final Set<String> supportedFileAttributeViews
+            = Collections.unmodifiableSet(
+                    new HashSet<String>(Arrays.asList("basic", "jrt")));
+
+    @Override
+    public final Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+    @Override
+    public final String toString() {
+        return "jrt:/";
+    }
+
+    @Override
+    public final String getSeparator() {
+        return "/";
+    }
+
+    private static final String GLOB_SYNTAX = "glob";
+    private static final String REGEX_SYNTAX = "regex";
+
+    @Override
+    public PathMatcher getPathMatcher(String syntaxAndInput) {
+        int pos = syntaxAndInput.indexOf(':');
+        if (pos <= 0 || pos == syntaxAndInput.length()) {
+            throw new IllegalArgumentException();
+        }
+        String syntax = syntaxAndInput.substring(0, pos);
+        String input = syntaxAndInput.substring(pos + 1);
+        String expr;
+        if (syntax.equalsIgnoreCase(GLOB_SYNTAX)) {
+            expr = JrtUtils.toRegexPattern(input);
+        } else {
+            if (syntax.equalsIgnoreCase(REGEX_SYNTAX)) {
+                expr = input;
+            } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax
+                        + "' not recognized");
+            }
+        }
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return (Path path) -> pattern.matcher(path.toString()).matches();
+    }
+
+    // These methods throw read only file system exception
+    final void setTimes(AbstractJrtPath jrtPath, FileTime mtime, FileTime atime, FileTime ctime)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final void createDirectory(AbstractJrtPath jrtPath, FileAttribute<?>... attrs) throws IOException {
+        throw readOnly();
+    }
+
+    final void deleteFile(AbstractJrtPath jrtPath, boolean failIfNotExists)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final OutputStream newOutputStream(AbstractJrtPath jrtPath, OpenOption... options)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final void copyFile(boolean deletesrc, AbstractJrtPath srcPath, AbstractJrtPath dstPath, CopyOption... options)
+            throws IOException {
+        throw readOnly();
+    }
+
+    final FileChannel newFileChannel(AbstractJrtPath jrtPath,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        throw new UnsupportedOperationException("newFileChannel");
+    }
+
+    final InputStream newInputStream(AbstractJrtPath jrtPath) throws IOException {
+        return new ByteArrayInputStream(getFileContent(jrtPath));
+    }
+
+    final SeekableByteChannel newByteChannel(AbstractJrtPath jrtPath,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        checkOptions(options);
+
+        byte[] buf = getFileContent(jrtPath);
+        final ReadableByteChannel rbc
+                = Channels.newChannel(new ByteArrayInputStream(buf));
+        final long size = buf.length;
+        return new SeekableByteChannel() {
+            long read = 0;
+
+            @Override
+            public boolean isOpen() {
+                return rbc.isOpen();
+            }
+
+            @Override
+            public long position() throws IOException {
+                return read;
+            }
+
+            @Override
+            public SeekableByteChannel position(long pos)
+                    throws IOException {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                int n = rbc.read(dst);
+                if (n > 0) {
+                    read += n;
+                }
+                return n;
+            }
+
+            @Override
+            public SeekableByteChannel truncate(long size)
+                    throws IOException {
+                throw new NonWritableChannelException();
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                throw new NonWritableChannelException();
+            }
+
+            @Override
+            public long size() throws IOException {
+                return size;
+            }
+
+            @Override
+            public void close() throws IOException {
+                rbc.close();
+            }
+        };
+    }
+
+    final JrtFileStore getFileStore(AbstractJrtPath jrtPath) {
+        return new JrtFileStore(jrtPath);
+    }
+
+    final void ensureOpen() throws IOException {
+        if (!isOpen()) {
+            throw new ClosedFileSystemException();
+        }
+    }
+
+    // abstract methods to be implemented by a particular jrt file system
+    abstract AbstractJrtPath getRootPath();
+
+    abstract boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException;
+
+    abstract boolean isLink(AbstractJrtPath jrtPath) throws IOException;
+
+    abstract AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException;
+
+    abstract AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException;
+
+    abstract boolean exists(AbstractJrtPath jrtPath) throws IOException;
+
+    abstract boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException;
+
+    /**
+     * returns the list of child paths of the given directory "path"
+     *
+     * @param path name of the directory whose content is listed
+     * @return iterator for child paths of the given directory path
+     */
+    abstract Iterator<Path> iteratorOf(AbstractJrtPath jrtPath) throws IOException;
+
+    // returns the content of the file resource specified by the path
+    abstract byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException;
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java
new file mode 100644
index 0000000..8e939a0
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/AbstractJrtPath.java
@@ -0,0 +1,935 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.attribute.*;
+import java.util.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/**
+ * Base class for Path implementation of jrt file systems.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+abstract class AbstractJrtPath implements Path {
+
+    protected final AbstractJrtFileSystem jrtfs;
+    private final byte[] path;
+    private volatile int[] offsets;
+    private int hashcode = 0;  // cached hashcode (created lazily)
+
+    AbstractJrtPath(AbstractJrtFileSystem jrtfs, byte[] path) {
+        this(jrtfs, path, false);
+        this.resolved = null;
+    }
+
+    AbstractJrtPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
+        this.resolved = null;
+        this.jrtfs = jrtfs;
+        if (normalized) {
+            this.path = path;
+        } else {
+            this.path = normalize(path);
+        }
+    }
+
+    // factory methods to create subtypes of AbstractJrtPath
+    protected abstract AbstractJrtPath newJrtPath(byte[] path);
+
+    protected abstract AbstractJrtPath newJrtPath(byte[] path, boolean normalized);
+
+    final byte[] getName() {
+        return path;
+    }
+
+    @Override
+    public final AbstractJrtPath getRoot() {
+        if (this.isAbsolute()) {
+            return jrtfs.getRootPath();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public final AbstractJrtPath getFileName() {
+        initOffsets();
+        int count = offsets.length;
+        if (count == 0) {
+            return null;  // no elements so no name
+        }
+        if (count == 1 && path[0] != '/') {
+            return this;
+        }
+        int lastOffset = offsets[count - 1];
+        int len = path.length - lastOffset;
+        byte[] result = new byte[len];
+        System.arraycopy(path, lastOffset, result, 0, len);
+        return newJrtPath(result);
+    }
+
+    @Override
+    public final AbstractJrtPath getParent() {
+        initOffsets();
+        int count = offsets.length;
+        if (count == 0) // no elements so no parent
+        {
+            return null;
+        }
+        int len = offsets[count - 1] - 1;
+        if (len <= 0) // parent is root only (may be null)
+        {
+            return getRoot();
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(path, 0, result, 0, len);
+        return newJrtPath(result);
+    }
+
+    @Override
+    public final int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+    @Override
+    public final AbstractJrtPath getName(int index) {
+        initOffsets();
+        if (index < 0 || index >= offsets.length) {
+            throw new IllegalArgumentException();
+        }
+        int begin = offsets[index];
+        int len;
+        if (index == (offsets.length - 1)) {
+            len = path.length - begin;
+        } else {
+            len = offsets[index + 1] - begin - 1;
+        }
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return newJrtPath(result);
+    }
+
+    @Override
+    public final AbstractJrtPath subpath(int beginIndex, int endIndex) {
+        initOffsets();
+        if (beginIndex < 0
+                || beginIndex >= offsets.length
+                || endIndex > offsets.length
+                || beginIndex >= endIndex) {
+            throw new IllegalArgumentException();
+        }
+
+        // starting offset and length
+        int begin = offsets[beginIndex];
+        int len;
+        if (endIndex == offsets.length) {
+            len = path.length - begin;
+        } else {
+            len = offsets[endIndex] - begin - 1;
+        }
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return newJrtPath(result);
+    }
+
+    @Override
+    public final AbstractJrtPath toRealPath(LinkOption... options) throws IOException {
+        AbstractJrtPath realPath = newJrtPath(getResolvedPath()).toAbsolutePath();
+        realPath = JrtFileSystem.followLinks(options) ? jrtfs.resolveLink(this) : realPath;
+        realPath.checkAccess();
+        return realPath;
+    }
+
+    final AbstractJrtPath readSymbolicLink() throws IOException {
+        if (!jrtfs.isLink(this)) {
+            throw new IOException("not a symbolic link");
+        }
+
+        return jrtfs.resolveLink(this);
+    }
+
+    final boolean isHidden() {
+        return false;
+    }
+
+    @Override
+    public final AbstractJrtPath toAbsolutePath() {
+        if (isAbsolute()) {
+            return this;
+        } else {
+            //add / bofore the existing path
+            byte[] tmp = new byte[path.length + 1];
+            tmp[0] = '/';
+            System.arraycopy(path, 0, tmp, 1, path.length);
+            return newJrtPath(tmp).normalize();
+        }
+    }
+
+    @Override
+    public final URI toUri() {
+        try {
+            return new URI("jrt",
+                    JrtFileSystem.getString(toAbsolutePath().path),
+                    null);
+        } catch (URISyntaxException ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    private boolean equalsNameAt(AbstractJrtPath other, int index) {
+        int mbegin = offsets[index];
+        int mlen;
+        if (index == (offsets.length - 1)) {
+            mlen = path.length - mbegin;
+        } else {
+            mlen = offsets[index + 1] - mbegin - 1;
+        }
+        int obegin = other.offsets[index];
+        int olen;
+        if (index == (other.offsets.length - 1)) {
+            olen = other.path.length - obegin;
+        } else {
+            olen = other.offsets[index + 1] - obegin - 1;
+        }
+        if (mlen != olen) {
+            return false;
+        }
+        int n = 0;
+        while (n < mlen) {
+            if (path[mbegin + n] != other.path[obegin + n]) {
+                return false;
+            }
+            n++;
+        }
+        return true;
+    }
+
+    @Override
+    public final AbstractJrtPath relativize(Path other) {
+        final AbstractJrtPath o = checkPath(other);
+        if (o.equals(this)) {
+            return newJrtPath(new byte[0], true);
+        }
+        if (/* this.getFileSystem() != o.getFileSystem() || */this.isAbsolute() != o.isAbsolute()) {
+            throw new IllegalArgumentException();
+        }
+        int mc = this.getNameCount();
+        int oc = o.getNameCount();
+        int n = Math.min(mc, oc);
+        int i = 0;
+        while (i < n) {
+            if (!equalsNameAt(o, i)) {
+                break;
+            }
+            i++;
+        }
+        int dotdots = mc - i;
+        int len = dotdots * 3 - 1;
+        if (i < oc) {
+            len += (o.path.length - o.offsets[i] + 1);
+        }
+        byte[] result = new byte[len];
+
+        int pos = 0;
+        while (dotdots > 0) {
+            result[pos++] = (byte) '.';
+            result[pos++] = (byte) '.';
+            if (pos < len) // no tailing slash at the end
+            {
+                result[pos++] = (byte) '/';
+            }
+            dotdots--;
+        }
+        if (i < oc) {
+            System.arraycopy(o.path, o.offsets[i],
+                    result, pos,
+                    o.path.length - o.offsets[i]);
+        }
+        return newJrtPath(result);
+    }
+
+    @Override
+    public AbstractJrtFileSystem getFileSystem() {
+        return jrtfs;
+    }
+
+    @Override
+    public final boolean isAbsolute() {
+        return (this.path.length > 0 && path[0] == '/');
+    }
+
+    @Override
+    public final AbstractJrtPath resolve(Path other) {
+        final AbstractJrtPath o = checkPath(other);
+        if (o.isAbsolute()) {
+            return o;
+        }
+        byte[] res;
+        if (this.path[path.length - 1] == '/') {
+            res = new byte[path.length + o.path.length];
+            System.arraycopy(path, 0, res, 0, path.length);
+            System.arraycopy(o.path, 0, res, path.length, o.path.length);
+        } else {
+            res = new byte[path.length + 1 + o.path.length];
+            System.arraycopy(path, 0, res, 0, path.length);
+            res[path.length] = '/';
+            System.arraycopy(o.path, 0, res, path.length + 1, o.path.length);
+        }
+        return newJrtPath(res);
+    }
+
+    @Override
+    public final Path resolveSibling(Path other) {
+        if (other == null) {
+            throw new NullPointerException();
+        }
+        Path parent = getParent();
+        return (parent == null) ? other : parent.resolve(other);
+    }
+
+    @Override
+    public final boolean startsWith(Path other) {
+        final AbstractJrtPath o = checkPath(other);
+        if (o.isAbsolute() != this.isAbsolute()
+                || o.path.length > this.path.length) {
+            return false;
+        }
+        int olast = o.path.length;
+        for (int i = 0; i < olast; i++) {
+            if (o.path[i] != this.path[i]) {
+                return false;
+            }
+        }
+        olast--;
+        return o.path.length == this.path.length
+                || o.path[olast] == '/'
+                || this.path[olast + 1] == '/';
+    }
+
+    @Override
+    public final boolean endsWith(Path other) {
+        final AbstractJrtPath o = checkPath(other);
+        int olast = o.path.length - 1;
+        if (olast > 0 && o.path[olast] == '/') {
+            olast--;
+        }
+        int last = this.path.length - 1;
+        if (last > 0 && this.path[last] == '/') {
+            last--;
+        }
+        if (olast == -1) // o.path.length == 0
+        {
+            return last == -1;
+        }
+        if ((o.isAbsolute() && (!this.isAbsolute() || olast != last))
+                || (last < olast)) {
+            return false;
+        }
+        for (; olast >= 0; olast--, last--) {
+            if (o.path[olast] != this.path[last]) {
+                return false;
+            }
+        }
+        return o.path[olast + 1] == '/'
+                || last == -1 || this.path[last] == '/';
+    }
+
+    @Override
+    public final AbstractJrtPath resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final Path resolveSibling(String other) {
+        return resolveSibling(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final boolean startsWith(String other) {
+        return startsWith(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final boolean endsWith(String other) {
+        return endsWith(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public final AbstractJrtPath normalize() {
+        byte[] res = getResolved();
+        if (res == path) // no change
+        {
+            return this;
+        }
+        return newJrtPath(res, true);
+    }
+
+    private AbstractJrtPath checkPath(Path path) {
+        if (path == null) {
+            throw new NullPointerException();
+        }
+        if (!(path instanceof AbstractJrtPath)) {
+            throw new ProviderMismatchException();
+        }
+        return (AbstractJrtPath) path;
+    }
+
+    // create offset list if not already created
+    private void initOffsets() {
+        if (offsets == null) {
+            int count, index;
+            // count names
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index++];
+                if (c != '/') {
+                    count++;
+                    while (index < path.length && path[index] != '/') {
+                        index++;
+                    }
+                }
+            }
+            // populate offsets
+            int[] result = new int[count];
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index];
+                if (c == '/') {
+                    index++;
+                } else {
+                    result[count++] = index++;
+                    while (index < path.length && path[index] != '/') {
+                        index++;
+                    }
+                }
+            }
+            synchronized (this) {
+                if (offsets == null) {
+                    offsets = result;
+                }
+            }
+        }
+    }
+
+    private volatile byte[] resolved;
+
+    final byte[] getResolvedPath() {
+        byte[] r = resolved;
+        if (r == null) {
+            if (isAbsolute()) {
+                r = getResolved();
+            } else {
+                r = toAbsolutePath().getResolvedPath();
+            }
+            resolved = r;
+        }
+        return resolved;
+    }
+
+    // removes redundant slashs, replace "\" to separator "/"
+    // and check for invalid characters
+    private static byte[] normalize(byte[] path) {
+        if (path.length == 0) {
+            return path;
+        }
+        byte prevC = 0;
+        for (int i = 0; i < path.length; i++) {
+            byte c = path[i];
+            if (c == '\\') {
+                return normalize(path, i);
+            }
+            if (c == (byte) '/' && prevC == '/') {
+                return normalize(path, i - 1);
+            }
+            if (c == '\u0000') {
+                throw new InvalidPathException(JrtFileSystem.getString(path),
+                        "Path: nul character not allowed");
+            }
+            prevC = c;
+        }
+
+        if (path.length > 1 && path[path.length - 1] == '/') {
+            return Arrays.copyOf(path, path.length - 1);
+        }
+
+        return path;
+    }
+
+    private static byte[] normalize(byte[] path, int off) {
+        byte[] to = new byte[path.length];
+        int n = 0;
+        while (n < off) {
+            to[n] = path[n];
+            n++;
+        }
+        int m = n;
+        byte prevC = 0;
+        while (n < path.length) {
+            byte c = path[n++];
+            if (c == (byte) '\\') {
+                c = (byte) '/';
+            }
+            if (c == (byte) '/' && prevC == (byte) '/') {
+                continue;
+            }
+            if (c == '\u0000') {
+                throw new InvalidPathException(JrtFileSystem.getString(path),
+                        "Path: nul character not allowed");
+            }
+            to[m++] = c;
+            prevC = c;
+        }
+        if (m > 1 && to[m - 1] == '/') {
+            m--;
+        }
+        return (m == to.length) ? to : Arrays.copyOf(to, m);
+    }
+
+    // Remove DotSlash(./) and resolve DotDot (..) components
+    private byte[] getResolved() {
+        if (path.length == 0) {
+            return path;
+        }
+        for (int i = 0; i < path.length; i++) {
+            byte c = path[i];
+            if (c == (byte) '.') {
+                return resolve0();
+            }
+        }
+
+        return path;
+    }
+
+    // TBD: performance, avoid initOffsets
+    private byte[] resolve0() {
+        byte[] to = new byte[path.length];
+        int nc = getNameCount();
+        int[] lastM = new int[nc];
+        int lastMOff = -1;
+        int m = 0;
+        for (int i = 0; i < nc; i++) {
+            int n = offsets[i];
+            int len = (i == offsets.length - 1)
+                    ? (path.length - n) : (offsets[i + 1] - n - 1);
+            if (len == 1 && path[n] == (byte) '.') {
+                if (m == 0 && path[0] == '/') // absolute path
+                {
+                    to[m++] = '/';
+                }
+                continue;
+            }
+            if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
+                if (lastMOff >= 0) {
+                    m = lastM[lastMOff--];  // retreat
+                    continue;
+                }
+                if (path[0] == '/') {  // "/../xyz" skip
+                    if (m == 0) {
+                        to[m++] = '/';
+                    }
+                } else {               // "../xyz" -> "../xyz"
+                    if (m != 0 && to[m - 1] != '/') {
+                        to[m++] = '/';
+                    }
+                    while (len-- > 0) {
+                        to[m++] = path[n++];
+                    }
+                }
+                continue;
+            }
+            if (m == 0 && path[0] == '/' || // absolute path
+                    m != 0 && to[m - 1] != '/') {   // not the first name
+                to[m++] = '/';
+            }
+            lastM[++lastMOff] = m;
+            while (len-- > 0) {
+                to[m++] = path[n++];
+            }
+        }
+        if (m > 1 && to[m - 1] == '/') {
+            m--;
+        }
+        return (m == to.length) ? to : Arrays.copyOf(to, m);
+    }
+
+    @Override
+    public final String toString() {
+        return JrtFileSystem.getString(path);
+    }
+
+    @Override
+    public final int hashCode() {
+        int h = hashcode;
+        if (h == 0) {
+            hashcode = h = Arrays.hashCode(path);
+        }
+        return h;
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        return obj != null
+                && obj instanceof AbstractJrtPath
+                && this.jrtfs == ((AbstractJrtPath) obj).jrtfs
+                && compareTo((Path) obj) == 0;
+    }
+
+    @Override
+    public final int compareTo(Path other) {
+        final AbstractJrtPath o = checkPath(other);
+        int len1 = this.path.length;
+        int len2 = o.path.length;
+
+        int n = Math.min(len1, len2);
+        byte v1[] = this.path;
+        byte v2[] = o.path;
+
+        int k = 0;
+        while (k < n) {
+            int c1 = v1[k] & 0xff;
+            int c2 = v2[k] & 0xff;
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+            k++;
+        }
+        return len1 - len2;
+    }
+
+    @Override
+    public final WatchKey register(
+            WatchService watcher,
+            WatchEvent.Kind<?>[] events,
+            WatchEvent.Modifier... modifiers) {
+        if (watcher == null || events == null || modifiers == null) {
+            throw new NullPointerException();
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
+        return register(watcher, events, new WatchEvent.Modifier[0]);
+    }
+
+    @Override
+    public final File toFile() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final Iterator<Path> iterator() {
+        return new Iterator<Path>() {
+            private int i = 0;
+
+            @Override
+            public boolean hasNext() {
+                return (i < getNameCount());
+            }
+
+            @Override
+            public Path next() {
+                if (i < getNameCount()) {
+                    Path result = getName(i);
+                    i++;
+                    return result;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void remove() {
+                throw new ReadOnlyFileSystemException();
+            }
+        };
+    }
+
+    /////////////////////////////////////////////////////////////////////
+    // Helpers for JrtFileSystemProvider and JrtFileSystem
+    final int getPathLength() {
+        return path.length;
+    }
+
+    final void createDirectory(FileAttribute<?>... attrs)
+            throws IOException {
+        jrtfs.createDirectory(this, attrs);
+    }
+
+    final InputStream newInputStream(OpenOption... options) throws IOException {
+        if (options.length > 0) {
+            for (OpenOption opt : options) {
+                if (opt != READ) {
+                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
+                }
+            }
+        }
+        return jrtfs.newInputStream(this);
+    }
+
+    final DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
+            throws IOException {
+        return new JrtDirectoryStream(this, filter);
+    }
+
+    final void delete() throws IOException {
+        jrtfs.deleteFile(this, true);
+    }
+
+    final void deleteIfExists() throws IOException {
+        jrtfs.deleteFile(this, false);
+    }
+
+    final AbstractJrtFileAttributes getAttributes(LinkOption... options) throws IOException {
+        AbstractJrtFileAttributes zfas = jrtfs.getFileAttributes(this, options);
+        if (zfas == null) {
+            throw new NoSuchFileException(toString());
+        }
+        return zfas;
+    }
+
+    final void setAttribute(String attribute, Object value, LinkOption... options)
+            throws IOException {
+        String type;
+        String attr;
+        int colonPos = attribute.indexOf(':');
+        if (colonPos == -1) {
+            type = "basic";
+            attr = attribute;
+        } else {
+            type = attribute.substring(0, colonPos++);
+            attr = attribute.substring(colonPos);
+        }
+        JrtFileAttributeView view = JrtFileAttributeView.get(this, type, options);
+        if (view == null) {
+            throw new UnsupportedOperationException("view <" + view + "> is not supported");
+        }
+        view.setAttribute(attr, value);
+    }
+
+    final void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
+            throws IOException {
+        jrtfs.setTimes(this, mtime, atime, ctime);
+    }
+
+    final Map<String, Object> readAttributes(String attributes, LinkOption... options)
+            throws IOException {
+        String view;
+        String attrs;
+        int colonPos = attributes.indexOf(':');
+        if (colonPos == -1) {
+            view = "basic";
+            attrs = attributes;
+        } else {
+            view = attributes.substring(0, colonPos++);
+            attrs = attributes.substring(colonPos);
+        }
+        JrtFileAttributeView jrtfv = JrtFileAttributeView.get(this, view, options);
+        if (jrtfv == null) {
+            throw new UnsupportedOperationException("view not supported");
+        }
+        return jrtfv.readAttributes(attrs);
+    }
+
+    final FileStore getFileStore() throws IOException {
+        // each JrtFileSystem only has one root (as requested for now)
+        if (exists()) {
+            return jrtfs.getFileStore(this);
+        }
+        throw new NoSuchFileException(JrtFileSystem.getString(path));
+    }
+
+    final boolean isSameFile(Path other) throws IOException {
+        if (this.equals(other)) {
+            return true;
+        }
+        if (other == null
+                || this.getFileSystem() != other.getFileSystem()) {
+            return false;
+        }
+        this.checkAccess();
+        AbstractJrtPath target = (AbstractJrtPath) other;
+        target.checkAccess();
+        return Arrays.equals(this.getResolvedPath(), target.getResolvedPath())
+                || jrtfs.isSameFile(this, target);
+    }
+
+    final SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        return jrtfs.newByteChannel(this, options, attrs);
+    }
+
+    final FileChannel newFileChannel(Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        return jrtfs.newFileChannel(this, options, attrs);
+    }
+
+    final void checkAccess(AccessMode... modes) throws IOException {
+        boolean w = false;
+        boolean x = false;
+        for (AccessMode mode : modes) {
+            switch (mode) {
+                case READ:
+                    break;
+                case WRITE:
+                    w = true;
+                    break;
+                case EXECUTE:
+                    x = true;
+                    break;
+                default:
+                    throw new UnsupportedOperationException();
+            }
+        }
+
+        BasicFileAttributes attrs = jrtfs.getFileAttributes(this);
+        if (attrs == null && (path.length != 1 || path[0] != '/')) {
+            throw new NoSuchFileException(toString());
+        }
+        if (w) {
+//            if (jrtfs.isReadOnly())
+            throw new AccessDeniedException(toString());
+        }
+        if (x) {
+            throw new AccessDeniedException(toString());
+        }
+    }
+
+    final boolean exists() {
+        try {
+            return jrtfs.exists(this);
+        } catch (IOException x) {
+        }
+        return false;
+    }
+
+    final OutputStream newOutputStream(OpenOption... options) throws IOException {
+        if (options.length == 0) {
+            return jrtfs.newOutputStream(this,
+                    CREATE_NEW, WRITE);
+        }
+        return jrtfs.newOutputStream(this, options);
+    }
+
+    final void move(AbstractJrtPath target, CopyOption... options)
+            throws IOException {
+        if (this.jrtfs == target.jrtfs) {
+            jrtfs.copyFile(true,
+                    this, target,
+                    options);
+        } else {
+            copyToTarget(target, options);
+            delete();
+        }
+    }
+
+    final void copy(AbstractJrtPath target, CopyOption... options)
+            throws IOException {
+        if (this.jrtfs == target.jrtfs) {
+            jrtfs.copyFile(false,
+                    this, target,
+                    options);
+        } else {
+            copyToTarget(target, options);
+        }
+    }
+
+    private void copyToTarget(AbstractJrtPath target, CopyOption... options)
+            throws IOException {
+        boolean replaceExisting = false;
+        boolean copyAttrs = false;
+        for (CopyOption opt : options) {
+            if (opt == REPLACE_EXISTING) {
+                replaceExisting = true;
+            } else if (opt == COPY_ATTRIBUTES) {
+                copyAttrs = true;
+            }
+        }
+        // attributes of source file
+        BasicFileAttributes jrtfas = getAttributes();
+        // check if target exists
+        boolean exists;
+        if (replaceExisting) {
+            try {
+                target.deleteIfExists();
+                exists = false;
+            } catch (DirectoryNotEmptyException x) {
+                exists = true;
+            }
+        } else {
+            exists = target.exists();
+        }
+        if (exists) {
+            throw new FileAlreadyExistsException(target.toString());
+        }
+
+        if (jrtfas.isDirectory()) {
+            // create directory or file
+            target.createDirectory();
+        } else {
+            try (InputStream is = jrtfs.newInputStream(this); OutputStream os = target.newOutputStream()) {
+                byte[] buf = new byte[8192];
+                int n;
+                while ((n = is.read(buf)) != -1) {
+                    os.write(buf, 0, n);
+                }
+            }
+        }
+        if (copyAttrs) {
+            BasicFileAttributeView view
+                    = JrtFileAttributeView.get(target, BasicFileAttributeView.class);
+            try {
+                view.setTimes(jrtfas.lastModifiedTime(),
+                        jrtfas.lastAccessTime(),
+                        jrtfas.creationTime());
+            } catch (IOException x) {
+                // rollback?
+                try {
+                    target.delete();
+                } catch (IOException ignore) {
+                }
+                throw x;
+            }
+        }
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java
index 1a870fa..ed7702c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtDirectoryStream.java
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
 import java.nio.file.DirectoryStream;
@@ -34,48 +33,47 @@
 import java.util.NoSuchElementException;
 import java.io.IOException;
 
+/**
+ * DirectoryStream implementation for jrt file system implementations.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 final class JrtDirectoryStream implements DirectoryStream<Path> {
-    private final JrtFileSystem jrtfs;
-    private final byte[] path;
-    // prefix to be used for children of this directory
-    // so that child path are reported relatively (if needed)
-    private final String childPrefix;
+
+    private final AbstractJrtFileSystem jrtfs;
+    private final AbstractJrtPath dir;
     private final DirectoryStream.Filter<? super Path> filter;
     private volatile boolean isClosed;
     private volatile Iterator<Path> itr;
 
-    JrtDirectoryStream(JrtPath jrtPath,
-                       DirectoryStream.Filter<? super java.nio.file.Path> filter)
-        throws IOException
-    {
+    JrtDirectoryStream(AbstractJrtPath jrtPath,
+            DirectoryStream.Filter<? super java.nio.file.Path> filter)
+            throws IOException {
         this.jrtfs = jrtPath.getFileSystem();
-        this.path = jrtPath.getResolvedPath();
+        this.dir = jrtPath;
         // sanity check
-        if (!jrtfs.isDirectory(path, true))
+        if (!jrtfs.isDirectory(dir, true)) {
             throw new NotDirectoryException(jrtPath.toString());
-
-        // absolute path and does not have funky chars in front like /./java.base
-        if (jrtPath.isAbsolute() && (path.length == jrtPath.getPathLength())) {
-            childPrefix = null;
-        } else {
-            // cases where directory content needs to modified with prefix
-            // like ./java.base, /./java.base, java.base and so on.
-            String dirName = jrtPath.toString();
-            int idx = dirName.indexOf(JrtFileSystem.getString(path).substring(1));
-            childPrefix = dirName.substring(0, idx);
         }
+
         this.filter = filter;
     }
 
     @Override
     public synchronized Iterator<Path> iterator() {
-        if (isClosed)
+        if (isClosed) {
             throw new ClosedDirectoryStreamException();
-        if (itr != null)
+        }
+        if (itr != null) {
             throw new IllegalStateException("Iterator has already been returned");
+        }
 
         try {
-            itr = jrtfs.iteratorOf(path, childPrefix);
+            itr = jrtfs.iteratorOf(dir);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileAttributes.java
new file mode 100644
index 0000000..161bbaa
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileAttributes.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.IOException;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import jdk.internal.jrtfs.JrtExplodedFileSystem.Node;
+
+/**
+ * jrt file system attributes implementation on top of 'exploded file system'
+ * Node.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+final class JrtExplodedFileAttributes extends AbstractJrtFileAttributes {
+
+    private final Node node;
+    private final BasicFileAttributes attrs;
+
+    JrtExplodedFileAttributes(Node node) throws IOException {
+        this.node = node;
+        this.attrs = node.getBasicAttrs();
+    }
+
+    @Override
+    public FileTime creationTime() {
+        return attrs.creationTime();
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return node.isDirectory();
+    }
+
+    @Override
+    public boolean isOther() {
+        return false;
+    }
+
+    @Override
+    public boolean isRegularFile() {
+        return node.isFile();
+    }
+
+    @Override
+    public FileTime lastAccessTime() {
+        return attrs.lastAccessTime();
+    }
+
+    @Override
+    public FileTime lastModifiedTime() {
+        return attrs.lastModifiedTime();
+    }
+
+    @Override
+    public long size() {
+        return isRegularFile() ? attrs.size() : 0L;
+    }
+
+    @Override
+    public boolean isSymbolicLink() {
+        return node.isLink();
+    }
+
+    @Override
+    public Object fileKey() {
+        return node.resolveLink(true);
+    }
+
+    @Override
+    public long compressedSize() {
+        return 0L;
+    }
+
+    @Override
+    public String extension() {
+        return node.getExtension();
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java
new file mode 100644
index 0000000..3a077b1
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedFileSystem.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import static java.util.stream.Collectors.toList;
+import static jdk.internal.jrtfs.AbstractJrtFileSystem.getString;
+
+/**
+ * A jrt file system built on $JAVA_HOME/modules directory ('exploded modules
+ * build')
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+class JrtExplodedFileSystem extends AbstractJrtFileSystem {
+
+    private static final String MODULES = "/modules/";
+    private static final String PACKAGES = "/packages/";
+    private static final int PACKAGES_LEN = PACKAGES.length();
+
+    // root path
+    private final JrtExplodedPath rootPath;
+    private volatile boolean isOpen;
+    private final FileSystem defaultFS;
+    private final String separator;
+    private final Map<String, Node> nodes = Collections.synchronizedMap(new HashMap<>());
+    private final BasicFileAttributes modulesDirAttrs;
+
+    JrtExplodedFileSystem(JrtFileSystemProvider provider,
+            Map<String, ?> env)
+            throws IOException {
+
+        super(provider, env);
+        checkExists(SystemImages.explodedModulesDir());
+        byte[] root = new byte[]{'/'};
+        rootPath = new JrtExplodedPath(this, root);
+        isOpen = true;
+        defaultFS = FileSystems.getDefault();
+        String str = defaultFS.getSeparator();
+        separator = str.equals(getSeparator()) ? null : str;
+        modulesDirAttrs = Files.readAttributes(SystemImages.explodedModulesDir(), BasicFileAttributes.class);
+        initNodes();
+    }
+
+    @Override
+    public void close() throws IOException {
+        cleanup();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return isOpen;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        cleanup();
+        super.finalize();
+    }
+
+    private synchronized void cleanup() {
+        isOpen = false;
+        nodes.clear();
+    }
+
+    @Override
+    JrtExplodedPath getRootPath() {
+        return rootPath;
+    }
+
+    // Base class for Nodes of this file system
+    abstract class Node {
+
+        private final String name;
+
+        Node(String name) {
+            this.name = name;
+        }
+
+        final String getName() {
+            return name;
+        }
+
+        final String getExtension() {
+            if (isFile()) {
+                final int index = name.lastIndexOf(".");
+                if (index != -1) {
+                    return name.substring(index + 1);
+                }
+            }
+
+            return null;
+        }
+
+        BasicFileAttributes getBasicAttrs() throws IOException {
+            return modulesDirAttrs;
+        }
+
+        boolean isLink() {
+            return false;
+        }
+
+        boolean isDirectory() {
+            return false;
+        }
+
+        boolean isFile() {
+            return false;
+        }
+
+        byte[] getContent() throws IOException {
+            if (!isFile()) {
+                throw new FileSystemException(name + " is not file");
+            }
+
+            throw new AssertionError("ShouldNotReachHere");
+        }
+
+        List<Node> getChildren() throws IOException {
+            if (!isDirectory()) {
+                throw new NotDirectoryException(name);
+            }
+
+            throw new AssertionError("ShouldNotReachHere");
+        }
+
+        final Node resolveLink() {
+            return resolveLink(false);
+        }
+
+        Node resolveLink(boolean recursive) {
+            return this;
+        }
+    }
+
+    // A Node that is backed by actual default file system Path
+    private final class PathNode extends Node {
+
+        // Path in underlying default file system
+        private final Path path;
+        private final boolean file;
+        // lazily initialized, don't read attributes unless required!
+        private BasicFileAttributes attrs;
+
+        PathNode(String name, Path path) {
+            super(name);
+            this.path = path;
+            this.file = Files.isRegularFile(path);
+        }
+
+        @Override
+        synchronized BasicFileAttributes getBasicAttrs() throws IOException {
+            if (attrs == null) {
+                attrs = Files.readAttributes(path, BasicFileAttributes.class);
+            }
+            return attrs;
+        }
+
+        @Override
+        boolean isDirectory() {
+            return !file;
+        }
+
+        @Override
+        boolean isFile() {
+            return file;
+        }
+
+        @Override
+        byte[] getContent() throws IOException {
+            if (!isFile()) {
+                throw new FileSystemException(getName() + " is not file");
+            }
+
+            return Files.readAllBytes(path);
+        }
+
+        @Override
+        List<Node> getChildren() throws IOException {
+            if (!isDirectory()) {
+                throw new NotDirectoryException(getName());
+            }
+
+            List<Node> children = new ArrayList<>();
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
+                for (Path cp : stream) {
+                    cp = SystemImages.explodedModulesDir().relativize(cp);
+                    String cpName = MODULES + nativeSlashToFrontSlash(cp.toString());
+                    try {
+                        children.add(findNode(cpName));
+                    } catch (NoSuchFileException nsfe) {
+                        // findNode may choose to hide certain files!
+                    }
+                }
+            }
+
+            return children;
+        }
+    }
+
+    // A Node that links to another Node
+    private final class LinkNode extends Node {
+
+        // underlying linked Node
+        private final Node link;
+
+        LinkNode(String name, Node link) {
+            super(name);
+            this.link = link;
+        }
+
+        @Override
+        BasicFileAttributes getBasicAttrs() throws IOException {
+            return link.getBasicAttrs();
+        }
+
+        @Override
+        public boolean isLink() {
+            return true;
+        }
+
+        @Override
+        Node resolveLink(boolean recursive) {
+            return recursive && (link instanceof LinkNode) ? ((LinkNode) link).resolveLink(true) : link;
+        }
+    }
+
+    // A directory Node with it's children Nodes
+    private final class DirNode extends Node {
+
+        // children Nodes of this Node.
+        private final List<Node> children;
+
+        DirNode(String name, List<Node> children) {
+            super(name);
+            this.children = children;
+        }
+
+        @Override
+        boolean isDirectory() {
+            return true;
+        }
+
+        @Override
+        List<Node> getChildren() throws IOException {
+            return children;
+        }
+    }
+
+    private JrtExplodedPath toJrtExplodedPath(String path) {
+        return toJrtExplodedPath(getBytes(path));
+    }
+
+    private JrtExplodedPath toJrtExplodedPath(byte[] path) {
+        return new JrtExplodedPath(this, path);
+    }
+
+    @Override
+    boolean isSameFile(AbstractJrtPath jrtPath1, AbstractJrtPath jrtPath2) throws IOException {
+        Node n1 = checkNode(jrtPath1);
+        Node n2 = checkNode(jrtPath2);
+        return n1 == n2;
+    }
+
+    @Override
+    boolean isLink(AbstractJrtPath jrtPath) throws IOException {
+        return checkNode(jrtPath).isLink();
+    }
+
+    @Override
+    AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
+        String name = checkNode(jrtPath).resolveLink().getName();
+        return toJrtExplodedPath(name);
+    }
+
+    @Override
+    AbstractJrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options) throws IOException {
+        Node node = checkNode(jrtPath);
+        if (node.isLink() && followLinks(options)) {
+            node = node.resolveLink(true);
+        }
+        return new JrtExplodedFileAttributes(node);
+    }
+
+    @Override
+    boolean exists(AbstractJrtPath jrtPath) throws IOException {
+        try {
+            checkNode(jrtPath);
+            return true;
+        } catch (NoSuchFileException nsfe) {
+            return false;
+        }
+    }
+
+    @Override
+    boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks) throws IOException {
+        Node node = checkNode(jrtPath);
+        return resolveLinks && node.isLink()
+                ? node.resolveLink(true).isDirectory()
+                : node.isDirectory();
+    }
+
+    @Override
+    Iterator<Path> iteratorOf(AbstractJrtPath dir) throws IOException {
+        Node node = checkNode(dir).resolveLink(true);
+        if (!node.isDirectory()) {
+            throw new NotDirectoryException(getString(dir.getName()));
+        }
+
+        Function<Node, Path> nodeToPath =
+            child -> dir.resolve(
+                toJrtExplodedPath(child.getName()).
+                getFileName());
+
+        return node.getChildren().stream().
+                   map(nodeToPath).collect(toList()).
+                   iterator();
+    }
+
+    @Override
+    byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException {
+        return checkNode(jrtPath).getContent();
+    }
+
+    private Node checkNode(AbstractJrtPath jrtPath) throws IOException {
+        return checkNode(jrtPath.getResolvedPath());
+    }
+
+    private Node checkNode(byte[] path) throws IOException {
+        ensureOpen();
+        return findNode(path);
+    }
+
+    synchronized Node findNode(byte[] path) throws IOException {
+        return findNode(getString(path));
+    }
+
+    // find Node for the given Path
+    synchronized Node findNode(String str) throws IOException {
+        Node node = findModulesNode(str);
+        if (node != null) {
+            return node;
+        }
+
+        // lazily created for paths like /packages/<package>/<module>/xyz
+        // For example /packages/java.lang/java.base/java/lang/
+        if (str.startsWith(PACKAGES)) {
+            // pkgEndIdx marks end of <package> part
+            int pkgEndIdx = str.indexOf('/', PACKAGES_LEN);
+            if (pkgEndIdx != -1) {
+                // modEndIdx marks end of <module> part
+                int modEndIdx = str.indexOf('/', pkgEndIdx + 1);
+                if (modEndIdx != -1) {
+                    // make sure we have such module link!
+                    // ie., /packages/<package>/<module> is valid
+                    Node linkNode = nodes.get(str.substring(0, modEndIdx));
+                    if (linkNode == null || !linkNode.isLink()) {
+                        throw new NoSuchFileException(str);
+                    }
+
+                    // map to "/modules/zyz" path and return that node
+                    // For example, "/modules/java.base/java/lang" for
+                    // "/packages/java.lang/java.base/java/lang".
+                    String mod = MODULES + str.substring(pkgEndIdx + 1);
+                    return findNode(mod);
+                }
+            }
+        }
+
+        throw new NoSuchFileException(str);
+    }
+
+    // find a Node for a path that starts like "/modules/..."
+    synchronized Node findModulesNode(String str) throws IOException {
+        Node node = nodes.get(str);
+        if (node != null) {
+            return node;
+        }
+
+        // lazily created "/modules/xyz/abc/" Node
+        // This is mapped to default file system path "<JDK_MODULES_DIR>/xyz/abc"
+        Path p = underlyingPath(str);
+        if (p != null) {
+            if (Files.isRegularFile(p)) {
+                Path file = p.getFileName();
+                if (file.toString().startsWith("_the.")) {
+                    return null;
+                }
+            }
+            node = new PathNode(str, p);
+            nodes.put(str, node);
+            return node;
+        }
+
+        return null;
+    }
+
+    Path underlyingPath(String str) {
+        if (str.startsWith(MODULES)) {
+            str = frontSlashToNativeSlash(str.substring("/modules".length()));
+            return defaultFS.getPath(SystemImages.explodedModulesDir().toString(), str);
+        }
+        return null;
+    }
+
+    // convert "/" to platform path separator
+    private String frontSlashToNativeSlash(String str) {
+        return separator == null ? str : str.replace("/", separator);
+    }
+
+    // convert platform path separator to "/"
+    private String nativeSlashToFrontSlash(String str) {
+        return separator == null ? str : str.replace(separator, "/");
+    }
+
+    // convert "/"s to "."s
+    private String slashesToDots(String str) {
+        return str.replace(separator != null ? separator : "/", ".");
+    }
+
+    // initialize file system Nodes
+    private void initNodes() throws IOException {
+        // same package prefix may exist in mutliple modules. This Map
+        // is filled by walking "jdk modules" directory recursively!
+        Map<String, List<String>> packageToModules = new HashMap<>();
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(SystemImages.explodedModulesDir())) {
+            for (Path module : stream) {
+                if (Files.isDirectory(module)) {
+                    String moduleName = module.getFileName().toString();
+                    // make sure "/modules/<moduleName>" is created
+                    findModulesNode(MODULES + moduleName);
+
+                    Files.walk(module).filter(Files::isDirectory).forEach((p) -> {
+                        p = module.relativize(p);
+                        String pkgName = slashesToDots(p.toString());
+                        // skip META-INFO and empty strings
+                        if (!pkgName.isEmpty() && !pkgName.startsWith("META-INF")) {
+                            List<String> moduleNames = packageToModules.get(pkgName);
+                            if (moduleNames == null) {
+                                moduleNames = new ArrayList<>();
+                                packageToModules.put(pkgName, moduleNames);
+                            }
+                            moduleNames.add(moduleName);
+                        }
+                    });
+                }
+            }
+        }
+
+        // create "/modules" directory
+        // "nodes" map contains only /modules/<foo> nodes only so far and so add all as children of /modules
+        DirNode modulesDir = new DirNode("/modules", new ArrayList<>(nodes.values()));
+        nodes.put(modulesDir.getName(), modulesDir);
+
+        // create children under "/packages"
+        List<Node> packagesChildren = new ArrayList<>(packageToModules.size());
+        for (Map.Entry<String, List<String>> entry : packageToModules.entrySet()) {
+            String pkgName = entry.getKey();
+            List<String> moduleNameList = entry.getValue();
+            List<Node> moduleLinkNodes = new ArrayList<>(moduleNameList.size());
+            for (String moduleName : moduleNameList) {
+                Node moduleNode = findModulesNode(MODULES + moduleName);
+                LinkNode linkNode = new LinkNode(PACKAGES + pkgName + "/" + moduleName, moduleNode);
+                nodes.put(linkNode.getName(), linkNode);
+                moduleLinkNodes.add(linkNode);
+            }
+
+            DirNode pkgDir = new DirNode(PACKAGES + pkgName, moduleLinkNodes);
+            nodes.put(pkgDir.getName(), pkgDir);
+            packagesChildren.add(pkgDir);
+        }
+
+        // "/packages" dir
+        DirNode packagesDir = new DirNode("/packages", packagesChildren);
+        nodes.put(packagesDir.getName(), packagesDir);
+
+        // finally "/" dir!
+        List<Node> rootChildren = new ArrayList<>();
+        rootChildren.add(modulesDir);
+        rootChildren.add(packagesDir);
+        DirNode root = new DirNode("/", rootChildren);
+        nodes.put(root.getName(), root);
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedPath.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedPath.java
new file mode 100644
index 0000000..8746ee0
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtExplodedPath.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.jrtfs;
+
+/**
+ * Path implementation for jrt file system on JDK exploded modules build.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+final class JrtExplodedPath extends AbstractJrtPath {
+
+    JrtExplodedPath(AbstractJrtFileSystem jrtfs, byte[] path) {
+        super(jrtfs, path);
+    }
+
+    JrtExplodedPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
+        super(jrtfs, path, normalized);
+    }
+
+    @Override
+    protected AbstractJrtPath newJrtPath(byte[] path) {
+        return new JrtExplodedPath(jrtfs, path);
+    }
+
+    @Override
+    protected AbstractJrtPath newJrtPath(byte[] path, boolean normalized) {
+        return new JrtExplodedPath(jrtfs, path, normalized);
+    }
+
+    @Override
+    public JrtExplodedFileSystem getFileSystem() {
+        return (JrtExplodedFileSystem) jrtfs;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java
index 93b88f7..e6e8065 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributeView.java
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
 import java.nio.file.LinkOption;
@@ -31,9 +30,19 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-final class JrtFileAttributeView implements BasicFileAttributeView
-{
+/**
+ * File attribute view for jrt file system.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+final class JrtFileAttributeView implements BasicFileAttributeView {
+
     private static enum AttrID {
+
         size,
         creationTime,
         lastAccessTime,
@@ -47,124 +56,133 @@
         extension
     };
 
-    private final JrtPath path;
+    private final AbstractJrtPath path;
     private final boolean isJrtView;
     private final LinkOption[] options;
 
-    private JrtFileAttributeView(JrtPath path, boolean isJrtView, LinkOption... options) {
+    private JrtFileAttributeView(AbstractJrtPath path, boolean isJrtView, LinkOption... options) {
         this.path = path;
         this.isJrtView = isJrtView;
         this.options = options;
     }
 
     @SuppressWarnings("unchecked") // Cast to V
-    static <V extends FileAttributeView> V get(JrtPath path, Class<V> type, LinkOption... options) {
-        if (type == null)
+    static <V extends FileAttributeView> V get(AbstractJrtPath path, Class<V> type, LinkOption... options) {
+        if (type == null) {
             throw new NullPointerException();
-        if (type == BasicFileAttributeView.class)
-            return (V)new JrtFileAttributeView(path, false, options);
-        if (type == JrtFileAttributeView.class)
-            return (V)new JrtFileAttributeView(path, true, options);
+        }
+        if (type == BasicFileAttributeView.class) {
+            return (V) new JrtFileAttributeView(path, false, options);
+        }
+        if (type == JrtFileAttributeView.class) {
+            return (V) new JrtFileAttributeView(path, true, options);
+        }
         return null;
     }
 
-    static JrtFileAttributeView get(JrtPath path, String type, LinkOption... options) {
-        if (type == null)
+    static JrtFileAttributeView get(AbstractJrtPath path, String type, LinkOption... options) {
+        if (type == null) {
             throw new NullPointerException();
-        if (type.equals("basic"))
+        }
+        if (type.equals("basic")) {
             return new JrtFileAttributeView(path, false, options);
-        if (type.equals("jjrt"))
+        }
+        if (type.equals("jrt")) {
             return new JrtFileAttributeView(path, true, options);
+        }
         return null;
     }
 
     @Override
     public String name() {
-        return isJrtView ? "jjrt" : "basic";
+        return isJrtView ? "jrt" : "basic";
     }
 
     @Override
-    public JrtFileAttributes readAttributes() throws IOException
-    {
+    public AbstractJrtFileAttributes readAttributes() throws IOException {
         return path.getAttributes(options);
     }
 
     @Override
     public void setTimes(FileTime lastModifiedTime,
-                         FileTime lastAccessTime,
-                         FileTime createTime)
-        throws IOException
-    {
+            FileTime lastAccessTime,
+            FileTime createTime)
+            throws IOException {
         path.setTimes(lastModifiedTime, lastAccessTime, createTime);
     }
 
     void setAttribute(String attribute, Object value)
-        throws IOException
-    {
+            throws IOException {
         try {
-            if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime)
-                setTimes ((FileTime)value, null, null);
-            if (AttrID.valueOf(attribute) == AttrID.lastAccessTime)
-                setTimes (null, (FileTime)value, null);
-            if (AttrID.valueOf(attribute) == AttrID.creationTime)
-                setTimes (null, null, (FileTime)value);
+            if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime) {
+                setTimes((FileTime) value, null, null);
+            }
+            if (AttrID.valueOf(attribute) == AttrID.lastAccessTime) {
+                setTimes(null, (FileTime) value, null);
+            }
+            if (AttrID.valueOf(attribute) == AttrID.creationTime) {
+                setTimes(null, null, (FileTime) value);
+            }
             return;
-        } catch (IllegalArgumentException x) {}
-        throw new UnsupportedOperationException("'" + attribute +
-            "' is unknown or read-only attribute");
+        } catch (IllegalArgumentException x) {
+        }
+        throw new UnsupportedOperationException("'" + attribute
+                + "' is unknown or read-only attribute");
     }
 
     Map<String, Object> readAttributes(String attributes)
-        throws IOException
-    {
-        JrtFileAttributes jrtfas = readAttributes();
+            throws IOException {
+        AbstractJrtFileAttributes jrtfas = readAttributes();
         LinkedHashMap<String, Object> map = new LinkedHashMap<>();
         if ("*".equals(attributes)) {
             for (AttrID id : AttrID.values()) {
                 try {
                     map.put(id.name(), attribute(id, jrtfas));
-                } catch (IllegalArgumentException x) {}
+                } catch (IllegalArgumentException x) {
+                }
             }
         } else {
             String[] as = attributes.split(",");
             for (String a : as) {
                 try {
                     map.put(a, attribute(AttrID.valueOf(a), jrtfas));
-                } catch (IllegalArgumentException x) {}
+                } catch (IllegalArgumentException x) {
+                }
             }
         }
         return map;
     }
 
-    Object attribute(AttrID id, JrtFileAttributes jrtfas) {
+    Object attribute(AttrID id, AbstractJrtFileAttributes jrtfas) {
         switch (id) {
-        case size:
-            return jrtfas.size();
-        case creationTime:
-            return jrtfas.creationTime();
-        case lastAccessTime:
-            return jrtfas.lastAccessTime();
-        case lastModifiedTime:
-            return jrtfas.lastModifiedTime();
-        case isDirectory:
-            return jrtfas.isDirectory();
-        case isRegularFile:
-            return jrtfas.isRegularFile();
-        case isSymbolicLink:
-            return jrtfas.isSymbolicLink();
-        case isOther:
-            return jrtfas.isOther();
-        case fileKey:
-            return jrtfas.fileKey();
-        case compressedSize:
-            if (isJrtView)
-                return jrtfas.compressedSize();
-            break;
-        case extension:
-            if (isJrtView) {
-                return jrtfas.extension();
-            }
-            break;
+            case size:
+                return jrtfas.size();
+            case creationTime:
+                return jrtfas.creationTime();
+            case lastAccessTime:
+                return jrtfas.lastAccessTime();
+            case lastModifiedTime:
+                return jrtfas.lastModifiedTime();
+            case isDirectory:
+                return jrtfas.isDirectory();
+            case isRegularFile:
+                return jrtfas.isRegularFile();
+            case isSymbolicLink:
+                return jrtfas.isSymbolicLink();
+            case isOther:
+                return jrtfas.isOther();
+            case fileKey:
+                return jrtfas.fileKey();
+            case compressedSize:
+                if (isJrtView) {
+                    return jrtfas.compressedSize();
+                }
+                break;
+            case extension:
+                if (isJrtView) {
+                    return jrtfas.extension();
+                }
+                break;
         }
         return null;
     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java
index f09dec55..9293b1f 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileAttributes.java
@@ -22,16 +22,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
-import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.attribute.FileTime;
-import java.util.Formatter;
 import jdk.internal.jimage.ImageReader.Node;
 
-final class JrtFileAttributes implements BasicFileAttributes
-{
+/**
+ * File attributes implementation for jrt image file system.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+final class JrtFileAttributes extends AbstractJrtFileAttributes {
+
     private final Node node;
 
     JrtFileAttributes(Node node) {
@@ -85,37 +91,13 @@
     }
 
     ///////// jrt entry attributes ///////////
+    @Override
     public long compressedSize() {
         return node.compressedSize();
     }
 
+    @Override
     public String extension() {
         return node.extension();
     }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder(1024);
-        try (Formatter fm = new Formatter(sb)) {
-            if (creationTime() != null)
-                fm.format("    creationTime    : %tc%n", creationTime().toMillis());
-            else
-                fm.format("    creationTime    : null%n");
-
-            if (lastAccessTime() != null)
-                fm.format("    lastAccessTime  : %tc%n", lastAccessTime().toMillis());
-            else
-                fm.format("    lastAccessTime  : null%n");
-            fm.format("    lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
-            fm.format("    isRegularFile   : %b%n", isRegularFile());
-            fm.format("    isDirectory     : %b%n", isDirectory());
-            fm.format("    isSymbolicLink  : %b%n", isSymbolicLink());
-            fm.format("    isOther         : %b%n", isOther());
-            fm.format("    fileKey         : %s%n", fileKey());
-            fm.format("    size            : %d%n", size());
-            fm.format("    compressedSize  : %d%n", compressedSize());
-            fm.format("    extension       : %s%n", extension());
-        }
-        return sb.toString();
-    }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java
index d0a5773..09a1f09 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java
@@ -22,23 +22,29 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
 import java.io.IOException;
-import java.nio.file.Files;
 import java.nio.file.FileStore;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
+import java.nio.file.FileSystem;
 import java.nio.file.attribute.FileAttributeView;
-import java.nio.file.attribute.FileStoreAttributeView;
 import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileStoreAttributeView;
 
+/**
+ * File store implementation for jrt file systems.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 final class JrtFileStore extends FileStore {
 
-    private final JrtFileSystem jrtfs;
+    protected final FileSystem jrtfs;
 
-    JrtFileStore(JrtPath jrtPath) {
+    JrtFileStore(AbstractJrtPath jrtPath) {
         this.jrtfs = jrtPath.getFileSystem();
     }
 
@@ -58,12 +64,6 @@
     }
 
     @Override
-    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
-        return (type == BasicFileAttributeView.class ||
-                type == JrtFileAttributeView.class);
-    }
-
-    @Override
     public boolean supportsFileAttributeView(String name) {
         return name.equals("basic") || name.equals("jrt");
     }
@@ -71,28 +71,35 @@
     @Override
     @SuppressWarnings("unchecked")
     public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
-        if (type == null)
+        if (type == null) {
             throw new NullPointerException();
-        return (V)null;
+        }
+        return (V) null;
     }
 
     @Override
     public long getTotalSpace() throws IOException {
-         throw new UnsupportedOperationException("getTotalSpace");
+        throw new UnsupportedOperationException("getTotalSpace");
     }
 
     @Override
     public long getUsableSpace() throws IOException {
-         throw new UnsupportedOperationException("getUsableSpace");
+        throw new UnsupportedOperationException("getUsableSpace");
     }
 
     @Override
     public long getUnallocatedSpace() throws IOException {
-         throw new UnsupportedOperationException("getUnallocatedSpace");
+        throw new UnsupportedOperationException("getUnallocatedSpace");
     }
 
     @Override
     public Object getAttribute(String attribute) throws IOException {
-         throw new UnsupportedOperationException("does not support " + attribute);
+        throw new UnsupportedOperationException("does not support " + attribute);
+    }
+
+    @Override
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        return (type == BasicFileAttributeView.class
+                || type == JrtFileAttributeView.class);
     }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
index 641428b..84a7a34 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java
@@ -24,73 +24,44 @@
  */
 package jdk.internal.jrtfs;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.nio.charset.Charset;
-import java.nio.file.ClosedFileSystemException;
-import java.nio.file.CopyOption;
 import java.nio.file.LinkOption;
-import java.nio.file.FileStore;
-import java.nio.file.FileSystem;
 import java.nio.file.FileSystemException;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.NotDirectoryException;
-import java.nio.file.OpenOption;
 import java.nio.file.Path;
-import java.nio.file.PathMatcher;
-import java.nio.file.ReadOnlyFileSystemException;
-import java.nio.file.StandardOpenOption;
-import java.nio.file.WatchService;
-import java.nio.file.attribute.FileAttribute;
-import java.nio.file.attribute.FileTime;
-import java.nio.file.attribute.UserPrincipalLookupService;
-import java.nio.file.spi.FileSystemProvider;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.function.Function;
-import java.util.regex.Pattern;
 import static java.util.stream.Collectors.toList;
 import jdk.internal.jimage.ImageReader;
 import jdk.internal.jimage.ImageReader.Node;
-import jdk.internal.jimage.UTF8String;
+
 
 /**
- * A FileSystem built on System jimage files.
+ * jrt file system implementation built on System jimage files.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
  */
-class JrtFileSystem extends FileSystem {
-    private static final Charset UTF_8 = Charset.forName("UTF-8");
+class JrtFileSystem extends AbstractJrtFileSystem {
 
-    private final JrtFileSystemProvider provider;
-    // System image readers
+    // System image reader
     private ImageReader bootImage;
-    private ImageReader extImage;
-    private ImageReader appImage;
     // root path
     private final JrtPath rootPath;
     private volatile boolean isOpen;
 
-    private static void checkExists(Path path) {
-        if (Files.notExists(path)) {
-            throw new FileSystemNotFoundException(path.toString());
-        }
-    }
-
     // open a .jimage and build directory structure
     private static ImageReader openImage(Path path) throws IOException {
-        ImageReader image = ImageReader.open(path.toString());
+        ImageReader image = ImageReader.open(path);
         image.getRootDirectory();
         return image;
     }
@@ -98,31 +69,18 @@
     JrtFileSystem(JrtFileSystemProvider provider,
             Map<String, ?> env)
             throws IOException {
-        this.provider = provider;
-        checkExists(SystemImages.bootImagePath);
-        checkExists(SystemImages.extImagePath);
-        checkExists(SystemImages.appImagePath);
+        super(provider, env);
+        checkExists(SystemImages.moduleImageFile());
 
-        // open image files
-        this.bootImage = openImage(SystemImages.bootImagePath);
-        this.extImage = openImage(SystemImages.extImagePath);
-        this.appImage = openImage(SystemImages.appImagePath);
+        // open image file
+        this.bootImage = openImage(SystemImages.moduleImageFile());
 
-        byte[] root = new byte[] { '/' };
+        byte[] root = new byte[]{'/'};
         rootPath = new JrtPath(this, root);
         isOpen = true;
     }
 
-    @Override
-    public FileSystemProvider provider() {
-        return provider;
-    }
-
-    @Override
-    public String getSeparator() {
-        return "/";
-    }
-
+    // FileSystem method implementations
     @Override
     public boolean isOpen() {
         return isOpen;
@@ -134,191 +92,139 @@
     }
 
     @Override
-    protected void finalize() {
+    protected void finalize() throws Throwable {
         try {
             cleanup();
-        } catch (IOException ignored) {}
+        } catch (IOException ignored) {
+        }
+        super.finalize();
     }
 
+    // AbstractJrtFileSystem method implementations
+    @Override
+    JrtPath getRootPath() {
+        return rootPath;
+    }
+
+    @Override
+    boolean isSameFile(AbstractJrtPath p1, AbstractJrtPath p2) throws IOException {
+        ensureOpen();
+        Node node1 = findNode(p1);
+        Node node2 = findNode(p2);
+        return node1.equals(node2);
+    }
+
+    @Override
+    boolean isLink(AbstractJrtPath jrtPath) throws IOException {
+        return checkNode(jrtPath).isLink();
+    }
+
+    @Override
+    AbstractJrtPath resolveLink(AbstractJrtPath jrtPath) throws IOException {
+        Node node = checkNode(jrtPath);
+        if (node.isLink()) {
+            node = node.resolveLink();
+            return toJrtPath(getBytes(node.getName()));
+        }
+
+        return jrtPath;
+    }
+
+    @Override
+    JrtFileAttributes getFileAttributes(AbstractJrtPath jrtPath, LinkOption... options)
+            throws IOException {
+        Node node = checkNode(jrtPath);
+        if (node.isLink() && followLinks(options)) {
+            return new JrtFileAttributes(node.resolveLink(true));
+        }
+        return new JrtFileAttributes(node);
+    }
+
+    @Override
+    boolean exists(AbstractJrtPath jrtPath) throws IOException {
+        try {
+            checkNode(jrtPath);
+        } catch (NoSuchFileException exp) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    boolean isDirectory(AbstractJrtPath jrtPath, boolean resolveLinks)
+            throws IOException {
+        Node node = checkNode(jrtPath);
+        return resolveLinks && node.isLink()
+                ? node.resolveLink(true).isDirectory()
+                : node.isDirectory();
+    }
+
+    @Override
+    Iterator<Path> iteratorOf(AbstractJrtPath jrtPath) throws IOException {
+        Node node = checkNode(jrtPath).resolveLink(true);
+        if (!node.isDirectory()) {
+            throw new NotDirectoryException(getString(jrtPath.getName()));
+        }
+
+        if (node.isRootDir()) {
+            return rootDirIterator(jrtPath);
+        } else if (node.isModulesDir()) {
+            return modulesDirIterator(jrtPath);
+        } else if (node.isPackagesDir()) {
+            return packagesDirIterator(jrtPath);
+        }
+
+        return nodesToIterator(jrtPath, node.getChildren());
+    }
+
+    @Override
+    byte[] getFileContent(AbstractJrtPath jrtPath) throws IOException {
+        final Node node = checkResource(jrtPath);
+        return bootImage.getResource(node);
+    }
+
+    // Implementation details below this point
     // clean up this file system - called from finalize and close
     private void cleanup() throws IOException {
         if (!isOpen) {
             return;
         }
 
-        synchronized(this) {
+        synchronized (this) {
             isOpen = false;
 
             // close all image reader and null out
             bootImage.close();
             bootImage = null;
-            extImage.close();
-            extImage = null;
-            appImage.close();
-            appImage = null;
         }
     }
 
-    private void ensureOpen() throws IOException {
-        if (!isOpen) {
-            throw new ClosedFileSystemException();
+    private Node lookup(byte[] path) {
+        Node node = null;
+        try {
+            node = bootImage.findNode(getString(path));
+        } catch (RuntimeException re) {
+            throw new InvalidPathException(getString(path), re.toString());
         }
+        return node;
     }
 
-    @Override
-    public boolean isReadOnly() {
-        return true;
-    }
-
-    private ReadOnlyFileSystemException readOnly() {
-        return new ReadOnlyFileSystemException();
-    }
-
-    @Override
-    public Iterable<Path> getRootDirectories() {
-        ArrayList<Path> pathArr = new ArrayList<>();
-        pathArr.add(rootPath);
-        return pathArr;
-    }
-
-    JrtPath getRootPath() {
-        return rootPath;
-    }
-
-    @Override
-    public JrtPath getPath(String first, String... more) {
-        String path;
-        if (more.length == 0) {
-            path = first;
-        } else {
-            StringBuilder sb = new StringBuilder();
-            sb.append(first);
-            for (String segment : more) {
-                if (segment.length() > 0) {
-                    if (sb.length() > 0) {
-                        sb.append('/');
-                    }
-                    sb.append(segment);
-                }
-            }
-            path = sb.toString();
-        }
-        return new JrtPath(this, getBytes(path));
-    }
-
-    @Override
-    public UserPrincipalLookupService getUserPrincipalLookupService() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public WatchService newWatchService() {
-        throw new UnsupportedOperationException();
-    }
-
-    FileStore getFileStore(JrtPath path) {
-        return new JrtFileStore(path);
-    }
-
-    @Override
-    public Iterable<FileStore> getFileStores() {
-        ArrayList<FileStore> list = new ArrayList<>(1);
-        list.add(new JrtFileStore(new JrtPath(this, new byte[]{'/'})));
-        return list;
-    }
-
-    private static final Set<String> supportedFileAttributeViews
-            = Collections.unmodifiableSet(
-                    new HashSet<String>(Arrays.asList("basic", "jrt")));
-
-    @Override
-    public Set<String> supportedFileAttributeViews() {
-        return supportedFileAttributeViews;
-    }
-
-    @Override
-    public String toString() {
-        return "jrt:/";
-    }
-
-    private static final String GLOB_SYNTAX = "glob";
-    private static final String REGEX_SYNTAX = "regex";
-
-    @Override
-    public PathMatcher getPathMatcher(String syntaxAndInput) {
-        int pos = syntaxAndInput.indexOf(':');
-        if (pos <= 0 || pos == syntaxAndInput.length()) {
-            throw new IllegalArgumentException();
-        }
-        String syntax = syntaxAndInput.substring(0, pos);
-        String input = syntaxAndInput.substring(pos + 1);
-        String expr;
-        if (syntax.equalsIgnoreCase(GLOB_SYNTAX)) {
-            expr = JrtUtils.toRegexPattern(input);
-        } else {
-            if (syntax.equalsIgnoreCase(REGEX_SYNTAX)) {
-                expr = input;
-            } else {
-                throw new UnsupportedOperationException("Syntax '" + syntax
-                        + "' not recognized");
-            }
-        }
-        // return matcher
-        final Pattern pattern = Pattern.compile(expr);
-        return (Path path) -> pattern.matcher(path.toString()).matches();
-    }
-
-    static byte[] getBytes(String name) {
-        return name.getBytes(UTF_8);
-    }
-
-    static String getString(byte[] name) {
-        return new String(name, UTF_8);
-    }
-
-    private static class NodeAndImage {
-        final Node node;
-        final ImageReader image;
-
-        NodeAndImage(Node node, ImageReader image) {
-            this.node = node; this.image = image;
-        }
-
-        byte[] getResource() throws IOException {
-            return image.getResource(node);
-        }
-    }
-
-    private NodeAndImage lookup(byte[] path) {
-        Node node = bootImage.findNode(path);
-        ImageReader image = bootImage;
-        if (node == null) {
-            node = extImage.findNode(path);
-            image = extImage;
-        }
-        if (node == null) {
-            node = appImage.findNode(path);
-            image = appImage;
-        }
-        return node != null? new NodeAndImage(node, image) : null;
-    }
-
-    private NodeAndImage lookupSymbolic(byte[] path) {
+    private Node lookupSymbolic(byte[] path) {
         for (int i = 1; i < path.length; i++) {
-            if (path[i] == (byte)'/') {
+            if (path[i] == (byte) '/') {
                 byte[] prefix = Arrays.copyOfRange(path, 0, i);
-                NodeAndImage ni = lookup(prefix);
-                if (ni == null) {
+                Node node = lookup(prefix);
+                if (node == null) {
                     break;
                 }
 
-                if (ni.node.isLink()) {
-                    Node link = ni.node.resolveLink(true);
+                if (node.isLink()) {
+                    Node link = node.resolveLink(true);
                     // resolved symbolic path concatenated to the rest of the path
-                    UTF8String resPath = link.getName().concat(new UTF8String(path, i));
-                    byte[] resPathBytes = resPath.getBytesCopy();
-                    ni = lookup(resPathBytes);
-                    return ni != null? ni : lookupSymbolic(resPathBytes);
+                    String resPath = link.getName() + getString(path).substring(i);
+                    byte[] resPathBytes = getBytes(resPath);
+                    node = lookup(resPathBytes);
+                    return node != null ? node : lookupSymbolic(resPathBytes);
                 }
             }
         }
@@ -326,336 +232,100 @@
         return null;
     }
 
-    private NodeAndImage findNode(byte[] path) throws IOException {
-        NodeAndImage ni = lookup(path);
-        if (ni == null) {
-            ni = lookupSymbolic(path);
-            if (ni == null) {
+    private Node findNode(AbstractJrtPath jrtPath) throws IOException {
+        return findNode(jrtPath.getResolvedPath());
+    }
+
+    private Node findNode(byte[] path) throws IOException {
+        Node node = lookup(path);
+        if (node == null) {
+            node = lookupSymbolic(path);
+            if (node == null) {
                 throw new NoSuchFileException(getString(path));
             }
         }
-        return ni;
+        return node;
     }
 
-    private NodeAndImage checkNode(byte[] path) throws IOException {
+    private Node checkNode(AbstractJrtPath jrtPath) throws IOException {
+        return checkNode(jrtPath.getResolvedPath());
+    }
+
+    private Node checkNode(byte[] path) throws IOException {
         ensureOpen();
         return findNode(path);
     }
 
-    private NodeAndImage checkResource(byte[] path) throws IOException {
-        NodeAndImage ni = checkNode(path);
-        if (ni.node.isDirectory()) {
+    private Node checkResource(AbstractJrtPath jrtPath) throws IOException {
+        return checkResource(jrtPath.getResolvedPath());
+    }
+
+    private Node checkResource(byte[] path) throws IOException {
+        Node node = checkNode(path);
+        if (node.isDirectory()) {
             throw new FileSystemException(getString(path) + " is a directory");
         }
 
-        assert ni.node.isResource() : "resource node expected here";
-        return ni;
+        assert node.isResource() : "resource node expected here";
+        return node;
     }
 
-    static boolean followLinks(LinkOption... options) {
-        if (options != null) {
-            for (LinkOption lo : options) {
-                if (lo == LinkOption.NOFOLLOW_LINKS) {
-                    return false;
-                } else if (lo == null) {
-                    throw new NullPointerException();
-                } else {
-                    throw new AssertionError("should not reach here");
-                }
-            }
-        }
-        return true;
-    }
-
-    // package private helpers
-    JrtFileAttributes getFileAttributes(byte[] path, LinkOption... options)
-            throws IOException {
-        NodeAndImage ni = checkNode(path);
-        if (ni.node.isLink() && followLinks(options)) {
-            return new JrtFileAttributes(ni.node.resolveLink(true));
-        }
-        return new JrtFileAttributes(ni.node);
-    }
-
-    void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
-            throws IOException {
-        throw readOnly();
-    }
-
-    boolean exists(byte[] path) throws IOException {
-        ensureOpen();
-        try {
-            findNode(path);
-        } catch (NoSuchFileException exp) {
-            return false;
-        }
-        return true;
-    }
-
-    boolean isDirectory(byte[] path, boolean resolveLinks)
-            throws IOException {
-        ensureOpen();
-        NodeAndImage ni = checkNode(path);
-        return resolveLinks && ni.node.isLink()?
-            ni.node.resolveLink(true).isDirectory() :
-            ni.node.isDirectory();
-    }
-
-    JrtPath toJrtPath(String path) {
+    private JrtPath toJrtPath(String path) {
         return toJrtPath(getBytes(path));
     }
 
-    JrtPath toJrtPath(byte[] path) {
+    private JrtPath toJrtPath(byte[] path) {
         return new JrtPath(this, path);
     }
 
-    boolean isSameFile(JrtPath p1, JrtPath p2) throws IOException {
-        NodeAndImage n1 = findNode(p1.getName());
-        NodeAndImage n2 = findNode(p2.getName());
-        return n1.node.equals(n2.node);
-    }
-
-    boolean isLink(JrtPath jrtPath) throws IOException {
-        return findNode(jrtPath.getName()).node.isLink();
-    }
-
-    JrtPath resolveLink(JrtPath jrtPath) throws IOException {
-        NodeAndImage ni = findNode(jrtPath.getName());
-        if (ni.node.isLink()) {
-            Node node = ni.node.resolveLink();
-            return toJrtPath(node.getName().getBytesCopy());
-        }
-
-        return jrtPath;
-    }
-
-    private Map<UTF8String, List<Node>> packagesTreeChildren = new ConcurrentHashMap<>();
-
-    /**
-     * returns the list of child paths of the given directory "path"
-     *
-     * @param path name of the directory whose content is listed
-     * @param childPrefix prefix added to returned children names - may be null
-              in which case absolute child paths are returned
-     * @return iterator for child paths of the given directory path
-     */
-    Iterator<Path> iteratorOf(byte[] path, String childPrefix)
-            throws IOException {
-        NodeAndImage ni = checkNode(path);
-        Node node = ni.node.resolveLink(true);
-
-        if (!node.isDirectory()) {
-            throw new NotDirectoryException(getString(path));
-        }
-
-        if (node.isRootDir()) {
-            return rootDirIterator(path, childPrefix);
-        } else if (node.isModulesDir()) {
-            return modulesDirIterator(path, childPrefix);
-        } else if (node.isPackagesDir()) {
-            return packagesDirIterator(path, childPrefix);
-        } else if (node.getNameString().startsWith("/packages/")) {
-            if (ni.image != appImage) {
-                UTF8String name = node.getName();
-                List<Node> children = packagesTreeChildren.get(name);
-                if (children != null) {
-                    return nodesToIterator(toJrtPath(path), childPrefix, children);
-                }
-
-                children = new ArrayList<>();
-                children.addAll(node.getChildren());
-                Node tmpNode = null;
-                // found in boot
-                if (ni.image == bootImage) {
-                    tmpNode = extImage.findNode(name);
-                    if (tmpNode != null) {
-                        children.addAll(tmpNode.getChildren());
-                    }
-                }
-
-                // found in ext
-                tmpNode = appImage.findNode(name);
-                if (tmpNode != null) {
-                    children.addAll(tmpNode.getChildren());
-                }
-
-                packagesTreeChildren.put(name, children);
-                return nodesToIterator(toJrtPath(path), childPrefix, children);
-            }
-        }
-
-        return nodesToIterator(toJrtPath(path), childPrefix, node.getChildren());
-    }
-
-    private Iterator<Path> nodesToIterator(Path path, String childPrefix, List<Node> childNodes) {
-        Function<Node, Path> f = childPrefix == null
-                ? child -> toJrtPath(child.getNameString())
-                : child -> toJrtPath(childPrefix + child.getNameString().substring(1));
-         return childNodes.stream().map(f).collect(toList()).iterator();
-    }
-
-    private void addRootDirContent(List<Node> children) {
-        for (Node child : children) {
-            if (!(child.isModulesDir() || child.isPackagesDir())) {
-                rootChildren.add(child);
-            }
-        }
+    private Iterator<Path> nodesToIterator(AbstractJrtPath dir, List<Node> childNodes) {
+        Function<Node, Path> nodeToPath =
+            child -> dir.resolve(
+                toJrtPath(child.getNameString()).getFileName());
+        return childNodes.stream().
+                map(nodeToPath).collect(toList()).
+                iterator();
     }
 
     private List<Node> rootChildren;
-    private synchronized void initRootChildren(byte[] path) {
+
+    private synchronized void initRootChildren(AbstractJrtPath jrtPath) throws IOException {
         if (rootChildren == null) {
             rootChildren = new ArrayList<>();
-            rootChildren.addAll(bootImage.findNode(path).getChildren());
-            addRootDirContent(extImage.findNode(path).getChildren());
-            addRootDirContent(appImage.findNode(path).getChildren());
+            rootChildren.addAll(findNode(jrtPath).getChildren());
         }
     }
 
-    private Iterator<Path> rootDirIterator(byte[] path, String childPrefix) throws IOException {
-        initRootChildren(path);
-        return nodesToIterator(rootPath, childPrefix, rootChildren);
+    private Iterator<Path> rootDirIterator(AbstractJrtPath jrtPath) throws IOException {
+        initRootChildren(jrtPath);
+        return nodesToIterator(jrtPath, rootChildren);
     }
 
     private List<Node> modulesChildren;
-    private synchronized void initModulesChildren(byte[] path) {
+
+    private synchronized void initModulesChildren(AbstractJrtPath jrtPath) throws IOException {
         if (modulesChildren == null) {
             modulesChildren = new ArrayList<>();
-            modulesChildren.addAll(bootImage.findNode(path).getChildren());
-            modulesChildren.addAll(appImage.findNode(path).getChildren());
-            modulesChildren.addAll(extImage.findNode(path).getChildren());
+            modulesChildren.addAll(findNode(jrtPath).getChildren());
         }
     }
 
-    private Iterator<Path> modulesDirIterator(byte[] path, String childPrefix) throws IOException {
-        initModulesChildren(path);
-        return nodesToIterator(new JrtPath(this, path), childPrefix, modulesChildren);
+    private Iterator<Path> modulesDirIterator(AbstractJrtPath jrtPath) throws IOException {
+        initModulesChildren(jrtPath);
+        return nodesToIterator(jrtPath, modulesChildren);
     }
 
     private List<Node> packagesChildren;
-    private synchronized void initPackagesChildren(byte[] path) {
+
+    private synchronized void initPackagesChildren(AbstractJrtPath jrtPath) throws IOException {
         if (packagesChildren == null) {
             packagesChildren = new ArrayList<>();
-            packagesChildren.addAll(bootImage.findNode(path).getChildren());
-            packagesChildren.addAll(extImage.findNode(path).getChildren());
-            packagesChildren.addAll(appImage.findNode(path).getChildren());
-        }
-    }
-    private Iterator<Path> packagesDirIterator(byte[] path, String childPrefix) throws IOException {
-        initPackagesChildren(path);
-        return nodesToIterator(new JrtPath(this, path), childPrefix, packagesChildren);
-    }
-
-    void createDirectory(byte[] dir, FileAttribute<?>... attrs)
-            throws IOException {
-        throw readOnly();
-    }
-
-    void copyFile(boolean deletesrc, byte[] src, byte[] dst, CopyOption... options)
-            throws IOException {
-        throw readOnly();
-    }
-
-    public void deleteFile(byte[] path, boolean failIfNotExists)
-            throws IOException {
-        throw readOnly();
-    }
-
-    OutputStream newOutputStream(byte[] path, OpenOption... options)
-            throws IOException {
-        throw readOnly();
-    }
-
-    private void checkOptions(Set<? extends OpenOption> options) {
-        // check for options of null type and option is an intance of StandardOpenOption
-        for (OpenOption option : options) {
-            if (option == null) {
-                throw new NullPointerException();
-            }
-            if (!(option instanceof StandardOpenOption)) {
-                throw new IllegalArgumentException();
-            }
+            packagesChildren.addAll(findNode(jrtPath).getChildren());
         }
     }
 
-    // Returns an input stream for reading the contents of the specified
-    // file entry.
-    InputStream newInputStream(byte[] path) throws IOException {
-        final NodeAndImage ni = checkResource(path);
-        return new ByteArrayInputStream(ni.getResource());
-    }
-
-    SeekableByteChannel newByteChannel(byte[] path,
-            Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        checkOptions(options);
-        if (options.contains(StandardOpenOption.WRITE)
-                || options.contains(StandardOpenOption.APPEND)) {
-            throw readOnly();
-        }
-
-        NodeAndImage ni = checkResource(path);
-        byte[] buf = ni.getResource();
-        final ReadableByteChannel rbc
-                = Channels.newChannel(new ByteArrayInputStream(buf));
-        final long size = buf.length;
-        return new SeekableByteChannel() {
-            long read = 0;
-
-            @Override
-            public boolean isOpen() {
-                return rbc.isOpen();
-            }
-
-            @Override
-            public long position() throws IOException {
-                return read;
-            }
-
-            @Override
-            public SeekableByteChannel position(long pos)
-                    throws IOException {
-                throw new UnsupportedOperationException();
-            }
-
-            @Override
-            public int read(ByteBuffer dst) throws IOException {
-                int n = rbc.read(dst);
-                if (n > 0) {
-                    read += n;
-                }
-                return n;
-            }
-
-            @Override
-            public SeekableByteChannel truncate(long size)
-                    throws IOException {
-                throw new NonWritableChannelException();
-            }
-
-            @Override
-            public int write(ByteBuffer src) throws IOException {
-                throw new NonWritableChannelException();
-            }
-
-            @Override
-            public long size() throws IOException {
-                return size;
-            }
-
-            @Override
-            public void close() throws IOException {
-                rbc.close();
-            }
-        };
-    }
-
-    // Returns a FileChannel of the specified path.
-    FileChannel newFileChannel(byte[] path,
-            Set<? extends OpenOption> options,
-            FileAttribute<?>... attrs)
-            throws IOException {
-        throw new UnsupportedOperationException("newFileChannel");
+    private Iterator<Path> packagesDirIterator(AbstractJrtPath jrtPath) throws IOException {
+        initPackagesChildren(jrtPath);
+        return nodesToIterator(jrtPath, packagesChildren);
     }
 }
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 54beafd..1cae4a5 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
@@ -22,26 +22,42 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
 import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
 import java.nio.channels.*;
 import java.nio.file.*;
 import java.nio.file.DirectoryStream.Filter;
 import java.nio.file.attribute.*;
 import java.nio.file.spi.FileSystemProvider;
 import java.net.URI;
-import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 
+/**
+ * File system provider for jrt file systems. Conditionally creates jrt fs on
+ * .jimage file or exploded modules directory of underlying JDK.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 public final class JrtFileSystemProvider extends FileSystemProvider {
+
     private volatile FileSystem theFileSystem;
 
-    public JrtFileSystemProvider() { }
+    public JrtFileSystemProvider() {
+    }
 
     @Override
     public String getScheme() {
@@ -55,50 +71,132 @@
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             String home = SystemImages.RUNTIME_HOME;
-            FilePermission perm =
-                new FilePermission(home + File.separator + "-", "read");
+            FilePermission perm
+                    = new FilePermission(home + File.separator + "-", "read");
             sm.checkPermission(perm);
         }
     }
 
     private void checkUri(URI uri) {
-        if (!uri.getScheme().equalsIgnoreCase(getScheme()))
+        if (!uri.getScheme().equalsIgnoreCase(getScheme())) {
             throw new IllegalArgumentException("URI does not match this provider");
-        if (uri.getAuthority() != null)
+        }
+        if (uri.getAuthority() != null) {
             throw new IllegalArgumentException("Authority component present");
-        if (uri.getPath() == null)
+        }
+        if (uri.getPath() == null) {
             throw new IllegalArgumentException("Path component is undefined");
-        if (!uri.getPath().equals("/"))
+        }
+        if (!uri.getPath().equals("/")) {
             throw new IllegalArgumentException("Path component should be '/'");
-        if (uri.getQuery() != null)
+        }
+        if (uri.getQuery() != null) {
             throw new IllegalArgumentException("Query component present");
-        if (uri.getFragment() != null)
+        }
+        if (uri.getFragment() != null) {
             throw new IllegalArgumentException("Fragment component present");
+        }
     }
 
     @Override
     public FileSystem newFileSystem(URI uri, Map<String, ?> env)
-        throws IOException
-    {
+            throws IOException {
         checkPermission();
         checkUri(uri);
-        return new JrtFileSystem(this, env);
+
+        if (env != null && env.containsKey("java.home")) {
+            return newFileSystem((String)env.get("java.home"), uri, env);
+        } else {
+            return SystemImages.hasModulesImage()
+                    ? new JrtFileSystem(this, env)
+                    : new JrtExplodedFileSystem(this, env);
+        }
+    }
+
+    private static final String JRT_FS_JAR = "jrt-fs.jar";
+    private FileSystem newFileSystem(String targetHome, URI uri, Map<String, ?> env)
+            throws IOException {
+        Objects.requireNonNull(targetHome);
+        Path jrtfs = FileSystems.getDefault().getPath(targetHome, JRT_FS_JAR);
+        if (Files.notExists(jrtfs)) {
+            throw new IOException(jrtfs.toString() + " not exist");
+        }
+
+        Map<String,?> newEnv = new HashMap<>(env);
+        newEnv.remove("java.home");
+        ClassLoader cl = newJrtFsLoader(jrtfs);
+        try {
+            Class<?> c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl);
+            return ((FileSystemProvider)c.newInstance()).newFileSystem(uri, newEnv);
+        } catch (ClassNotFoundException |
+                 IllegalAccessException |
+                 InstantiationException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private static class JrtFsLoader extends URLClassLoader {
+        JrtFsLoader(URL[] urls) {
+            super(urls);
+        }
+
+        @Override
+        protected Class<?> loadClass(String cn, boolean resolve)
+                throws ClassNotFoundException
+        {
+            Class<?> c = findLoadedClass(cn);
+            if (c == null) {
+                URL u = findResource(cn.replace('.', '/') + ".class");
+                if (u != null) {
+                    c = findClass(cn);
+                } else {
+                    return super.loadClass(cn, resolve);
+                }
+            }
+            if (resolve)
+                resolveClass(c);
+            return c;
+        }
+    }
+
+    private static URLClassLoader newJrtFsLoader(Path jrtfs) {
+        final URL url;
+        try {
+            url = jrtfs.toUri().toURL();
+        } catch (MalformedURLException mue) {
+            throw new IllegalArgumentException(mue);
+        }
+
+        final URL[] urls = new URL[] { url };
+        return AccessController.doPrivileged(
+                new PrivilegedAction<URLClassLoader>() {
+                    @Override
+                    public URLClassLoader run() {
+                        return new JrtFsLoader(urls);
+                    }
+                }
+        );
     }
 
     @Override
     public Path getPath(URI uri) {
         checkPermission();
-        if (!uri.getScheme().equalsIgnoreCase(getScheme()))
+        if (!uri.getScheme().equalsIgnoreCase(getScheme())) {
             throw new IllegalArgumentException("URI does not match this provider");
-        if (uri.getAuthority() != null)
+        }
+        if (uri.getAuthority() != null) {
             throw new IllegalArgumentException("Authority component present");
-        if (uri.getQuery() != null)
+        }
+        if (uri.getQuery() != null) {
             throw new IllegalArgumentException("Query component present");
-        if (uri.getFragment() != null)
+        }
+        if (uri.getFragment() != null) {
             throw new IllegalArgumentException("Fragment component present");
+        }
         String path = uri.getPath();
-        if (path == null || path.charAt(0) != '/')
+        if (path == null || path.charAt(0) != '/') {
             throw new IllegalArgumentException("Invalid path component");
+        }
         return getTheFileSystem().getPath(path);
     }
 
@@ -110,11 +208,21 @@
                 fs = this.theFileSystem;
                 if (fs == null) {
                     try {
-                        this.theFileSystem = fs = new JrtFileSystem(this, null) {
-                            @Override public void close() {
-                                throw new UnsupportedOperationException();
-                            }
-                        };
+                        if (SystemImages.hasModulesImage()) {
+                            this.theFileSystem = fs = new JrtFileSystem(this, null) {
+                                @Override
+                                public void close() {
+                                    throw new UnsupportedOperationException();
+                                }
+                            };
+                        } else {
+                            this.theFileSystem = fs = new JrtExplodedFileSystem(this, null) {
+                                @Override
+                                public void close() {
+                                    throw new UnsupportedOperationException();
+                                }
+                            };
+                        }
                     } catch (IOException ioe) {
                         throw new InternalError(ioe);
                     }
@@ -132,71 +240,69 @@
     }
 
     // Checks that the given file is a JrtPath
-    static final JrtPath toJrtPath(Path path) {
-        if (path == null)
+    static final AbstractJrtPath toAbstractJrtPath(Path path) {
+        if (path == null) {
             throw new NullPointerException();
-        if (!(path instanceof JrtPath))
+        }
+        if (!(path instanceof AbstractJrtPath)) {
             throw new ProviderMismatchException();
-        return (JrtPath)path;
+        }
+        return (AbstractJrtPath) path;
     }
 
     @Override
     public void checkAccess(Path path, AccessMode... modes) throws IOException {
-        toJrtPath(path).checkAccess(modes);
+        toAbstractJrtPath(path).checkAccess(modes);
     }
 
     @Override
     public Path readSymbolicLink(Path link) throws IOException {
-        return toJrtPath(link).readSymbolicLink();
+        return toAbstractJrtPath(link).readSymbolicLink();
     }
 
     @Override
     public void copy(Path src, Path target, CopyOption... options)
-        throws IOException
-    {
-        toJrtPath(src).copy(toJrtPath(target), options);
+            throws IOException {
+        toAbstractJrtPath(src).copy(toAbstractJrtPath(target), options);
     }
 
     @Override
     public void createDirectory(Path path, FileAttribute<?>... attrs)
-        throws IOException
-    {
-        toJrtPath(path).createDirectory(attrs);
+            throws IOException {
+        toAbstractJrtPath(path).createDirectory(attrs);
     }
 
     @Override
     public final void delete(Path path) throws IOException {
-        toJrtPath(path).delete();
+        toAbstractJrtPath(path).delete();
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public <V extends FileAttributeView> V
-        getFileAttributeView(Path path, Class<V> type, LinkOption... options)
-    {
-        return JrtFileAttributeView.get(toJrtPath(path), type, options);
+            getFileAttributeView(Path path, Class<V> type, LinkOption... options) {
+        return JrtFileAttributeView.get(toAbstractJrtPath(path), type, options);
     }
 
     @Override
     public FileStore getFileStore(Path path) throws IOException {
-        return toJrtPath(path).getFileStore();
+        return toAbstractJrtPath(path).getFileStore();
     }
 
     @Override
     public boolean isHidden(Path path) {
-        return toJrtPath(path).isHidden();
+        return toAbstractJrtPath(path).isHidden();
     }
 
     @Override
     public boolean isSameFile(Path path, Path other) throws IOException {
-        return toJrtPath(path).isSameFile(other);
+        return toAbstractJrtPath(path).isSameFile(other);
     }
 
     @Override
     public void move(Path src, Path target, CopyOption... options)
-        throws IOException
-    {
-        toJrtPath(src).move(toJrtPath(target), options);
+            throws IOException {
+        toAbstractJrtPath(src).move(toAbstractJrtPath(target), options);
     }
 
     @Override
@@ -204,74 +310,66 @@
             Set<? extends OpenOption> options,
             ExecutorService exec,
             FileAttribute<?>... attrs)
-            throws IOException
-    {
+            throws IOException {
         throw new UnsupportedOperationException();
     }
 
     @Override
     public SeekableByteChannel newByteChannel(Path path,
-                                              Set<? extends OpenOption> options,
-                                              FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return toJrtPath(path).newByteChannel(options, attrs);
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        return toAbstractJrtPath(path).newByteChannel(options, attrs);
     }
 
     @Override
     public DirectoryStream<Path> newDirectoryStream(
-        Path path, Filter<? super Path> filter) throws IOException
-    {
-        return toJrtPath(path).newDirectoryStream(filter);
+            Path path, Filter<? super Path> filter) throws IOException {
+        return toAbstractJrtPath(path).newDirectoryStream(filter);
     }
 
     @Override
     public FileChannel newFileChannel(Path path,
-                                      Set<? extends OpenOption> options,
-                                      FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return toJrtPath(path).newFileChannel(options, attrs);
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException {
+        return toAbstractJrtPath(path).newFileChannel(options, attrs);
     }
 
     @Override
     public InputStream newInputStream(Path path, OpenOption... options)
-        throws IOException
-    {
-        return toJrtPath(path).newInputStream(options);
+            throws IOException {
+        return toAbstractJrtPath(path).newInputStream(options);
     }
 
     @Override
     public OutputStream newOutputStream(Path path, OpenOption... options)
-        throws IOException
-    {
-        return toJrtPath(path).newOutputStream(options);
+            throws IOException {
+        return toAbstractJrtPath(path).newOutputStream(options);
     }
 
     @Override
     @SuppressWarnings("unchecked") // Cast to A
     public <A extends BasicFileAttributes> A
-        readAttributes(Path path, Class<A> type, LinkOption... options)
-        throws IOException
-    {
-        if (type == BasicFileAttributes.class || type == JrtFileAttributes.class)
-            return (A)toJrtPath(path).getAttributes(options);
+            readAttributes(Path path, Class<A> type, LinkOption... options)
+            throws IOException {
+        if (type == BasicFileAttributes.class || type == JrtFileAttributes.class) {
+            return (A) toAbstractJrtPath(path).getAttributes(options);
+        }
         return null;
     }
 
     @Override
     public Map<String, Object>
-        readAttributes(Path path, String attribute, LinkOption... options)
-        throws IOException
-    {
-        return toJrtPath(path).readAttributes(attribute, options);
+            readAttributes(Path path, String attribute, LinkOption... options)
+            throws IOException {
+        return toAbstractJrtPath(path).readAttributes(attribute, options);
     }
 
     @Override
     public void setAttribute(Path path, String attribute,
-                             Object value, LinkOption... options)
-        throws IOException
-    {
-        toJrtPath(path).setAttribute(attribute, value, options);
+            Object value, LinkOption... options)
+            throws IOException {
+        toAbstractJrtPath(path).setAttribute(attribute, value, options);
     }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
index 175ceaa..3bd0f6c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java
@@ -22,848 +22,34 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
-import java.io.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.channels.*;
-import java.nio.file.*;
-import java.nio.file.DirectoryStream.Filter;
-import java.nio.file.attribute.*;
-import java.util.*;
-import static java.nio.file.StandardOpenOption.*;
-import static java.nio.file.StandardCopyOption.*;
+/**
+ * jrt Path implementation for jrt on .jimage files.
+ *
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
+final class JrtPath extends AbstractJrtPath {
 
-final class JrtPath implements Path {
-
-    private final JrtFileSystem jrtfs;
-    private final byte[] path;
-    private volatile int[] offsets;
-    private int hashcode = 0;  // cached hashcode (created lazily)
-
-    JrtPath(JrtFileSystem jrtfs, byte[] path) {
+    JrtPath(AbstractJrtFileSystem jrtfs, byte[] path) {
         this(jrtfs, path, false);
     }
 
-    JrtPath(JrtFileSystem jrtfs, byte[] path, boolean normalized) {
-        this.jrtfs = jrtfs;
-        if (normalized)
-            this.path = path;
-        else
-            this.path = normalize(path);
-    }
-
-    byte[] getName() {
-        return path;
+    JrtPath(AbstractJrtFileSystem jrtfs, byte[] path, boolean normalized) {
+        super(jrtfs, path, normalized);
     }
 
     @Override
-    public JrtPath getRoot() {
-        if (this.isAbsolute())
-            return jrtfs.getRootPath();
-        else
-            return null;
+    protected JrtPath newJrtPath(byte[] path) {
+        return new JrtPath(jrtfs, path);
     }
 
     @Override
-    public Path getFileName() {
-        initOffsets();
-        int count = offsets.length;
-        if (count == 0)
-            return null;  // no elements so no name
-        if (count == 1 && path[0] != '/')
-            return this;
-        int lastOffset = offsets[count-1];
-        int len = path.length - lastOffset;
-        byte[] result = new byte[len];
-        System.arraycopy(path, lastOffset, result, 0, len);
-        return new JrtPath(jrtfs, result);
-    }
-
-    @Override
-    public JrtPath getParent() {
-        initOffsets();
-        int count = offsets.length;
-        if (count == 0)    // no elements so no parent
-            return null;
-        int len = offsets[count-1] - 1;
-        if (len <= 0)      // parent is root only (may be null)
-            return getRoot();
-        byte[] result = new byte[len];
-        System.arraycopy(path, 0, result, 0, len);
-        return new JrtPath(jrtfs, result);
-    }
-
-    @Override
-    public int getNameCount() {
-        initOffsets();
-        return offsets.length;
-    }
-
-    @Override
-    public JrtPath getName(int index) {
-        initOffsets();
-        if (index < 0 || index >= offsets.length)
-            throw new IllegalArgumentException();
-        int begin = offsets[index];
-        int len;
-        if (index == (offsets.length-1))
-            len = path.length - begin;
-        else
-            len = offsets[index+1] - begin - 1;
-        // construct result
-        byte[] result = new byte[len];
-        System.arraycopy(path, begin, result, 0, len);
-        return new JrtPath(jrtfs, result);
-    }
-
-    @Override
-    public JrtPath subpath(int beginIndex, int endIndex) {
-        initOffsets();
-        if (beginIndex < 0 ||
-            beginIndex >=  offsets.length ||
-            endIndex > offsets.length ||
-            beginIndex >= endIndex)
-            throw new IllegalArgumentException();
-
-        // starting offset and length
-        int begin = offsets[beginIndex];
-        int len;
-        if (endIndex == offsets.length)
-            len = path.length - begin;
-        else
-            len = offsets[endIndex] - begin - 1;
-        // construct result
-        byte[] result = new byte[len];
-        System.arraycopy(path, begin, result, 0, len);
-        return new JrtPath(jrtfs, result);
-    }
-
-    @Override
-    public JrtPath toRealPath(LinkOption... options) throws IOException {
-        JrtPath realPath = new JrtPath(jrtfs, getResolvedPath()).toAbsolutePath();
-        realPath = JrtFileSystem.followLinks(options)? jrtfs.resolveLink(this) : realPath;
-        realPath.checkAccess();
-        return realPath;
-    }
-
-    JrtPath readSymbolicLink() throws IOException {
-        if (! jrtfs.isLink(this)) {
-           throw new IOException("not a symbolic link");
-        }
-
-        return jrtfs.resolveLink(this);
-    }
-
-    boolean isHidden() {
-        return false;
-    }
-
-    @Override
-    public JrtPath toAbsolutePath() {
-        if (isAbsolute()) {
-            return this;
-        } else {
-            //add / bofore the existing path
-            byte[] tmp = new byte[path.length + 1];
-            tmp[0] = '/';
-            System.arraycopy(path, 0, tmp, 1, path.length);
-            return (JrtPath) new JrtPath(jrtfs, tmp).normalize();
-        }
-    }
-
-    @Override
-    public URI toUri() {
-        try {
-            return new URI("jrt",
-                           JrtFileSystem.getString(toAbsolutePath().path),
-                           null);
-        } catch (URISyntaxException ex) {
-            throw new AssertionError(ex);
-        }
-    }
-
-    private boolean equalsNameAt(JrtPath other, int index) {
-        int mbegin = offsets[index];
-        int mlen;
-        if (index == (offsets.length-1))
-            mlen = path.length - mbegin;
-        else
-            mlen = offsets[index + 1] - mbegin - 1;
-        int obegin = other.offsets[index];
-        int olen;
-        if (index == (other.offsets.length - 1))
-            olen = other.path.length - obegin;
-        else
-            olen = other.offsets[index + 1] - obegin - 1;
-        if (mlen != olen)
-            return false;
-        int n = 0;
-        while(n < mlen) {
-            if (path[mbegin + n] != other.path[obegin + n])
-                return false;
-            n++;
-        }
-        return true;
-    }
-
-    @Override
-    public Path relativize(Path other) {
-        final JrtPath o = checkPath(other);
-        if (o.equals(this))
-            return new JrtPath(getFileSystem(), new byte[0], true);
-        if (/* this.getFileSystem() != o.getFileSystem() || */
-            this.isAbsolute() != o.isAbsolute()) {
-            throw new IllegalArgumentException();
-        }
-        int mc = this.getNameCount();
-        int oc = o.getNameCount();
-        int n = Math.min(mc, oc);
-        int i = 0;
-        while (i < n) {
-            if (!equalsNameAt(o, i))
-                break;
-            i++;
-        }
-        int dotdots = mc - i;
-        int len = dotdots * 3 - 1;
-        if (i < oc)
-            len += (o.path.length - o.offsets[i] + 1);
-        byte[] result = new byte[len];
-
-        int pos = 0;
-        while (dotdots > 0) {
-            result[pos++] = (byte)'.';
-            result[pos++] = (byte)'.';
-            if (pos < len)       // no tailing slash at the end
-                result[pos++] = (byte)'/';
-            dotdots--;
-        }
-        if (i < oc)
-            System.arraycopy(o.path, o.offsets[i],
-                             result, pos,
-                             o.path.length - o.offsets[i]);
-        return new JrtPath(getFileSystem(), result);
-    }
-
-    @Override
-    public JrtFileSystem getFileSystem() {
-        return jrtfs;
-    }
-
-    @Override
-    public boolean isAbsolute() {
-        return (this.path.length > 0 && path[0] == '/');
-    }
-
-    @Override
-    public JrtPath resolve(Path other) {
-        final JrtPath o = checkPath(other);
-        if (o.isAbsolute())
-            return o;
-        byte[] res;
-        if (this.path[path.length - 1] == '/') {
-            res = new byte[path.length + o.path.length];
-            System.arraycopy(path, 0, res, 0, path.length);
-            System.arraycopy(o.path, 0, res, path.length, o.path.length);
-        } else {
-            res = new byte[path.length + 1 + o.path.length];
-            System.arraycopy(path, 0, res, 0, path.length);
-            res[path.length] = '/';
-            System.arraycopy(o.path, 0, res, path.length + 1, o.path.length);
-        }
-        return new JrtPath(jrtfs, res);
-    }
-
-    @Override
-    public Path resolveSibling(Path other) {
-        if (other == null)
-            throw new NullPointerException();
-        Path parent = getParent();
-        return (parent == null) ? other : parent.resolve(other);
-    }
-
-    @Override
-    public boolean startsWith(Path other) {
-        final JrtPath o = checkPath(other);
-        if (o.isAbsolute() != this.isAbsolute() ||
-            o.path.length > this.path.length)
-            return false;
-        int olast = o.path.length;
-        for (int i = 0; i < olast; i++) {
-            if (o.path[i] != this.path[i])
-                return false;
-        }
-        olast--;
-        return o.path.length == this.path.length ||
-               o.path[olast] == '/' ||
-               this.path[olast + 1] == '/';
-    }
-
-    @Override
-    public boolean endsWith(Path other) {
-        final JrtPath o = checkPath(other);
-        int olast = o.path.length - 1;
-        if (olast > 0 && o.path[olast] == '/')
-            olast--;
-        int last = this.path.length - 1;
-        if (last > 0 && this.path[last] == '/')
-            last--;
-        if (olast == -1)    // o.path.length == 0
-            return last == -1;
-        if ((o.isAbsolute() &&(!this.isAbsolute() || olast != last)) ||
-            (last < olast))
-            return false;
-        for (; olast >= 0; olast--, last--) {
-            if (o.path[olast] != this.path[last])
-                return false;
-        }
-        return o.path[olast + 1] == '/' ||
-               last == -1 || this.path[last] == '/';
-    }
-
-    @Override
-    public JrtPath resolve(String other) {
-        return resolve(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final Path resolveSibling(String other) {
-        return resolveSibling(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final boolean startsWith(String other) {
-        return startsWith(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final boolean endsWith(String other) {
-        return endsWith(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public Path normalize() {
-        byte[] res = getResolved();
-        if (res == path)    // no change
-            return this;
-        return new JrtPath(jrtfs, res, true);
-    }
-
-    private JrtPath checkPath(Path path) {
-        if (path == null)
-            throw new NullPointerException();
-        if (!(path instanceof JrtPath))
-            throw new ProviderMismatchException();
-        return (JrtPath) path;
-    }
-
-    // create offset list if not already created
-    private void initOffsets() {
-        if (offsets == null) {
-            int count, index;
-            // count names
-            count = 0;
-            index = 0;
-            while (index < path.length) {
-                byte c = path[index++];
-                if (c != '/') {
-                    count++;
-                    while (index < path.length && path[index] != '/')
-                        index++;
-                }
-            }
-            // populate offsets
-            int[] result = new int[count];
-            count = 0;
-            index = 0;
-            while (index < path.length) {
-                byte c = path[index];
-                if (c == '/') {
-                    index++;
-                } else {
-                    result[count++] = index++;
-                    while (index < path.length && path[index] != '/')
-                        index++;
-                }
-            }
-            synchronized (this) {
-                if (offsets == null)
-                    offsets = result;
-            }
-        }
-    }
-
-    // resolved path for locating jrt entry inside the jrt file,
-    // the result path does not contain ./ and .. components
-    // resolved bytes will always start with '/'
-    private volatile byte[] resolved = null;
-    byte[] getResolvedPath() {
-        byte[] r = resolved;
-        if (r == null) {
-            if (isAbsolute())
-                r = getResolved();
-            else
-                r = toAbsolutePath().getResolvedPath();
-            resolved = r;
-        }
-        return resolved;
-    }
-
-    // removes redundant slashs, replace "\" to separator "/"
-    // and check for invalid characters
-    private static byte[] normalize(byte[] path) {
-        if (path.length == 0)
-            return path;
-        byte prevC = 0;
-        for (int i = 0; i < path.length; i++) {
-            byte c = path[i];
-            if (c == '\\')
-                return normalize(path, i);
-            if (c == (byte)'/' && prevC == '/')
-                return normalize(path, i - 1);
-            if (c == '\u0000')
-                throw new InvalidPathException(JrtFileSystem.getString(path),
-                                               "Path: nul character not allowed");
-            prevC = c;
-        }
-
-        if (path.length > 1 && path[path.length - 1] == '/') {
-            return Arrays.copyOf(path, path.length - 1);
-        }
-
-        return path;
-    }
-
-    private static byte[] normalize(byte[] path, int off) {
-        byte[] to = new byte[path.length];
-        int n = 0;
-        while (n < off) {
-            to[n] = path[n];
-            n++;
-        }
-        int m = n;
-        byte prevC = 0;
-        while (n < path.length) {
-            byte c = path[n++];
-            if (c == (byte)'\\')
-                c = (byte)'/';
-            if (c == (byte)'/' && prevC == (byte)'/')
-                continue;
-            if (c == '\u0000')
-                throw new InvalidPathException(JrtFileSystem.getString(path),
-                                               "Path: nul character not allowed");
-            to[m++] = c;
-            prevC = c;
-        }
-        if (m > 1 && to[m - 1] == '/')
-            m--;
-        return (m == to.length)? to : Arrays.copyOf(to, m);
-    }
-
-    // Remove DotSlash(./) and resolve DotDot (..) components
-    private byte[] getResolved() {
-        if (path.length == 0)
-            return path;
-        for (int i = 0; i < path.length; i++) {
-            byte c = path[i];
-            if (c == (byte)'.')
-                return resolve0();
-        }
-
-        return path;
-    }
-
-    // TBD: performance, avoid initOffsets
-    private byte[] resolve0() {
-        byte[] to = new byte[path.length];
-        int nc = getNameCount();
-        int[] lastM = new int[nc];
-        int lastMOff = -1;
-        int m = 0;
-        for (int i = 0; i < nc; i++) {
-            int n = offsets[i];
-            int len = (i == offsets.length - 1)?
-                      (path.length - n):(offsets[i + 1] - n - 1);
-            if (len == 1 && path[n] == (byte)'.') {
-                if (m == 0 && path[0] == '/')   // absolute path
-                    to[m++] = '/';
-                continue;
-            }
-            if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
-                if (lastMOff >= 0) {
-                    m = lastM[lastMOff--];  // retreat
-                    continue;
-                }
-                if (path[0] == '/') {  // "/../xyz" skip
-                    if (m == 0)
-                        to[m++] = '/';
-                } else {               // "../xyz" -> "../xyz"
-                    if (m != 0 && to[m-1] != '/')
-                        to[m++] = '/';
-                    while (len-- > 0)
-                        to[m++] = path[n++];
-                }
-                continue;
-            }
-            if (m == 0 && path[0] == '/' ||   // absolute path
-                m != 0 && to[m-1] != '/') {   // not the first name
-                to[m++] = '/';
-            }
-            lastM[++lastMOff] = m;
-            while (len-- > 0)
-                to[m++] = path[n++];
-        }
-        if (m > 1 && to[m - 1] == '/')
-            m--;
-        return (m == to.length)? to : Arrays.copyOf(to, m);
-    }
-
-    @Override
-    public String toString() {
-        return JrtFileSystem.getString(path);
-    }
-
-    @Override
-    public int hashCode() {
-        int h = hashcode;
-        if (h == 0)
-            hashcode = h = Arrays.hashCode(path);
-        return h;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return obj != null &&
-               obj instanceof JrtPath &&
-               this.jrtfs == ((JrtPath)obj).jrtfs &&
-               compareTo((Path) obj) == 0;
-    }
-
-    @Override
-    public int compareTo(Path other) {
-        final JrtPath o = checkPath(other);
-        int len1 = this.path.length;
-        int len2 = o.path.length;
-
-        int n = Math.min(len1, len2);
-        byte v1[] = this.path;
-        byte v2[] = o.path;
-
-        int k = 0;
-        while (k < n) {
-            int c1 = v1[k] & 0xff;
-            int c2 = v2[k] & 0xff;
-            if (c1 != c2)
-                return c1 - c2;
-            k++;
-        }
-        return len1 - len2;
-    }
-
-    @Override
-    public WatchKey register(
-            WatchService watcher,
-            WatchEvent.Kind<?>[] events,
-            WatchEvent.Modifier... modifiers) {
-        if (watcher == null || events == null || modifiers == null) {
-            throw new NullPointerException();
-        }
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
-        return register(watcher, events, new WatchEvent.Modifier[0]);
-    }
-
-    @Override
-    public final File toFile() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Iterator<Path> iterator() {
-        return new Iterator<Path>() {
-            private int i = 0;
-
-            @Override
-            public boolean hasNext() {
-                return (i < getNameCount());
-            }
-
-            @Override
-            public Path next() {
-                if (i < getNameCount()) {
-                    Path result = getName(i);
-                    i++;
-                    return result;
-                } else {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            @Override
-            public void remove() {
-                throw new ReadOnlyFileSystemException();
-            }
-        };
-    }
-
-    /////////////////////////////////////////////////////////////////////
-    // Helpers for JrtFileSystemProvider and JrtFileSystem
-
-    int getPathLength() {
-        return path.length;
-    }
-
-
-    void createDirectory(FileAttribute<?>... attrs)
-        throws IOException
-    {
-        jrtfs.createDirectory(getResolvedPath(), attrs);
-    }
-
-    InputStream newInputStream(OpenOption... options) throws IOException
-    {
-        if (options.length > 0) {
-            for (OpenOption opt : options) {
-                if (opt != READ)
-                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
-            }
-        }
-        return jrtfs.newInputStream(getResolvedPath());
-    }
-
-    DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
-        throws IOException
-    {
-        return new JrtDirectoryStream(this, filter);
-    }
-
-    void delete() throws IOException {
-        jrtfs.deleteFile(getResolvedPath(), true);
-    }
-
-    void deleteIfExists() throws IOException {
-        jrtfs.deleteFile(getResolvedPath(), false);
-    }
-
-    JrtFileAttributes getAttributes(LinkOption... options) throws IOException
-    {
-        JrtFileAttributes zfas = jrtfs.getFileAttributes(getResolvedPath(), options);
-        if (zfas == null)
-            throw new NoSuchFileException(toString());
-        return zfas;
-    }
-
-    void setAttribute(String attribute, Object value, LinkOption... options)
-        throws IOException
-    {
-        String type;
-        String attr;
-        int colonPos = attribute.indexOf(':');
-        if (colonPos == -1) {
-            type = "basic";
-            attr = attribute;
-        } else {
-            type = attribute.substring(0, colonPos++);
-            attr = attribute.substring(colonPos);
-        }
-        JrtFileAttributeView view = JrtFileAttributeView.get(this, type, options);
-        if (view == null)
-            throw new UnsupportedOperationException("view <" + view + "> is not supported");
-        view.setAttribute(attr, value);
-    }
-
-    void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
-        throws IOException
-    {
-        jrtfs.setTimes(getResolvedPath(), mtime, atime, ctime);
-    }
-
-    Map<String, Object> readAttributes(String attributes, LinkOption... options)
-        throws IOException
-
-    {
-        String view;
-        String attrs;
-        int colonPos = attributes.indexOf(':');
-        if (colonPos == -1) {
-            view = "basic";
-            attrs = attributes;
-        } else {
-            view = attributes.substring(0, colonPos++);
-            attrs = attributes.substring(colonPos);
-        }
-        JrtFileAttributeView jrtfv = JrtFileAttributeView.get(this, view, options);
-        if (jrtfv == null) {
-            throw new UnsupportedOperationException("view not supported");
-        }
-        return jrtfv.readAttributes(attrs);
-    }
-
-    FileStore getFileStore() throws IOException {
-        // each JrtFileSystem only has one root (as requested for now)
-        if (exists())
-            return jrtfs.getFileStore(this);
-        throw new NoSuchFileException(JrtFileSystem.getString(path));
-    }
-
-    boolean isSameFile(Path other) throws IOException {
-        if (this.equals(other))
-            return true;
-        if (other == null ||
-            this.getFileSystem() != other.getFileSystem())
-            return false;
-        this.checkAccess();
-        JrtPath path = (JrtPath)other;
-        path.checkAccess();
-        return Arrays.equals(this.getResolvedPath(), path.getResolvedPath()) ||
-            jrtfs.isSameFile(this, (JrtPath)other);
-    }
-
-    SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
-                                       FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return jrtfs.newByteChannel(getResolvedPath(), options, attrs);
-    }
-
-
-    FileChannel newFileChannel(Set<? extends OpenOption> options,
-                               FileAttribute<?>... attrs)
-        throws IOException
-    {
-        return jrtfs.newFileChannel(getResolvedPath(), options, attrs);
-    }
-
-    void checkAccess(AccessMode... modes) throws IOException {
-        boolean w = false;
-        boolean x = false;
-        for (AccessMode mode : modes) {
-            switch (mode) {
-                case READ:
-                    break;
-                case WRITE:
-                    w = true;
-                    break;
-                case EXECUTE:
-                    x = true;
-                    break;
-                default:
-                    throw new UnsupportedOperationException();
-            }
-        }
-        JrtFileAttributes attrs = jrtfs.getFileAttributes(getResolvedPath());
-        if (attrs == null && (path.length != 1 || path[0] != '/'))
-            throw new NoSuchFileException(toString());
-        if (w) {
-            if (jrtfs.isReadOnly())
-                throw new AccessDeniedException(toString());
-        }
-        if (x)
-            throw new AccessDeniedException(toString());
-    }
-
-    boolean exists() {
-        if (isAbsolute())
-            return true;
-        try {
-            return jrtfs.exists(getResolvedPath());
-        } catch (IOException x) {}
-        return false;
-    }
-
-    OutputStream newOutputStream(OpenOption... options) throws IOException
-    {
-        if (options.length == 0)
-            return jrtfs.newOutputStream(getResolvedPath(),
-                                       CREATE_NEW, WRITE);
-        return jrtfs.newOutputStream(getResolvedPath(), options);
-    }
-
-    void move(JrtPath target, CopyOption... options)
-        throws IOException
-    {
-        if (this.jrtfs == target.jrtfs)
-        {
-            jrtfs.copyFile(true,
-                         getResolvedPath(), target.getResolvedPath(),
-                         options);
-        } else {
-            copyToTarget(target, options);
-            delete();
-        }
-    }
-
-    void copy(JrtPath target, CopyOption... options)
-        throws IOException
-    {
-        if (this.jrtfs == target.jrtfs)
-            jrtfs.copyFile(false,
-                         getResolvedPath(), target.getResolvedPath(),
-                         options);
-        else
-            copyToTarget(target, options);
-    }
-
-    private void copyToTarget(JrtPath target, CopyOption... options)
-        throws IOException
-    {
-        boolean replaceExisting = false;
-        boolean copyAttrs = false;
-        for (CopyOption opt : options) {
-            if (opt == REPLACE_EXISTING)
-                replaceExisting = true;
-            else if (opt == COPY_ATTRIBUTES)
-                copyAttrs = true;
-        }
-        // attributes of source file
-        JrtFileAttributes jrtfas = getAttributes();
-        // check if target exists
-        boolean exists;
-        if (replaceExisting) {
-            try {
-                target.deleteIfExists();
-                exists = false;
-            } catch (DirectoryNotEmptyException x) {
-                exists = true;
-            }
-        } else {
-            exists = target.exists();
-        }
-        if (exists)
-            throw new FileAlreadyExistsException(target.toString());
-
-        if (jrtfas.isDirectory()) {
-            // create directory or file
-            target.createDirectory();
-        } else {
-            try (InputStream is = jrtfs.newInputStream(getResolvedPath()); OutputStream os = target.newOutputStream()) {
-                byte[] buf = new byte[8192];
-                int n;
-                while ((n = is.read(buf)) != -1) {
-                    os.write(buf, 0, n);
-                }
-            }
-        }
-        if (copyAttrs) {
-            BasicFileAttributeView view =
-                JrtFileAttributeView.get(target, BasicFileAttributeView.class);
-            try {
-                view.setTimes(jrtfas.lastModifiedTime(),
-                              jrtfas.lastAccessTime(),
-                              jrtfas.creationTime());
-            } catch (IOException x) {
-                // rollback?
-                try {
-                    target.delete();
-                } catch (IOException ignore) { }
-                throw x;
-            }
-        }
+    protected JrtPath newJrtPath(byte[] path, boolean normalized) {
+        return new JrtPath(jrtfs, path, normalized);
     }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtUtils.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtUtils.java
index 9014bf0..f1cd810 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtUtils.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtUtils.java
@@ -27,6 +27,13 @@
 
 import java.util.regex.PatternSyntaxException;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 final class JrtUtils {
     private JrtUtils() {}
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java
index c209ad2..249479e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImages.java
@@ -22,11 +22,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.internal.jrtfs;
 
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.nio.file.Files;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
@@ -35,22 +35,52 @@
 import java.security.CodeSource;
 import java.security.PrivilegedAction;
 
+/**
+ * @implNote This class needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 final class SystemImages {
     private SystemImages() {}
 
+
     static final String RUNTIME_HOME;
-    static final Path bootImagePath;
-    static final Path extImagePath;
-    static final Path appImagePath;
+    // "modules" jimage file Path
+    private static final Path moduleImageFile;
+    // "modules" jimage exists or not?
+    private static final boolean modulesImageExists;
+    // <JAVA_HOME>/modules directory Path
+    private static final Path explodedModulesDir;
 
     static {
         PrivilegedAction<String> pa = SystemImages::findHome;
         RUNTIME_HOME = AccessController.doPrivileged(pa);
 
         FileSystem fs = FileSystems.getDefault();
-        bootImagePath = fs.getPath(RUNTIME_HOME, "lib", "modules", "bootmodules.jimage");
-        extImagePath = fs.getPath(RUNTIME_HOME, "lib", "modules", "extmodules.jimage");
-        appImagePath = fs.getPath(RUNTIME_HOME, "lib", "modules", "appmodules.jimage");
+        moduleImageFile = fs.getPath(RUNTIME_HOME, "lib", "modules");
+        explodedModulesDir = fs.getPath(RUNTIME_HOME, "modules");
+
+        modulesImageExists = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                @Override
+                public Boolean run() {
+                    return Files.isRegularFile(moduleImageFile);
+                }
+            });
+    }
+
+    static boolean hasModulesImage() {
+        return modulesImageExists;
+    }
+
+    static Path moduleImageFile() {
+        return moduleImageFile;
+    }
+
+    static Path explodedModulesDir() {
+        return explodedModulesDir;
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js
index 968d1c7..c86514a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtfsviewer.js
@@ -25,6 +25,13 @@
  * questions.
  */
 
+/*
+ * @implNote This script needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
 function usage() {
     print("Usage:");
     print("jdk9+: jjs -fx jrtfsviewer.js");
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js
index e4b3c81..ed96f89 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/jrtls.js
@@ -27,6 +27,13 @@
  * Usage: jjs jrtls.js
  *
  * Recursively list the content of / directory of the jrt fs.
+ *
+ * @implNote This script needs to maintain JDK 8 source compatibility.
+ *
+ * It is used internally in the JDK to implement jimage/jrtfs access,
+ * but also compiled and delivered as part of the jrtfs.jar to support access
+ * to the jimage file provided by the shipped JDK by tools running on JDK 8.
+ */
  */
 
 // classes used
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
new file mode 100644
index 0000000..13c3eed
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Optional;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Stream;
+
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ServicesCatalog;
+
+/**
+ * Find resources and packages in modules defined to the boot class loader or
+ * resources and packages on the "boot class path" specified via -Xbootclasspath/a.
+ */
+
+public class BootLoader {
+    private BootLoader() { }
+
+    // The unnamed module for the boot loader
+    private static final Module UNNAMED_MODULE;
+    private static final String JAVA_HOME = System.getProperty("java.home");
+
+    static {
+        UNNAMED_MODULE
+            = SharedSecrets.getJavaLangReflectModuleAccess().defineUnnamedModule(null);
+        setBootLoaderUnnamedModule0(UNNAMED_MODULE);
+    }
+
+    // ServiceCatalog for the boot class loader
+    private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog();
+
+    /**
+     * Returns the unnamed module for the boot loader.
+     */
+    public static Module getUnnamedModule() {
+        return UNNAMED_MODULE;
+    }
+
+    /**
+     * Returns the ServiceCatalog for modules defined to the boot class loader.
+     */
+    public static ServicesCatalog getServicesCatalog() {
+        return SERVICES_CATALOG;
+    }
+
+    /**
+     * Register a module with this class loader so that its classes (and
+     * resources) become visible via this class loader.
+     */
+    public static void loadModule(ModuleReference mref) {
+        ClassLoaders.bootLoader().loadModule(mref);
+    }
+
+    /**
+     * Loads the Class object with the given name defined to the boot loader.
+     */
+    public static Class<?> loadClassOrNull(String name) {
+        return ClassLoaders.bootLoader().loadClassOrNull(name);
+    }
+
+    /**
+     * Returns a URL to a resource in a named 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
+     * boot loader.
+     */
+    public static InputStream findResourceAsStream(String mn, String name)
+        throws IOException
+    {
+        return ClassLoaders.bootLoader().findResourceAsStream(mn, name);
+    }
+
+    /**
+     * 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.
+     */
+    public static URL findResource(String name) {
+        return ClassLoaders.bootLoader().findResource(name);
+    }
+
+    /**
+     * 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.
+     */
+    public static Enumeration<URL> findResources(String name) throws IOException {
+        return ClassLoaders.bootLoader().findResources(name);
+    }
+
+    /**
+     * Define a package for the given class to the boot loader, if not already
+     * defined.
+     */
+    public static Package definePackage(Class<?> c) {
+        return getDefinedPackage(c.getPackageName());
+    }
+
+    /**
+     * Returns the Package of the given name defined to the boot loader or null
+     * if the package has not been defined.
+     */
+    public static Package getDefinedPackage(String pn) {
+        Package pkg = ClassLoaders.bootLoader().getDefinedPackage(pn);
+        if (pkg == null) {
+            String location = getSystemPackageLocation(pn.replace('.', '/'));
+            if (location != null) {
+                pkg = PackageHelper.definePackage(pn.intern(), location);
+            }
+        }
+        return pkg;
+    }
+
+    /**
+     * Returns a stream of the packages defined to the boot loader.
+     */
+    public static Stream<Package> packages() {
+        return Arrays.stream(getSystemPackageNames())
+                     .map(name -> getDefinedPackage(name.replace('/', '.')));
+    }
+
+    /**
+     * Helper class to define {@code Package} objects for packages in modules
+     * defined to the boot loader.
+     */
+    static class PackageHelper {
+        private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+        /**
+         * Define the {@code Package} with the given name. The specified
+         * location is a jrt URL to a named module in the run-time image, a
+         * file path to a module in an exploded run-time image, or the file
+         * path to an enty on the boot class path (java agent Boot-Class-Path
+         * or -Xbootclasspath/a.
+         *
+         * <p> If the given location is a JAR file containing a manifest,
+         * the defined Package contains the versioning information from
+         * the manifest, if present.
+         *
+         * @param name     package name
+         * @param location location where the package is (jrt URL or file path)
+         */
+        static Package definePackage(String name, String location) {
+            Module module = findModule(location);
+            if (module != null) {
+                // named module from runtime image or exploded module
+                if (name.isEmpty())
+                    throw new InternalError("empty package in " + location);
+                return JLA.definePackage(ClassLoaders.bootLoader(), name, module);
+            }
+
+            // package in unnamed module (-Xbootclasspath/a)
+            URL url = toFileURL(location);
+            Manifest man = url != null ? getManifest(location) : null;
+
+            return ClassLoaders.bootLoader().defineOrCheckPackage(name, man, url);
+        }
+
+        /**
+         * Finds the module at the given location defined to the boot loader.
+         * The module is either in runtime image or exploded image.
+         * Otherwise this method returns null.
+         */
+        private static Module findModule(String location) {
+            String mn = null;
+            if (location.startsWith("jrt:/")) {
+                // named module in runtime image ("jrt:/".length() == 5)
+                mn = location.substring(5, location.length());
+            } else {
+                // named module in exploded image
+                Path path = Paths.get(location);
+                Path modulesDir = Paths.get(JAVA_HOME, "modules");
+                if (path.startsWith(modulesDir)) {
+                    mn = path.getFileName().toString();
+                }
+            }
+
+            if (mn != null) {
+                // named module from runtime image or exploded module
+                Optional<Module> om = Layer.boot().findModule(mn);
+                if (!om.isPresent())
+                    throw new InternalError(mn + " not in boot layer");
+                return om.get();
+            }
+
+            return null;
+        }
+
+        /**
+         * Returns URL if the given location is a regular file path.
+         */
+        private static URL toFileURL(String location) {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                public URL run() {
+                    Path path = Paths.get(location);
+                    if (Files.isRegularFile(path)) {
+                        try {
+                            return path.toUri().toURL();
+                        } catch (MalformedURLException e) {}
+                    }
+                    return null;
+                }
+            });
+        }
+
+        /**
+         * Returns the Manifest if the given location is a JAR file
+         * containing a manifest.
+         */
+        private static Manifest getManifest(String location) {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                public Manifest run() {
+                    Path jar = Paths.get(location);
+                    try (InputStream in = Files.newInputStream(jar);
+                         JarInputStream jis = new JarInputStream(in, false)) {
+                        return jis.getManifest();
+                    } catch (IOException e) {
+                        return null;
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Returns an array of the binary name of the packages defined by
+     * the boot loader, in VM internal form (forward slashes instead of dot).
+     */
+    private static native String[] getSystemPackageNames();
+
+    /**
+     * Returns the location of the package of the given name, if
+     * defined by the boot loader; otherwise {@code null} is returned.
+     *
+     * The location may be a module from the runtime image or exploded image,
+     * or from the boot class append path (i.e. -Xbootclasspath/a or
+     * BOOT-CLASS-PATH attribute specified in java agent).
+     */
+    private static native String getSystemPackageLocation(String name);
+    private static native void setBootLoaderUnnamedModule0(Module module);
+}
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
new file mode 100644
index 0000000..055cba2
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
@@ -0,0 +1,766 @@
+/*
+ * 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 jdk.internal.loader;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleReader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import jdk.internal.module.ModulePatcher.PatchedModuleReader;
+import jdk.internal.misc.VM;
+import sun.misc.URLClassPath;
+import sun.misc.Resource;
+
+
+/**
+ * The platform or application class loader. Resources loaded from modules
+ * defined to the boot class loader are also loaded via an instance of this
+ * ClassLoader type.
+ *
+ * <p> This ClassLoader supports loading of classes and resources from modules.
+ * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
+ * method. Defining a module to this ClassLoader has the effect of making the
+ * types in the module visible. </p>
+ *
+ * <p> This ClassLoader also supports loading of classes and resources from a
+ * class path of URLs that are specified to the ClassLoader at construction
+ * time. The class path may expand at runtime (the Class-Path attribute in JAR
+ * files or via instrumentation agents). </p>
+ *
+ * <p> The delegation model used by this ClassLoader differs to the regular
+ * delegation model. When requested to load a class then this ClassLoader first
+ * maps the class name to its package name. If there is a module defined to a
+ * BuiltinClassLoader containing this package then the class loader delegates
+ * directly to that class loader. If there isn't a module containing the
+ * package then it delegates the search to the parent class loader and if not
+ * found in the parent then it searches the class path. The main difference
+ * between this and the usual delegation model is that it allows the platform
+ * class loader to delegate to the application class loader, important with
+ * upgraded modules defined to the platform class loader.
+ */
+
+public class BuiltinClassLoader
+    extends SecureClassLoader
+{
+    static {
+        if (!ClassLoader.registerAsParallelCapable())
+            throw new InternalError();
+    }
+
+    // parent ClassLoader
+    private final BuiltinClassLoader parent;
+
+    // the URL class path or null if there is no class path
+    private final URLClassPath ucp;
+
+
+    /**
+     * A module defined/loaded by a built-in class loader.
+     *
+     * A LoadedModule encapsulates a ModuleReference along with its CodeSource
+     * URL to avoid needing to create this URL when define classes.
+     */
+    private static class LoadedModule {
+        private final BuiltinClassLoader loader;
+        private final ModuleReference mref;
+        private final URL codeSourceURL;          // may be null
+
+        LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
+            URL url = null;
+            if (mref.location().isPresent()) {
+                try {
+                    url = mref.location().get().toURL();
+                } catch (MalformedURLException e) { }
+            }
+            this.loader = loader;
+            this.mref = mref;
+            this.codeSourceURL = url;
+        }
+
+        BuiltinClassLoader loader() { return loader; }
+        ModuleReference mref() { return mref; }
+        String name() { return mref.descriptor().name(); }
+        URL codeSourceURL() { return codeSourceURL; }
+    }
+
+
+    // maps package name to loaded module for modules in the boot layer
+    private static final Map<String, LoadedModule> packageToModule
+        = new ConcurrentHashMap<>(1024);
+
+    // maps a module name to a module reference
+    private final Map<String, ModuleReference> nameToModule;
+
+    // maps a module reference to a module reader
+    private final Map<ModuleReference, ModuleReader> moduleToReader;
+
+
+    /**
+     * Create a new instance.
+     */
+    BuiltinClassLoader(BuiltinClassLoader parent, URLClassPath ucp) {
+        // ensure getParent() returns null when the parent is the boot loader
+        super(parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
+
+        this.parent = parent;
+        this.ucp = ucp;
+
+        this.nameToModule = new ConcurrentHashMap<>();
+        this.moduleToReader = new ConcurrentHashMap<>();
+    }
+
+    /**
+     * Register a module this this class loader. This has the effect of making
+     * the types in the module visible.
+     */
+    public void loadModule(ModuleReference mref) {
+        String mn = mref.descriptor().name();
+        if (nameToModule.putIfAbsent(mn, mref) != null) {
+            throw new InternalError(mn + " already defined to this loader");
+        }
+
+        LoadedModule loadedModule = new LoadedModule(this, mref);
+        for (String pn : mref.descriptor().packages()) {
+            LoadedModule other = packageToModule.putIfAbsent(pn, loadedModule);
+            if (other != null) {
+                throw new InternalError(pn + " in modules " + mn + " and "
+                                        + other.mref().descriptor().name());
+            }
+        }
+    }
+
+    /**
+     * Returns the {@code ModuleReference} for the named module defined to
+     * this class loader; or {@code null} if not defined.
+     *
+     * @param name The name of the module to find
+     */
+    protected ModuleReference findModule(String name) {
+        return nameToModule.get(name);
+    }
+
+
+    // -- finding resources
+
+    /**
+     * Returns a URL to a resource of the given name in a module defined to
+     * this class loader.
+     */
+    @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;
+
+        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();
+        }
+
+        // check access to the URL
+        return checkURL(url);
+    }
+
+    /**
+     * Returns an input stream to a resource of the given name in a module
+     * defined to this class loader.
+     */
+    public InputStream findResourceAsStream(String mn, String name)
+        throws IOException
+    {
+        // 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) {
+
+            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);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns an enumeration of URL objects to all the resources with the
+     * given name on the class path of this class 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());
+                if (url != null) {
+                    result.add(url);
+                }
+            }
+            return Collections.enumeration(result); // checked URLs
+        } else {
+            return Collections.emptyEnumeration();
+        }
+    }
+
+
+    // -- finding/loading classes
+
+    /**
+     * Finds the class with the specified binary name.
+     */
+    @Override
+    protected Class<?> findClass(String cn) throws ClassNotFoundException {
+        // no class loading until VM is fully initialized
+        if (!VM.isModuleSystemInited())
+            throw new ClassNotFoundException(cn);
+
+        // find the candidate module for this class
+        LoadedModule loadedModule = findLoadedModule(cn);
+
+        Class<?> c = null;
+        if (loadedModule != null) {
+
+            // attempt to load class in module defined to this loader
+            if (loadedModule.loader() == this) {
+                c = findClassInModuleOrNull(loadedModule, cn);
+            }
+
+        } else {
+
+            // search class path
+            if (ucp != null) {
+                c = findClassOnClassPathOrNull(cn);
+            }
+
+        }
+
+        // not found
+        if (c == null)
+            throw new ClassNotFoundException(cn);
+
+        return c;
+    }
+
+    /**
+     * Finds the class with the specified binary name in a given module.
+     * This method returns {@code null} if the class cannot be found.
+     */
+    @Override
+    protected Class<?> findClass(String mn, String cn) {
+        ModuleReference mref = nameToModule.get(mn);
+        if (mref == null)
+            return null;   // not defined to this class loader
+
+        // 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);
+    }
+
+    /**
+     * Loads the class with the specified binary name.
+     */
+    @Override
+    protected Class<?> loadClass(String cn, boolean resolve)
+        throws ClassNotFoundException
+    {
+        Class<?> c = loadClassOrNull(cn, resolve);
+        if (c == null)
+            throw new ClassNotFoundException(cn);
+        return c;
+    }
+
+    /**
+     * A variation of {@code loadCass} to load a class with the specified
+     * binary name. This method returns {@code null} when the class is not
+     * found.
+     */
+    protected Class<?> loadClassOrNull(String cn, boolean resolve) {
+        synchronized (getClassLoadingLock(cn)) {
+            // check if already loaded
+            Class<?> c = findLoadedClass(cn);
+
+            if (c == null) {
+
+                // find the candidate module for this class
+                LoadedModule loadedModule = findLoadedModule(cn);
+                if (loadedModule != null) {
+
+                    // package is in a module
+                    BuiltinClassLoader loader = loadedModule.loader();
+                    if (loader == this) {
+                        if (VM.isModuleSystemInited()) {
+                            c = findClassInModuleOrNull(loadedModule, cn);
+                        }
+                    } else {
+                        // delegate to the other loader
+                        c = loader.loadClassOrNull(cn);
+                    }
+
+                } else {
+
+                    // check parent
+                    if (parent != null) {
+                        c = parent.loadClassOrNull(cn);
+                    }
+
+                    // check class path
+                    if (c == null && ucp != null && VM.isModuleSystemInited()) {
+                        c = findClassOnClassPathOrNull(cn);
+                    }
+                }
+
+            }
+
+            if (resolve && c != null)
+                resolveClass(c);
+
+            return c;
+        }
+    }
+
+    /**
+     * A variation of {@code loadCass} to load a class with the specified
+     * binary name. This method returns {@code null} when the class is not
+     * found.
+     */
+    protected  Class<?> loadClassOrNull(String cn) {
+        return loadClassOrNull(cn, false);
+    }
+
+    /**
+     * Find the candidate loaded module for the given class name.
+     * Returns {@code null} if none of the modules defined to this
+     * class loader contain the API package for the class.
+     */
+    private LoadedModule findLoadedModule(String cn) {
+        int pos = cn.lastIndexOf('.');
+        if (pos < 0)
+            return null; // unnamed package
+
+        String pn = cn.substring(0, pos);
+        return packageToModule.get(pn);
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * Finds the class with the specified binary name on the class path.
+     *
+     * @return the resulting Class or {@code null} if not found
+     */
+    private Class<?> findClassOnClassPathOrNull(String cn) {
+        return AccessController.doPrivileged(
+            new PrivilegedAction<Class<?>>() {
+                public Class<?> run() {
+                    String path = cn.replace('.', '/').concat(".class");
+                    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;
+                }
+            });
+    }
+
+    /**
+     * Defines the given binary class name to the VM, loading the class
+     * bytes from the given module.
+     *
+     * @return the resulting Class or {@code null} if an I/O error occurs
+     */
+    private Class<?> defineClass(String cn, LoadedModule loadedModule) {
+        ModuleReference mref = loadedModule.mref();
+        ModuleReader reader = moduleReaderFor(mref);
+
+        try {
+            ByteBuffer bb = null;
+            URL csURL = null;
+
+            // locate class file, special handling for patched modules to
+            // avoid locating the resource twice
+            String rn = cn.replace('.', '/').concat(".class");
+            if (reader instanceof PatchedModuleReader) {
+                Resource r = ((PatchedModuleReader)reader).findResource(rn);
+                if (r != null) {
+                    bb = r.getByteBuffer();
+                    csURL = r.getCodeSourceURL();
+                }
+            } else {
+                bb = reader.read(rn).orElse(null);
+                csURL = loadedModule.codeSourceURL();
+            }
+
+            if (bb == null) {
+                // class not found
+                return null;
+            }
+
+            CodeSource cs = new CodeSource(csURL, (CodeSigner[]) null);
+            try {
+                // define class to VM
+                return defineClass(cn, bb, cs);
+
+            } finally {
+                reader.release(bb);
+            }
+
+        } catch (IOException ioe) {
+            // TBD on how I/O errors should be propagated
+            return null;
+        }
+    }
+
+    /**
+     * Defines the given binary class name to the VM, loading the class
+     * bytes via the given Resource object.
+     *
+     * @return the resulting Class
+     * @throws IOException if reading the resource fails
+     * @throws SecurityException if there is a sealing violation (JAR spec)
+     */
+    private Class<?> defineClass(String cn, Resource res) throws IOException {
+        URL url = res.getCodeSourceURL();
+
+        // if class is in a named package then ensure that the package is defined
+        int pos = cn.lastIndexOf('.');
+        if (pos != -1) {
+            String pn = cn.substring(0, pos);
+            Manifest man = res.getManifest();
+            defineOrCheckPackage(pn, man, url);
+        }
+
+        // defines the class to the runtime
+        ByteBuffer bb = res.getByteBuffer();
+        if (bb != null) {
+            CodeSigner[] signers = res.getCodeSigners();
+            CodeSource cs = new CodeSource(url, signers);
+            return defineClass(cn, bb, cs);
+        } else {
+            byte[] b = res.getBytes();
+            CodeSigner[] signers = res.getCodeSigners();
+            CodeSource cs = new CodeSource(url, signers);
+            return defineClass(cn, b, 0, b.length, cs);
+        }
+    }
+
+
+    // -- packages
+
+    /**
+     * Defines a package in this ClassLoader. If the package is already defined
+     * then its sealing needs to be checked if sealed by the legacy sealing
+     * mechanism.
+     *
+     * @throws SecurityException if there is a sealing violation (JAR spec)
+     */
+    protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {
+        Package pkg = getAndVerifyPackage(pn, man, url);
+        if (pkg == null) {
+            try {
+                if (man != null) {
+                    pkg = definePackage(pn, man, url);
+                } else {
+                    pkg = definePackage(pn, null, null, null, null, null, null, null);
+                }
+            } catch (IllegalArgumentException iae) {
+                // defined by another thread so need to re-verify
+                pkg = getAndVerifyPackage(pn, man, url);
+                if (pkg == null)
+                    throw new InternalError("Cannot find package: " + pn);
+            }
+        }
+        return pkg;
+    }
+
+    /**
+     * Get the Package with the specified package name. If defined
+     * then verify that it against the manifest and code source.
+     *
+     * @throws SecurityException if there is a sealing violation (JAR spec)
+     */
+    private Package getAndVerifyPackage(String pn, Manifest man, URL url) {
+        Package pkg = getDefinedPackage(pn);
+        if (pkg != null) {
+            if (pkg.isSealed()) {
+                if (!pkg.isSealed(url)) {
+                    throw new SecurityException(
+                        "sealing violation: package " + pn + " is sealed");
+                }
+            } else {
+                // can't seal package if already defined without sealing
+                if ((man != null) && isSealed(pn, man)) {
+                    throw new SecurityException(
+                        "sealing violation: can't seal package " + pn +
+                        ": already defined");
+                }
+            }
+        }
+        return pkg;
+    }
+
+    /**
+     * Defines a new package in this ClassLoader. The attributes in the specified
+     * Manifest are use to get the package version and sealing information.
+     *
+     * @throws IllegalArgumentException if the package name duplicates an
+     * existing package either in this class loader or one of its ancestors
+     */
+    private Package definePackage(String pn, Manifest man, URL url) {
+        String specTitle = null;
+        String specVersion = null;
+        String specVendor = null;
+        String implTitle = null;
+        String implVersion = null;
+        String implVendor = null;
+        String sealed = null;
+        URL sealBase = null;
+
+        if (man != null) {
+            Attributes attr = man.getAttributes(pn.replace('.', '/').concat("/"));
+            if (attr != null) {
+                specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
+                specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
+                specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
+                implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
+                implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+                implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
+                sealed = attr.getValue(Attributes.Name.SEALED);
+            }
+
+            attr = man.getMainAttributes();
+            if (attr != null) {
+                if (specTitle == null)
+                    specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
+                if (specVersion == null)
+                    specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
+                if (specVendor == null)
+                    specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
+                if (implTitle == null)
+                    implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
+                if (implVersion == null)
+                    implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
+                if (implVendor == null)
+                    implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
+                if (sealed == null)
+                    sealed = attr.getValue(Attributes.Name.SEALED);
+            }
+
+            // package is sealed
+            if ("true".equalsIgnoreCase(sealed))
+                sealBase = url;
+        }
+        return definePackage(pn,
+                             specTitle,
+                             specVersion,
+                             specVendor,
+                             implTitle,
+                             implVersion,
+                             implVendor,
+                             sealBase);
+    }
+
+    /**
+     * Returns {@code true} if the specified package name is sealed according to
+     * the given manifest.
+     */
+    private boolean isSealed(String pn, Manifest man) {
+        String path = pn.replace('.', '/').concat("/");
+        Attributes attr = man.getAttributes(path);
+        String sealed = null;
+        if (attr != null)
+            sealed = attr.getValue(Attributes.Name.SEALED);
+        if (sealed == null && (attr = man.getMainAttributes()) != null)
+            sealed = attr.getValue(Attributes.Name.SEALED);
+        return "true".equalsIgnoreCase(sealed);
+    }
+
+    // -- permissions
+
+    /**
+     * Returns the permissions for the given CodeSource.
+     */
+    @Override
+    protected PermissionCollection getPermissions(CodeSource cs) {
+        PermissionCollection perms = super.getPermissions(cs);
+
+        // add the permission to access the resource
+        URL url = cs.getLocation();
+        if (url == null)
+            return perms;
+        Permission p = null;
+        try {
+            p = url.openConnection().getPermission();
+            if (p != null) {
+                // for directories then need recursive access
+                if (p instanceof FilePermission) {
+                    String path = p.getName();
+                    if (path.endsWith(File.separator)) {
+                        path += "-";
+                        p = new FilePermission(path, "read");
+                    }
+                }
+                perms.add(p);
+            }
+        } catch (IOException ioe) { }
+
+        return perms;
+    }
+
+
+    // -- miscellaneous supporting methods
+
+    /**
+     * Returns the ModuleReader for the given module.
+     */
+    private ModuleReader moduleReaderFor(ModuleReference mref) {
+        return moduleToReader.computeIfAbsent(mref, m -> createModuleReader(mref));
+    }
+
+    /**
+     * Creates a ModuleReader for the given module.
+     */
+    private ModuleReader createModuleReader(ModuleReference mref) {
+        try {
+            return mref.open();
+        } catch (IOException e) {
+            // Return a null module reader to avoid a future class load
+            // attempting to open the module again.
+            return new NullModuleReader();
+        }
+    }
+
+    /**
+     * A ModuleReader that doesn't read any resources.
+     */
+    private static class NullModuleReader implements ModuleReader {
+        @Override
+        public Optional<URI> find(String name) {
+            return Optional.empty();
+        }
+        @Override
+        public void close() {
+            throw new InternalError("Should not get here");
+        }
+    };
+
+    /**
+     * Checks access to the given URL. We use URLClassPath for consistent
+     * checking with java.net.URLClassLoader.
+     */
+    private static URL checkURL(URL url) {
+        return URLClassPath.checkURL(url);
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
new file mode 100644
index 0000000..f21146f
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
@@ -0,0 +1,253 @@
+/*
+ * 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 jdk.internal.loader;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Module;
+import java.net.URL;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.util.jar.Manifest;
+
+import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.VM;
+import sun.misc.URLClassPath;
+
+
+/**
+ * Creates and provides access to the built-in platform and application class
+ * loaders. It also creates the class loader that is used to locate resources
+ * in modules defined to the boot class loader.
+ */
+
+public class ClassLoaders {
+
+    private ClassLoaders() { }
+
+    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+    // the built-in class loaders
+    private static final BootClassLoader BOOT_LOADER;
+    private static final PlatformClassLoader PLATFORM_LOADER;
+    private static final AppClassLoader APP_LOADER;
+
+    /**
+     * Creates the built-in class loaders
+     */
+    static {
+
+        // -Xbootclasspth/a or -javaagent Boot-Class-Path
+        URLClassPath bcp = null;
+        String s = VM.getSavedProperty("jdk.boot.class.path.append");
+        if (s != null && s.length() > 0)
+            bcp = toURLClassPath(s);
+
+        // we have a class path if -cp is specified or -m is not specified
+        URLClassPath ucp = null;
+        String mainMid = System.getProperty("jdk.module.main");
+        String cp = System.getProperty("java.class.path");
+        if (mainMid == null && (cp == null || cp.length() == 0))
+            cp = ".";
+        if (cp != null && cp.length() > 0)
+            ucp = toURLClassPath(cp);
+
+
+        // create the class loaders
+        BOOT_LOADER = new BootClassLoader(bcp);
+        PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
+        APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);
+    }
+
+    /**
+     * Returns the class loader that is used to find resources in modules
+     * defined to the boot class loader.
+     *
+     * @apiNote This method is not public, it should instead be used via
+     * the BootLoader class that provides a restricted API to this class
+     * loader.
+     */
+    static BuiltinClassLoader bootLoader() {
+        return BOOT_LOADER;
+    }
+
+    /**
+     * Returns the platform class loader.
+     */
+    public static ClassLoader platformClassLoader() {
+        return PLATFORM_LOADER;
+    }
+
+    /**
+     * Returns the application class loader.
+     */
+    public static ClassLoader appClassLoader() {
+        return APP_LOADER;
+    }
+
+    /**
+     * The class loader that is used to find resources in modules defined to
+     * the boot class loader. It is not used for class loading.
+     */
+    private static class BootClassLoader extends BuiltinClassLoader {
+        BootClassLoader(URLClassPath bcp) {
+            super(null, bcp);
+        }
+
+        @Override
+        protected Class<?> loadClassOrNull(String cn) {
+            return JLA.findBootstrapClassOrNull(this, cn);
+        }
+    };
+
+    /**
+     * The platform class loader, a unique type to make it easier to distinguish
+     * from the application class loader.
+     */
+    private static class PlatformClassLoader extends BuiltinClassLoader {
+        static {
+            if (!ClassLoader.registerAsParallelCapable())
+                throw new InternalError();
+        }
+
+        PlatformClassLoader(BootClassLoader parent) {
+            super(parent, null);
+        }
+
+        /**
+         * Called by the VM to support define package for AppCDS.
+         *
+         * Shared classes are returned in ClassLoader::findLoadedClass
+         * that bypass the defineClass call.
+         */
+        private Package definePackage(String pn, Module module) {
+            return JLA.definePackage(this, pn, module);
+        }
+    }
+
+    /**
+     * The application class loader that is a {@code BuiltinClassLoader} with
+     * customizations to be compatible with long standing behavior.
+     */
+    private static class AppClassLoader extends BuiltinClassLoader {
+        static {
+            if (!ClassLoader.registerAsParallelCapable())
+                throw new InternalError();
+        }
+
+        final URLClassPath ucp;
+
+        AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) {
+            super(parent, ucp);
+            this.ucp = ucp;
+        }
+
+        @Override
+        protected Class<?> loadClass(String cn, boolean resolve)
+            throws ClassNotFoundException
+        {
+            // for compatibility reasons, say where restricted package list has
+            // been updated to list API packages in the unnamed module.
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                int i = cn.lastIndexOf('.');
+                if (i != -1) {
+                    sm.checkPackageAccess(cn.substring(0, i));
+                }
+            }
+
+            return super.loadClass(cn, resolve);
+        }
+
+        @Override
+        protected PermissionCollection getPermissions(CodeSource cs) {
+            PermissionCollection perms = super.getPermissions(cs);
+            perms.add(new RuntimePermission("exitVM"));
+            return perms;
+        }
+
+        /**
+         * Called by the VM to support dynamic additions to the class path
+         *
+         * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
+         */
+        void appendToClassPathForInstrumentation(String path) {
+            appendToUCP(path, ucp);
+        }
+
+        /**
+         * Called by the VM to support define package for AppCDS
+         *
+         * Shared classes are returned in ClassLoader::findLoadedClass
+         * that bypass the defineClass call.
+         */
+        private Package definePackage(String pn, Module module) {
+            return JLA.definePackage(this, pn, module);
+        }
+
+        /**
+         * Called by the VM to support define package for AppCDS
+         */
+        protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {
+            return super.defineOrCheckPackage(pn, man, url);
+        }
+    }
+
+    /**
+     * Returns a {@code URLClassPath} of file URLs to each of the elements in
+     * the given class path.
+     */
+    private static URLClassPath toURLClassPath(String cp) {
+        URLClassPath ucp = new URLClassPath(new URL[0]);
+        appendToUCP(cp, ucp);
+        return ucp;
+    }
+
+    /**
+     * Converts the elements in the given class path to file URLs and adds
+     * them to the given URLClassPath.
+     */
+    private static void appendToUCP(String cp, URLClassPath ucp) {
+        String[] elements = cp.split(File.pathSeparator);
+        if (elements.length == 0) {
+            // contains path separator(s) only, default to current directory
+            // to be compatible with long standing behavior
+            elements = new String[] { "" };
+        }
+        for (String s: elements) {
+            try {
+                URL url = Paths.get(s).toRealPath().toUri().toURL();
+                ucp.addURL(url);
+            } catch (InvalidPathException | IOException ignore) {
+                // malformed path string or class path element does not exist
+            }
+        }
+    }
+
+}
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
new file mode 100644
index 0000000..91604ec
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
@@ -0,0 +1,540 @@
+/*
+ * 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 jdk.internal.loader;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * A class loader that loads classes and resources from a collection of
+ * modules, or from a single module where the class loader is a member
+ * of a pool of class loaders.
+ *
+ * <p> The delegation model used by this ClassLoader differs to the regular
+ * delegation model. When requested to load a class then this ClassLoader first
+ * maps the class name to its package name. If there a module defined to the
+ * Loader containing the package then the class loader attempts to load from
+ * that module. If the package is instead defined to a module in a "remote"
+ * ClassLoader then this class loader delegates directly to that class loader.
+ * The map of package name to remote class loader is created based on the
+ * modules read by modules defined to this class loader. If the package is not
+ * local or remote then this class loader will delegate to the parent class
+ * loader. This allows automatic modules (for example) to link to types in the
+ * unnamed module of the parent class loader.
+ *
+ * @see Layer#createWithOneLoader
+ * @see Layer#createWithManyLoaders
+ */
+
+public final class Loader extends SecureClassLoader {
+
+    static {
+        ClassLoader.registerAsParallelCapable();
+    }
+
+    // the loader pool is in a pool, can be null
+    private final LoaderPool pool;
+
+    // parent ClassLoader, can be null
+    private final ClassLoader parent;
+
+    // maps a module name to a module reference
+    private final Map<String, ModuleReference> nameToModule;
+
+    // maps package name to a module loaded by this class loader
+    private final Map<String, LoadedModule> localPackageToModule;
+
+    // maps package name to a remote class loader, populated post initialization
+    private final Map<String, ClassLoader> remotePackageToLoader
+        = new ConcurrentHashMap<>();
+
+    // maps a module reference to a module reader, populated lazily
+    private final Map<ModuleReference, ModuleReader> moduleToReader
+        = new ConcurrentHashMap<>();
+
+    // ACC used when loading classes and resources */
+    private final AccessControlContext acc;
+
+    /**
+     * A module defined/loaded to a {@code Loader}.
+     */
+    private static class LoadedModule {
+        private final ModuleReference mref;
+        private final URL url;          // may be null
+        private final CodeSource cs;
+
+        LoadedModule(ModuleReference mref) {
+            URL url = null;
+            if (mref.location().isPresent()) {
+                try {
+                    url = mref.location().get().toURL();
+                } catch (MalformedURLException e) { }
+            }
+            this.mref = mref;
+            this.url = url;
+            this.cs = new CodeSource(url, (CodeSigner[]) null);
+        }
+
+        ModuleReference mref() { return mref; }
+        String name() { return mref.descriptor().name(); }
+        URL location() { return url; }
+        CodeSource codeSource() { return cs; }
+    }
+
+
+    /**
+     * Creates a {@code Loader} in a loader pool that loads classes/resources
+     * from one module.
+     */
+    public Loader(ResolvedModule resolvedModule,
+                  LoaderPool pool,
+                  ClassLoader parent)
+    {
+        super(parent);
+
+        this.pool = pool;
+        this.parent = parent;
+
+        ModuleReference mref = resolvedModule.reference();
+        ModuleDescriptor descriptor = mref.descriptor();
+        String mn = descriptor.name();
+        this.nameToModule = Map.of(mn, mref);
+
+        Map<String, LoadedModule> localPackageToModule = new HashMap<>();
+        LoadedModule lm = new LoadedModule(mref);
+        descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm));
+        this.localPackageToModule = localPackageToModule;
+
+        this.acc = AccessController.getContext();
+    }
+
+    /**
+     * Creates a {@code Loader} that loads classes/resources from a collection
+     * of modules.
+     *
+     * @throws IllegalArgumentException
+     *         If two or more modules have the same package
+     */
+    public Loader(Collection<ResolvedModule> modules, ClassLoader parent) {
+        super(parent);
+
+        this.pool = null;
+        this.parent = parent;
+
+        Map<String, ModuleReference> nameToModule = new HashMap<>();
+        Map<String, LoadedModule> localPackageToModule = new HashMap<>();
+        for (ResolvedModule resolvedModule : modules) {
+            ModuleReference mref = resolvedModule.reference();
+            ModuleDescriptor descriptor = mref.descriptor();
+            nameToModule.put(descriptor.name(), mref);
+            descriptor.packages().forEach(pn -> {
+                LoadedModule lm = new LoadedModule(mref);
+                if (localPackageToModule.put(pn, lm) != null)
+                    throw new IllegalArgumentException("Package "
+                        + pn + " in more than one module");
+            });
+        }
+        this.nameToModule = nameToModule;
+        this.localPackageToModule = localPackageToModule;
+
+        this.acc = AccessController.getContext();
+    }
+
+
+    /**
+     * Completes initialization of this Loader. This method populates
+     * remotePackageToLoader with the packages of the remote modules, where
+     * "remote modules" are the modules read by modules defined to this loader.
+     *
+     * @param cf the Configuration containing at least modules to be defined to
+     *           this class loader
+     *
+     * @param parentLayer the parent Layer
+     */
+    public Loader initRemotePackageMap(Configuration cf, Layer parentLayer) {
+
+        for (String name : nameToModule.keySet()) {
+
+            ResolvedModule resolvedModule = cf.findModule(name).get();
+            assert resolvedModule.configuration() == cf;
+
+            for (ResolvedModule other : resolvedModule.reads()) {
+                String mn = other.name();
+                ClassLoader loader;
+
+                if (other.configuration() == cf) {
+
+                    // The module reads another module in the newly created
+                    // layer. If all modules are defined to the same class
+                    // loader then the packages are local.
+                    if (pool == null) {
+                        assert nameToModule.containsKey(mn);
+                        continue;
+                    }
+
+                    loader = pool.loaderFor(mn);
+                    assert loader != null;
+
+                } 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 class loader for the module in the layer
+                    // For now we use the platform loader for modules defined to the
+                    // boot loader
+                    assert layer.findModule(mn).isPresent();
+                    loader = layer.findLoader(mn);
+                    if (loader == null)
+                        loader = ClassLoaders.platformClassLoader();
+                }
+
+                // find the packages that are exported to the target module
+                String target = resolvedModule.name();
+                ModuleDescriptor descriptor = other.reference().descriptor();
+                for (ModuleDescriptor.Exports e : descriptor.exports()) {
+                    boolean delegate;
+                    if (e.isQualified()) {
+                        // qualified export in same configuration
+                        delegate = (other.configuration() == cf)
+                                && e.targets().contains(target);
+                    } else {
+                        // unqualified
+                        delegate = true;
+                    }
+
+                    if (delegate) {
+                        String pn = e.source();
+                        ClassLoader l = remotePackageToLoader.putIfAbsent(pn, loader);
+                        if (l != null && l != loader) {
+                            throw new IllegalArgumentException("Package "
+                                + pn + " cannot be imported from multiple loaders");
+                        }
+
+                    }
+                }
+            }
+
+        }
+
+        return this;
+    }
+
+    /**
+     * Returns the loader pool that this loader is in or {@code null} if this
+     * loader is not in a loader pool.
+     */
+    public LoaderPool pool() {
+        return pool;
+    }
+
+
+    // -- resources --
+
+
+    /**
+     * Returns a URL to a resource of the given name in a module defined to
+     * this class loader.
+     */
+    @Override
+    protected URL findResource(String mn, String name) throws IOException {
+        ModuleReference mref = nameToModule.get(mn);
+        if (mref == null)
+            return null;   // not defined to this class loader
+
+        try {
+            return AccessController.doPrivileged(
+                new PrivilegedExceptionAction<URL>() {
+                    @Override
+                    public URL run() throws IOException {
+                        Optional<URI> ouri = moduleReaderFor(mref).find(name);
+                        if (ouri.isPresent()) {
+                            try {
+                                return ouri.get().toURL();
+                            } catch (MalformedURLException e) { }
+                        }
+                        return null;
+                    }
+                }, acc);
+        } catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getCause();
+        }
+    }
+
+
+    // -- finding/loading classes
+
+    /**
+     * Finds the class with the specified binary name.
+     */
+    @Override
+    protected Class<?> findClass(String cn) throws ClassNotFoundException {
+        Class<?> c = null;
+        LoadedModule loadedModule = findLoadedModule(cn);
+        if (loadedModule != null)
+            c = findClassInModuleOrNull(loadedModule, cn);
+        if (c == null)
+            throw new ClassNotFoundException(cn);
+        return c;
+    }
+
+    /**
+     * Finds the class with the specified binary name in a given module.
+     * This method returns {@code null} if the class cannot be found.
+     */
+    @Override
+    protected Class<?> findClass(String mn, String cn) {
+        Class<?> c = null;
+        LoadedModule loadedModule = findLoadedModule(cn);
+        if (loadedModule != null && loadedModule.name().equals(mn))
+            c = findClassInModuleOrNull(loadedModule, cn);
+        return c;
+    }
+
+    /**
+     * Loads the class with the specified binary name.
+     */
+    @Override
+    protected Class<?> loadClass(String cn, boolean resolve)
+        throws ClassNotFoundException
+    {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            String pn = packageName(cn);
+            if (!pn.isEmpty()) {
+                sm.checkPackageAccess(pn);
+            }
+        }
+
+        synchronized (getClassLoadingLock(cn)) {
+            // check if already loaded
+            Class<?> c = findLoadedClass(cn);
+
+            if (c == null) {
+
+                LoadedModule loadedModule = findLoadedModule(cn);
+
+                if (loadedModule != null) {
+
+                    // class is in module defined to this class loader
+                    c = findClassInModuleOrNull(loadedModule, cn);
+
+                } else {
+
+                    // type in another module or visible via the parent loader
+                    String pn = packageName(cn);
+                    ClassLoader loader = remotePackageToLoader.get(pn);
+                    if (loader == null) {
+                        // type not in a module read by any of the modules
+                        // defined to this loader, so delegate to parent
+                        // class loader
+                        loader = parent;
+                    }
+                    if (loader == null) {
+                        c = BootLoader.loadClassOrNull(cn);
+                    } else {
+                        c = loader.loadClass(cn);
+                    }
+
+                }
+            }
+
+            if (c == null)
+                throw new ClassNotFoundException(cn);
+
+            if (resolve)
+                resolveClass(c);
+
+            return c;
+        }
+    }
+
+
+    /**
+     * 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, acc);
+    }
+
+    /**
+     * Defines the given binary class name to the VM, loading the class
+     * bytes from the given module.
+     *
+     * @return the resulting Class or {@code null} if an I/O error occurs
+     */
+    private Class<?> defineClass(String cn, LoadedModule loadedModule) {
+        ModuleReader reader = moduleReaderFor(loadedModule.mref());
+
+        try {
+            // read class file
+            String rn = cn.replace('.', '/').concat(".class");
+            ByteBuffer bb = reader.read(rn).orElse(null);
+            if (bb == null) {
+                // class not found
+                return null;
+            }
+
+            try {
+                return defineClass(cn, bb, loadedModule.codeSource());
+            } finally {
+                reader.release(bb);
+            }
+
+        } catch (IOException ioe) {
+            // TBD on how I/O errors should be propagated
+            return null;
+        }
+    }
+
+
+    // -- permissions
+
+    /**
+     * Returns the permissions for the given CodeSource.
+     */
+    @Override
+    protected PermissionCollection getPermissions(CodeSource cs) {
+        PermissionCollection perms = super.getPermissions(cs);
+
+        URL url = cs.getLocation();
+        if (url == null)
+            return perms;
+
+        // add the permission to access the resource
+        try {
+            Permission p = url.openConnection().getPermission();
+            if (p != null) {
+                // for directories then need recursive access
+                if (p instanceof FilePermission) {
+                    String path = p.getName();
+                    if (path.endsWith(File.separator)) {
+                        path += "-";
+                        p = new FilePermission(path, "read");
+                    }
+                }
+                perms.add(p);
+            }
+        } catch (IOException ioe) { }
+
+        return perms;
+    }
+
+
+    // -- miscellaneous supporting methods
+
+    /**
+     * Find the candidate module for the given class name.
+     * Returns {@code null} if none of the modules defined to this
+     * class loader contain the API package for the class.
+     */
+    private LoadedModule findLoadedModule(String cn) {
+        String pn = packageName(cn);
+        return pn.isEmpty() ? null : localPackageToModule.get(pn);
+    }
+
+    /**
+     * Returns the package name for the given class name
+     */
+    private String packageName(String cn) {
+        int pos = cn.lastIndexOf('.');
+        return (pos < 0) ? "" : cn.substring(0, pos);
+    }
+
+
+    /**
+     * Returns the ModuleReader for the given module.
+     */
+    private ModuleReader moduleReaderFor(ModuleReference mref) {
+        return moduleToReader.computeIfAbsent(mref, m -> createModuleReader(mref));
+    }
+
+    /**
+     * Creates a ModuleReader for the given module.
+     */
+    private ModuleReader createModuleReader(ModuleReference mref) {
+        try {
+            return mref.open();
+        } catch (IOException e) {
+            // Return a null module reader to avoid a future class load
+            // attempting to open the module again.
+            return new NullModuleReader();
+        }
+    }
+
+    /**
+     * A ModuleReader that doesn't read any resources.
+     */
+    private static class NullModuleReader implements ModuleReader {
+        @Override
+        public Optional<URI> find(String name) {
+            return Optional.empty();
+        }
+        @Override
+        public void close() {
+            throw new InternalError("Should not get here");
+        }
+    }
+
+}
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
new file mode 100644
index 0000000..a9bbc26
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/LoaderPool.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.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.Map;
+import java.util.stream.Stream;
+
+/**
+ * A pool of class loaders.
+ *
+ * @see Layer#defineModulesWithManyLoaders
+ */
+
+public final class LoaderPool {
+
+    // maps module names to class loaders
+    private final Map<String, Loader> loaders;
+
+
+    /**
+     * Creates a pool of class loaders. Each module in the given configuration
+     * will be loaded its own class loader in the pool. The class loader is
+     * created with the given parent class loader as its parent.
+     */
+    public LoaderPool(Configuration cf,
+                      Layer parentLayer,
+                      ClassLoader parentLoader)
+    {
+        Map<String, Loader> loaders = new HashMap<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            Loader loader = new Loader(resolvedModule, this, parentLoader);
+            String mn = resolvedModule.name();
+            loaders.put(mn, loader);
+        }
+        this.loaders = loaders;
+
+        // complete the initialization
+        loaders.values().forEach(l -> l.initRemotePackageMap(cf, parentLayer));
+    }
+
+
+    /**
+     * Returns the class loader for the named module
+     */
+    public Loader loaderFor(String name) {
+        Loader loader = loaders.get(name);
+        assert loader != null;
+        return loader;
+    }
+
+    /**
+     * Returns a stream of the loaders in this pool.
+     */
+    public Stream<Loader> loaders() {
+        return loaders.values().stream();
+    }
+
+}
+
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 75ba73d..158d3c4 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
@@ -25,11 +25,17 @@
 
 package jdk.internal.misc;
 
+import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Executable;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.net.URL;
 import java.security.AccessControlContext;
 import java.util.Map;
+import java.util.stream.Stream;
 
+import jdk.internal.module.ServicesCatalog;
 import sun.reflect.ConstantPool;
 import sun.reflect.annotation.AnnotationType;
 import sun.nio.ch.Interruptible;
@@ -124,6 +130,43 @@
     void invokeFinalize(Object o) throws Throwable;
 
     /**
+     * Returns the boot Layer
+     */
+    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 a class loaded by the bootstrap class loader.
+     */
+    Class<?> findBootstrapClassOrNull(ClassLoader cl, String name);
+
+    /**
+     * Returns a URL to a resource with the given name in a module that is
+     * defined to the given class loader.
+     */
+    URL findResource(ClassLoader cl, String moduleName, String name) throws IOException;
+
+    /**
+     * Returns the Packages for the given class loader.
+     */
+    Stream<Package> packages(ClassLoader cl);
+
+    /**
+     * Define a Package of the given name and module by the given class loader.
+     */
+    Package definePackage(ClassLoader cl, String name, Module module);
+
+    /**
      * Invokes Long.fastUUID
      */
     String fastUUID(long lsb, long msb);
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
new file mode 100644
index 0000000..e0c7e66
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+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.lang.module.ModuleDescriptor.Version;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides access to non-public methods in java.lang.module.
+ */
+
+public interface JavaLangModuleAccess {
+
+    /**
+     * Returns {@code ModuleDescriptor.Requires} of the given modifier
+     * and module name.
+     */
+    Requires newRequires(Set<Requires.Modifier> ms, String mn);
+
+    /**
+     * Returns an unqualified {@code ModuleDescriptor.Exports}
+     * of the given package name.
+     */
+    Exports newExports(String source);
+
+    /**
+     * Returns a qualified {@code ModuleDescriptor.Exports}
+     * of the given package name and targets.
+     */
+    Exports newExports(String source, Set<String> targets);
+
+    /**
+     * Returns a {@code ModuleDescriptor.Provides}
+     * of the given service name and providers.
+     */
+    Provides newProvides(String service, Set<String> providers);
+
+    /**
+     * Returns a {@code ModuleDescriptor.Version} of the given version.
+     */
+    Version newVersion(String v);
+
+    /**
+     * Clones the given module descriptor with an augmented set of packages
+     */
+    ModuleDescriptor newModuleDescriptor(ModuleDescriptor md, Set<String> pkgs);
+
+    /**
+     * Returns a new {@code ModuleDescriptor} instance.
+     */
+    ModuleDescriptor newModuleDescriptor(String name,
+                                         boolean automatic,
+                                         boolean synthetic,
+                                         Set<Requires> requires,
+                                         Set<String> uses,
+                                         Set<Exports> exports,
+                                         Map<String, Provides> provides,
+                                         Version version,
+                                         String mainClass,
+                                         String osName,
+                                         String osArch,
+                                         String osVersion,
+                                         Set<String> conceals,
+                                         Set<String> packages);
+}
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
new file mode 100644
index 0000000..91aa495
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Module;
+import java.net.URI;
+
+/**
+ * Provides access to non-public methods in java.lang.reflect.Module
+ */
+
+public interface JavaLangReflectModuleAccess {
+
+    /**
+     * Defines the unnamed module for the given class loader.
+     */
+    Module defineUnnamedModule(ClassLoader loader);
+
+    /**
+     * Defines a new module to the Java virtual machine. The module
+     * is defined to the given class loader.
+     *
+     * The URI is for information purposes only, it can be {@code null}.
+     */
+    Module defineModule(ClassLoader loader, ModuleDescriptor descriptor, URI uri);
+
+    /**
+     * Updates the readability so that module m1 reads m2. The new read edge
+     * does not result in a strong reference to m2 (m2 can be GC'ed).
+     *
+     * This method is the same as m1.addReads(m2) but without a permission check.
+     */
+    void addReads(Module m1, Module m2);
+
+    /**
+     * Updates module m1 to export a package to module m2. The export does
+     * not result in a strong reference to m2 (m2 can be GC'ed).
+     */
+    void addExports(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 export a package to all unnamed modules.
+     */
+    void addExportsToAllUnnamed(Module m, String pkg);
+
+    /**
+     * Add a package to the given module.
+     */
+    void addPackage(Module m, String pkg);
+}
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
new file mode 100644
index 0000000..ab76a58
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilResourceBundleAccess.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * Provides access to non-public methods in java.util.ResourceBundle.
+ */
+public interface JavaUtilResourceBundleAccess {
+    /**
+     * Sets the bundle's parent to the given parent.
+     */
+    void setParent(ResourceBundle bundle, ResourceBundle parent);
+
+    /**
+     * Returns the parent of the given bundle or null if the bundle has no parent.
+     */
+    ResourceBundle getParent(ResourceBundle bundle);
+
+    /**
+     * Sets the bundle's locale to the given locale.
+     */
+    void setLocale(ResourceBundle bundle, Locale locale);
+
+    /**
+     * Sets the bundle's base name to the given name.
+     */
+    void setName(ResourceBundle bundle, String name);
+}
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 307989e..3246bde 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
@@ -25,6 +25,7 @@
 
 package jdk.internal.misc;
 
+import java.lang.module.ModuleDescriptor;
 import java.util.jar.JarFile;
 import java.io.Console;
 import java.io.FileDescriptor;
@@ -45,6 +46,8 @@
     private static final Unsafe unsafe = Unsafe.getUnsafe();
     private static JavaUtilJarAccess javaUtilJarAccess;
     private static JavaLangAccess javaLangAccess;
+    private static JavaLangModuleAccess javaLangModuleAccess;
+    private static JavaLangReflectModuleAccess javaLangReflectModuleAccess;
     private static JavaLangInvokeAccess javaLangInvokeAccess;
     private static JavaLangRefAccess javaLangRefAccess;
     private static JavaIOAccess javaIOAccess;
@@ -56,6 +59,7 @@
     private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
     private static JavaSecurityAccess javaSecurityAccess;
     private static JavaUtilZipFileAccess javaUtilZipFileAccess;
+    private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
     private static JavaAWTAccess javaAWTAccess;
     private static JavaAWTFontAccess javaAWTFontAccess;
     private static JavaBeansAccess javaBeansAccess;
@@ -95,6 +99,27 @@
         return javaLangInvokeAccess;
     }
 
+    public static void setJavaLangModuleAccess(JavaLangModuleAccess jlrma) {
+        javaLangModuleAccess = jlrma;
+    }
+
+    public static JavaLangModuleAccess getJavaLangModuleAccess() {
+        if (javaLangModuleAccess == null) {
+            unsafe.ensureClassInitialized(ModuleDescriptor.class);
+        }
+        return javaLangModuleAccess;
+    }
+
+    public static void setJavaLangReflectModuleAccess(JavaLangReflectModuleAccess jlrma) {
+        javaLangReflectModuleAccess = jlrma;
+    }
+
+    public static JavaLangReflectModuleAccess getJavaLangReflectModuleAccess() {
+        if (javaLangReflectModuleAccess == null)
+            unsafe.ensureClassInitialized(java.lang.reflect.Module.class);
+        return javaLangReflectModuleAccess;
+    }
+
     public static void setJavaLangRefAccess(JavaLangRefAccess jlra) {
         javaLangRefAccess = jlra;
     }
@@ -229,4 +254,12 @@
     public static void setJavaBeansAccess(JavaBeansAccess access) {
         javaBeansAccess = access;
     }
+
+    public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() {
+        return javaUtilResourceBundleAccess;
+    }
+
+    public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) {
+        javaUtilResourceBundleAccess = access;
+    }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
index 04af46a..e49d17b 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
@@ -144,36 +144,67 @@
     // public native static void writeJavaProfilerReport();
 
 
-    private static volatile boolean booted = false;
+    // the init level when the VM is fully initialized
+    private static final int JAVA_LANG_SYSTEM_INITED     = 1;
+    private static final int MODULE_SYSTEM_INITED        = 2;
+    private static final int SYSTEM_LOADER_INITIALIZING  = 3;
+    private static final int SYSTEM_BOOTED               = 4;
+
+    // 0, 1, 2, ...
+    private static volatile int initLevel;
     private static final Object lock = new Object();
 
-    // Invoked by System.initializeSystemClass just before returning.
-    // Subsystems that are invoked during initialization can check this
-    // property in order to avoid doing things that should wait until the
-    // application class loader has been set up.
-    //
-    public static void booted() {
+    /**
+     * Sets the init level.
+     *
+     * @see java.lang.System#initPhase1
+     * @see java.lang.System#initPhase2
+     * @see java.lang.System#initPhase3
+     */
+    public static void initLevel(int value) {
         synchronized (lock) {
-            booted = true;
+            if (value <= initLevel || value > SYSTEM_BOOTED)
+                throw new InternalError();
+            initLevel = value;
             lock.notifyAll();
         }
     }
 
-    public static boolean isBooted() {
-        return booted;
+    /**
+     * Returns the current init level.
+     */
+    public static int initLevel() {
+        return initLevel;
     }
 
-    // Waits until VM completes initialization
-    //
-    // This method is invoked by the Finalizer thread
-    public static void awaitBooted() throws InterruptedException {
+    /**
+     * Waits for the init level to get the given value.
+     *
+     * @see java.lang.ref.Finalizer
+     */
+    public static void awaitInitLevel(int value) throws InterruptedException {
         synchronized (lock) {
-            while (!booted) {
+            while (initLevel < value) {
                 lock.wait();
             }
         }
     }
 
+    /**
+     * Returns {@code true} if the module system has been initialized.
+     * @see java.lang.System#initPhase2
+     */
+    public static boolean isModuleSystemInited() {
+        return VM.initLevel() >= MODULE_SYSTEM_INITED;
+    }
+
+    /**
+     * Returns {@code true} if the VM is fully initialized.
+     */
+    public static boolean isBooted() {
+        return initLevel >= SYSTEM_BOOTED;
+    }
+
     // A user-settable upper limit on the maximum amount of allocatable direct
     // buffer memory.  This value may be changed during VM initialization if
     // "java" is launched with "-XX:MaxDirectMemorySize=<size>".
@@ -240,8 +271,8 @@
     //
     // This method can only be invoked during system initialization.
     public static void saveAndRemoveProperties(Properties props) {
-        if (booted)
-            throw new IllegalStateException("System initialization has completed");
+        if (initLevel() != 0)
+            throw new IllegalStateException("Wrong init level");
 
         savedProps.putAll(props);
 
@@ -273,13 +304,16 @@
 
         // used by sun.launcher.LauncherHelper
         props.remove("sun.java.launcher.diag");
+
+        // used by jdk.internal.loader.ClassLoaders
+        props.remove("jdk.boot.class.path.append");
     }
 
-    // Initialize any miscellenous operating system settings that need to be
+    // Initialize any miscellaneous operating system settings that need to be
     // set for the class libraries.
     //
     public static void initializeOSEnvironment() {
-        if (!booted) {
+        if (initLevel() == 0) {
             OSEnvironment.initialize();
         }
     }
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
new file mode 100644
index 0000000..8d51a5c
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.module;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Version;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+
+/**
+ * This builder is optimized for reconstituting ModuleDescriptor
+ * for installed modules.  The validation should be done at jlink time.
+ *
+ * 1. skip name validation
+ * 2. ignores dependency hashes.
+ * 3. ModuleDescriptor skips the defensive copy and directly uses the
+ *    sets/maps created in this Builder.
+ *
+ * SystemModules should contain modules for the boot layer.
+ */
+final class Builder {
+    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;
+
+    final String name;
+    final Set<Requires> requires;
+    final Set<Exports> exports;
+    final Map<String, Provides> provides;
+    final Set<String> conceals;
+    final int numPackages;
+    Set<String> uses;
+    Version version;
+    String mainClass;
+    String osName;
+    String osArch;
+    String osVersion;
+
+    Builder(String name, int reqs, int exports,
+            int provides, int conceals, int packages) {
+        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.conceals = conceals > 0 ? new HashSet<>(conceals) : Collections.emptySet();
+        this.uses = Collections.emptySet();
+        this.numPackages = packages;
+    }
+
+    /**
+     * 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));
+        return this;
+    }
+
+    /**
+     * Adds a module dependence with an empty set of modifiers.
+     */
+    public Builder requires(String mn) {
+        requires.add(jlma.newRequires(Collections.emptySet(), mn));
+        return this;
+    }
+
+    /**
+     * Adds a module dependence with the given modifier.
+     */
+    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));
+        }
+        return this;
+    }
+
+    /**
+     * Sets the set of service dependences.
+     */
+    public Builder uses(Set<String> uses) {
+        this.uses = uses;
+        return this;
+    }
+
+    /**
+     * Adds an export to a set of target modules.
+     */
+    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) concealed packages.
+     */
+    public Builder conceals(Set<String> packages) {
+        conceals.addAll(packages);
+        return this;
+    }
+
+    /**
+     * Adds a concealed package.
+     */
+    public Builder conceals(String pn) {
+        conceals.add(pn);
+        return this;
+    }
+
+    /**
+     * Sets the module version.
+     *
+     * @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 ver = cachedVersion;
+        if (ver != null && v.equals(ver.toString())) {
+            version = ver;
+        } else {
+            cachedVersion = version = Version.parse(v);
+        }
+        return this;
+    }
+
+    /**
+     * Sets the module main class.
+     *
+     * @throws IllegalStateException if already set
+     */
+    public Builder mainClass(String mc) {
+        if (mainClass != null)
+            throw new IllegalStateException("main class already set");
+        mainClass = mc;
+        return this;
+    }
+
+    /**
+     * Sets the OS name.
+     *
+     * @throws IllegalStateException if already set
+     */
+    public Builder osName(String name) {
+        if (osName != null)
+            throw new IllegalStateException("OS name already set");
+        this.osName = name;
+        return this;
+    }
+
+    /**
+     * Sets the OS arch.
+     *
+     * @throws IllegalStateException if already set
+     */
+    public Builder osArch(String arch) {
+        if (osArch != null)
+            throw new IllegalStateException("OS arch already set");
+        this.osArch = arch;
+        return this;
+    }
+
+    /**
+     * Sets the OS version.
+     *
+     * @throws IllegalStateException if already set
+     */
+    public Builder osVersion(String version) {
+        if (osVersion != null)
+            throw new IllegalStateException("OS version already set");
+        this.osVersion = version;
+        return this;
+    }
+
+    /**
+     * Returns the set of packages that is the union of the exported and
+     * concealed packages.
+     */
+    private Set<String> computePackages(Set<Exports> exports, Set<String> conceals) {
+        if (exports.isEmpty())
+            return conceals;
+
+        Set<String> pkgs = new HashSet<>(numPackages);
+        pkgs.addAll(conceals);
+        for (Exports e : exports) {
+            pkgs.add(e.source());
+        }
+        return pkgs;
+    }
+
+    /**
+     * Builds a {@code ModuleDescriptor} from the components.
+     */
+    public ModuleDescriptor build() {
+        assert name != null;
+
+        return jlma.newModuleDescriptor(name,
+                                        false,    // automatic
+                                        false,    // assume not synthetic for now
+                                        requires,
+                                        uses,
+                                        exports,
+                                        provides,
+                                        version,
+                                        mainClass,
+                                        osName,
+                                        osArch,
+                                        osVersion,
+                                        conceals,
+                                        computePackages(exports, conceals));
+    }
+}
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
new file mode 100644
index 0000000..1738bfe
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+
+public final class Checks {
+
+    private Checks() { }
+
+    private static void fail(String what, String id, int i) {
+        throw new IllegalArgumentException(id
+                                           + ": Invalid " + what + ": "
+                                           + " Illegal character"
+                                           + " at index " + i);
+    }
+
+    /**
+     * Returns {@code true} if the given identifier is a legal Java identifier.
+     */
+    public static boolean isJavaIdentifier(String id) {
+        int n = id.length();
+        if (n == 0)
+            return false;
+        if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
+            return false;
+        int cp = id.codePointAt(0);
+        int i = Character.charCount(cp);
+        for (; i < n; i += Character.charCount(cp)) {
+            cp = id.codePointAt(i);
+            if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
+                return false;
+        }
+        if (cp == '.')
+            return false;
+
+        return true;
+    }
+
+    /**
+     * Checks if a given identifier is a legal Java identifier.
+     */
+    public static String requireJavaIdentifier(String what, String id) {
+        if (id == null)
+            throw new IllegalArgumentException("Null " + what);
+        int n = id.length();
+        if (n == 0)
+            throw new IllegalArgumentException("Empty " + what);
+        if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
+            fail(what, id, 0);
+        int cp = id.codePointAt(0);
+        int i = Character.charCount(cp);
+        int last = 0;
+        for (; i < n; i += Character.charCount(cp)) {
+            cp = id.codePointAt(i);
+            if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
+                fail(what, id, i);
+            last = i;
+        }
+        if (cp == '.')
+            fail(what, id, last);
+
+        return id;
+    }
+
+    public static String requireModuleName(String id) {
+        return requireJavaIdentifier("module name", id);
+    }
+
+    public static String requirePackageName(String id) {
+        return requireJavaIdentifier("package name", id);
+    }
+
+    public static String requireServiceTypeName(String id) {
+        return requireJavaIdentifier("service type name", id);
+    }
+
+    public static String requireServiceProviderName(String id) {
+        return requireJavaIdentifier("service provider name", id);
+    }
+
+}
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
new file mode 100644
index 0000000..66b4891
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+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.Provides;
+import java.lang.module.ModuleDescriptor.Version;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ByteVector;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.module.Hasher.DependencyHashes;
+import static jdk.internal.module.ClassFileConstants.*;
+
+
+/**
+ * Provides ASM implementations of {@code Attribute} to read and write the
+ * class file attributes in a module-info class file.
+ */
+
+class ClassFileAttributes {
+
+    private ClassFileAttributes() { }
+
+    /**
+     * Module_attribute {
+     *   // See lang-vm.html for details.
+     * }
+     */
+    static class ModuleAttribute extends Attribute {
+
+        private ModuleDescriptor descriptor;
+
+        ModuleAttribute(ModuleDescriptor descriptor) {
+            super(MODULE);
+            this.descriptor = descriptor;
+        }
+
+        ModuleAttribute() {
+            super(MODULE);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            ModuleDescriptor.Builder builder
+                = new ModuleDescriptor.Builder("xyzzy"); // Name never used
+            ModuleAttribute attr = new ModuleAttribute();
+
+            // 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);
+                int flags = cr.readUnsignedShort(off + 2);
+                Set<Modifier> mods;
+                if (flags == 0) {
+                    mods = Collections.emptySet();
+                } else {
+                    mods = new HashSet<>();
+                    if ((flags & ACC_PUBLIC) != 0)
+                        mods.add(Modifier.PUBLIC);
+                    if ((flags & ACC_SYNTHETIC) != 0)
+                        mods.add(Modifier.SYNTHETIC);
+                    if ((flags & ACC_MANDATED) != 0)
+                        mods.add(Modifier.MANDATED);
+                }
+                builder.requires(mods, dn);
+                off += 4;
+            }
+
+            // exports_count and exports[exports_count]
+            int exports_count = cr.readUnsignedShort(off);
+            off += 2;
+            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;
+                    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);
+                            off += 2;
+                            targets.add(t);
+                        }
+                        builder.exports(pkg, targets);
+                    } else {
+                        builder.exports(pkg);
+                    }
+                }
+            }
+
+            // uses_count and uses_index[uses_count]
+            int uses_count = cr.readUnsignedShort(off);
+            off += 2;
+            if (uses_count > 0) {
+                for (int i=0; i<uses_count; i++) {
+                    String sn = cr.readClass(off, buf).replace('/', '.');
+                    builder.uses(sn);
+                    off += 2;
+                }
+            }
+
+            // provides_count and provides[provides_count]
+            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 HashSet<>()).add(cn);
+                    off += 4;
+                }
+                provides.entrySet().forEach(e -> builder.provides(e.getKey(),
+                                                                  e.getValue()));
+            }
+
+            attr.descriptor = builder.build();
+            return attr;
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            assert descriptor != null;
+            ByteVector attr = new ByteVector();
+
+            // requires_count
+            attr.putShort(descriptor.requires().size());
+
+            // requires[requires_count]
+            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))
+                    flags |= ACC_SYNTHETIC;
+                if (md.modifiers().contains(Modifier.MANDATED))
+                    flags |= ACC_MANDATED;
+                int index = cw.newUTF8(dn);
+                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);
+                    }
+                }
+            }
+
+            // uses_count and uses_index[uses_count]
+            if (descriptor.uses().isEmpty()) {
+                attr.putShort(0);
+            } else {
+                attr.putShort(descriptor.uses().size());
+                for (String s : descriptor.uses()) {
+                    String service = s.replace('.', '/');
+                    int index = cw.newClass(service);
+                    attr.putShort(index);
+                }
+            }
+
+            // provides_count and provides[provides_count]
+            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()) {
+                    String service = p.service().replace('.', '/');
+                    int index = cw.newClass(service);
+                    for (String provider : p.providers()) {
+                        attr.putShort(index);
+                        attr.putShort(cw.newClass(provider.replace('.', '/')));
+                    }
+                }
+            }
+
+            return attr;
+        }
+    }
+
+    /**
+     * 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.
+     *
+     * <pre> {@code
+     *
+     * ConcealedPackages_attribute {
+     *   // index to CONSTANT_utf8_info structure in constant pool representing
+     *   // the string "ConcealedPackages"
+     *   u2 attribute_name_index;
+     *   u4 attribute_length;
+     *
+     *   // the number of entries in the packages table
+     *   u2 package_count;
+     *   { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
+     *     u2 package_index
+     *   } package[package_count];
+     *
+     * }</pre>
+     */
+    static class ConcealedPackagesAttribute extends Attribute {
+        private final Set<String> packages;
+
+        ConcealedPackagesAttribute(Set<String> packages) {
+            super(CONCEALED_PACKAGES);
+            this.packages = packages;
+        }
+
+        ConcealedPackagesAttribute() {
+            this(null);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            // package count
+            int package_count = cr.readUnsignedShort(off);
+            off += 2;
+
+            // packages
+            Set<String> packages = new HashSet<>();
+            for (int i=0; i<package_count; i++) {
+                String pkg = cr.readUTF8(off, buf).replace('/', '.');
+                packages.add(pkg);
+                off += 2;
+            }
+
+            return new ConcealedPackagesAttribute(packages);
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            assert packages != null;
+
+            ByteVector attr = new ByteVector();
+
+            // package_count
+            attr.putShort(packages.size());
+
+            // packages
+            packages.stream()
+                .map(p -> p.replace('.', '/'))
+                .forEach(p -> attr.putShort(cw.newUTF8(p)));
+
+            return attr;
+        }
+
+    }
+
+    /**
+     * Version attribute.
+     *
+     * <pre> {@code
+     *
+     * Version_attribute {
+     *   // index to CONSTANT_utf8_info structure in constant pool representing
+     *   // the string "Version"
+     *   u2 attribute_name_index;
+     *   u4 attribute_length;
+     *
+     *   // index to CONSTANT_CONSTANT_utf8_info structure with the version
+     *   u2 version_index;
+     * }
+     *
+     * } </pre>
+     */
+    static class VersionAttribute extends Attribute {
+        private final Version version;
+
+        VersionAttribute(Version version) {
+            super(VERSION);
+            this.version = version;
+        }
+
+        VersionAttribute() {
+            this(null);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            String value = cr.readUTF8(off, buf);
+            return new VersionAttribute(Version.parse(value));
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            ByteVector attr = new ByteVector();
+            int index = cw.newUTF8(version.toString());
+            attr.putShort(index);
+            return attr;
+        }
+    }
+
+    /**
+     * MainClass attribute.
+     *
+     * <pre> {@code
+     *
+     * MainClass_attribute {
+     *   // index to CONSTANT_utf8_info structure in constant pool representing
+     *   // the string "MainClass"
+     *   u2 attribute_name_index;
+     *   u4 attribute_length;
+     *
+     *   // index to CONSTANT_Class_info structure with the main class name
+     *   u2 main_class_index;
+     * }
+     *
+     * } </pre>
+     */
+    static class MainClassAttribute extends Attribute {
+        private final String mainClass;
+
+        MainClassAttribute(String mainClass) {
+            super(MAIN_CLASS);
+            this.mainClass = mainClass;
+        }
+
+        MainClassAttribute() {
+            this(null);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            String value = cr.readClass(off, buf);
+            return new MainClassAttribute(value);
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            ByteVector attr = new ByteVector();
+            int index = cw.newClass(mainClass);
+            attr.putShort(index);
+            return attr;
+        }
+    }
+
+    /**
+     * TargetPlatform attribute.
+     *
+     * <pre> {@code
+     *
+     * TargetPlatform_attribute {
+     *   // index to CONSTANT_utf8_info structure in constant pool representing
+     *   // the string "TargetPlatform"
+     *   u2 attribute_name_index;
+     *   u4 attribute_length;
+     *
+     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS name
+     *   u2 os_name_index;
+     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS arch
+     *   u2 os_arch_index
+     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS version
+     *   u2 os_version_index;
+     * }
+     *
+     * } </pre>
+     */
+    static class TargetPlatformAttribute extends Attribute {
+        private final String osName;
+        private final String osArch;
+        private final String osVersion;
+
+        TargetPlatformAttribute(String osName, String osArch, String osVersion) {
+            super(TARGET_PLATFORM);
+            this.osName = osName;
+            this.osArch = osArch;
+            this.osVersion = osVersion;
+        }
+
+        TargetPlatformAttribute() {
+            this(null, null, null);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+
+            String osName = null;
+            String osArch = null;
+            String osVersion = null;
+
+            int name_index = cr.readUnsignedShort(off);
+            if (name_index != 0)
+                osName = cr.readUTF8(off, buf);
+            off += 2;
+
+            int arch_index = cr.readUnsignedShort(off);
+            if (arch_index != 0)
+                osArch = cr.readUTF8(off, buf);
+            off += 2;
+
+            int version_index = cr.readUnsignedShort(off);
+            if (version_index != 0)
+                osVersion = cr.readUTF8(off, buf);
+            off += 2;
+
+            return new TargetPlatformAttribute(osName, osArch, osVersion);
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            ByteVector attr = new ByteVector();
+
+            int name_index = 0;
+            if (osName != null && osName.length() > 0)
+                name_index = cw.newUTF8(osName);
+            attr.putShort(name_index);
+
+            int arch_index = 0;
+            if (osArch != null && osArch.length() > 0)
+                arch_index = cw.newUTF8(osArch);
+            attr.putShort(arch_index);
+
+            int version_index = 0;
+            if (osVersion != null && osVersion.length() > 0)
+                version_index = cw.newUTF8(osVersion);
+            attr.putShort(version_index);
+
+            return attr;
+        }
+    }
+
+    /**
+     * Hashes attribute.
+     *
+     * <pre> {@code
+     *
+     * Hashes_attribute {
+     *   // index to CONSTANT_utf8_info structure in constant pool representing
+     *   // the string "Hashes"
+     *   u2 attribute_name_index;
+     *   u4 attribute_length;
+     *
+     *   // index to CONSTANT_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];
+     *
+     * } </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 {
+        private final DependencyHashes hashes;
+
+        HashesAttribute(DependencyHashes hashes) {
+            super(HASHES);
+            this.hashes = hashes;
+        }
+
+        HashesAttribute() {
+            this(null);
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            String algorithm = cr.readUTF8(off, buf);
+            off += 2;
+
+            int hash_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);
+                off += 2;
+                String hash = cr.readUTF8(off, buf);
+                off += 2;
+                map.put(dn, hash);
+            }
+
+            DependencyHashes hashes = new DependencyHashes(algorithm, map);
+
+            return new HashesAttribute(hashes);
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            ByteVector attr = new ByteVector();
+
+            int index = cw.newUTF8(hashes.algorithm());
+            attr.putShort(index);
+
+            Set<String> names = hashes.names();
+            attr.putShort(names.size());
+
+            for (String dn : names) {
+                String hash = hashes.hashFor(dn);
+                assert hash != null;
+                attr.putShort(cw.newUTF8(dn));
+                attr.putShort(cw.newUTF8(hash));
+            }
+
+            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
new file mode 100644
index 0000000..6a61f09
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileConstants.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+
+// Constants in module-info.class files
+
+public class ClassFileConstants {
+
+    private ClassFileConstants() { }
+
+    // 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";
+
+    // 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;
+
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ConfigurableModuleFinder.java b/jdk/src/java.base/share/classes/jdk/internal/module/ConfigurableModuleFinder.java
new file mode 100644
index 0000000..914f870
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ConfigurableModuleFinder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.module;
+
+import java.lang.module.ModuleFinder;
+
+/**
+ * A ModuleFinder that may be configured to work at either run-time
+ * or link-time.
+ */
+
+public interface ConfigurableModuleFinder extends ModuleFinder {
+
+    public static enum Phase {
+        RUN_TIME,
+        LINK_TIME
+    }
+
+    /**
+     * Configures this finder to work in the given phase.
+     */
+    void configurePhase(Phase phase);
+
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java b/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java
new file mode 100644
index 0000000..947900f
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.module;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Supporting class for computing, encoding and decoding hashes (message
+ * digests).
+ */
+
+public class Hasher {
+    private Hasher() { }
+
+    /**
+     * A supplier of an encoded message digest.
+     */
+    public static interface HashSupplier {
+        String generate(String algorithm);
+    }
+
+    /**
+     * Encapsulates the result of hashing the contents of a number of module
+     * artifacts.
+     */
+    public static class DependencyHashes {
+        private final String algorithm;
+        private final Map<String, String> nameToHash;
+
+        public DependencyHashes(String algorithm, Map<String, String> nameToHash) {
+            this.algorithm = algorithm;
+            this.nameToHash = nameToHash;
+        }
+
+        /**
+         * Returns the algorithm used to hash the dependences ("SHA-256" or
+         * "MD5" for example).
+         */
+        public String algorithm() {
+            return algorithm;
+        }
+
+        /**
+         * Returns the set of module names for which hashes are recorded.
+         */
+        public Set<String> names() {
+            return nameToHash.keySet();
+        }
+
+        /**
+         * Retruns the hash string for the given module name, {@code null}
+         * if there is no hash recorded for the module.
+         */
+        public String hashFor(String dn) {
+            return nameToHash.get(dn);
+        }
+    }
+
+
+    /**
+     * Computes the hash for the given file with the given message digest
+     * algorithm. Returns the results a base64-encoded String.
+     *
+     * @throws UncheckedIOException if an I/O error occurs
+     * @throws RuntimeException if the algorithm is not available
+     */
+    public static String generate(Path file, String algorithm) {
+        try {
+            MessageDigest md = MessageDigest.getInstance(algorithm);
+
+            // Ideally we would just mmap the file but this consumes too much
+            // memory when jlink is running concurrently on very large jmods
+            try (FileChannel fc = FileChannel.open(file)) {
+                ByteBuffer bb = ByteBuffer.allocate(32*1024);
+                int nread;
+                while ((nread = fc.read(bb)) > 0) {
+                    bb.flip();
+                    md.update(bb);
+                    assert bb.remaining() == 0;
+                    bb.clear();
+                }
+            }
+
+            byte[] bytes = md.digest();
+            return Base64.getEncoder().encodeToString(bytes);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    /**
+     * Computes the hash for every entry in the given map, returning a
+     * {@code DependencyHashes} to encapsulate the result. The map key is
+     * the entry name, typically the module name. The map value is the file
+     * path to the entry (module artifact).
+     *
+     * @return DependencyHashes encapsulate the hashes
+     */
+    public static DependencyHashes generate(Map<String, Path> map, String algorithm) {
+        Map<String, String> nameToHash = new HashMap<>();
+        for (Map.Entry<String, Path> entry: map.entrySet()) {
+            String name = entry.getKey();
+            Path path = entry.getValue();
+            nameToHash.put(name, generate(path, algorithm));
+        }
+        return new DependencyHashes(algorithm, nameToHash);
+    }
+}
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
new file mode 100644
index 0000000..5b6c3c4
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
@@ -0,0 +1,533 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.io.File;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.perf.PerfCounter;
+
+/**
+ * Initializes/boots the module system.
+ *
+ * The {@link #boot() boot} method is called early in the startup to initialize
+ * the module system. In summary, the boot method creates a Configuration by
+ * resolving a set of module names specified via the launcher (or equivalent)
+ * -m and -addmods options. The modules are located on a module path that is
+ * constructed from the upgrade, system and application module paths. The
+ * Configuration is reified by creating the boot Layer with each module in the
+ * the configuration defined to one of the built-in class loaders. The mapping
+ * of modules to class loaders is statically mapped in a helper class.
+ */
+
+public final class ModuleBootstrap {
+    private ModuleBootstrap() { }
+
+    private static final String JAVA_BASE = "java.base";
+
+    // the token for "all unnamed modules"
+    private static final String ALL_UNNAMED = "ALL-UNNAMED";
+
+    // the token for "all system modules"
+    private static final String ALL_SYSTEM = "ALL-SYSTEM";
+
+    // the token for "all modules on the module path"
+    private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
+
+    // ModuleFinder for the initial configuration
+    private static ModuleFinder initialFinder;
+
+    /**
+     * Returns the ModuleFinder for the initial configuration
+     */
+    public static ModuleFinder finder() {
+        assert initialFinder != null;
+        return initialFinder;
+    }
+
+    /**
+     * Initialize the module system, returning the boot Layer.
+     *
+     * @see java.lang.System#initPhase2()
+     */
+    public static Layer boot() {
+
+        long t0 = System.nanoTime();
+
+        // system module path
+        ModuleFinder systemModulePath = ModuleFinder.ofSystem();
+
+        // Once we have the system module path then we define the base module.
+        // We do this here so that java.base is defined to the VM as early as
+        // possible and also that resources in the base module can be located
+        // for error messages that may happen from here on.
+        Optional<ModuleReference> obase = systemModulePath.find(JAVA_BASE);
+        if (!obase.isPresent())
+            throw new InternalError(JAVA_BASE + " not found");
+        ModuleReference base = obase.get();
+        BootLoader.loadModule(base);
+        Modules.defineModule(null, base.descriptor(), base.location().orElse(null));
+
+
+        // -upgrademodulepath option specified to launcher
+        ModuleFinder upgradeModulePath
+            = createModulePathFinder("jdk.upgrade.module.path");
+
+        // -modulepath option specified to the launcher
+        ModuleFinder appModulePath = createModulePathFinder("jdk.module.path");
+
+        // The module finder: [-upgrademodulepath] system-module-path [-modulepath]
+        ModuleFinder finder = systemModulePath;
+        if (upgradeModulePath != null)
+            finder = ModuleFinder.compose(upgradeModulePath, finder);
+        if (appModulePath != null)
+            finder = ModuleFinder.compose(finder, appModulePath);
+
+        // launcher -m option to specify the initial module
+        String mainModule = System.getProperty("jdk.module.main");
+
+        // additional module(s) specified by -addmods
+        boolean addAllSystemModules = false;
+        boolean addAllApplicationModules = false;
+        Set<String> addModules = null;
+        String propValue = System.getProperty("jdk.launcher.addmods");
+        if (propValue != null) {
+            addModules = new HashSet<>();
+            for (String mod: propValue.split(",")) {
+                switch (mod) {
+                    case ALL_SYSTEM:
+                        addAllSystemModules = true;
+                        break;
+                    case ALL_MODULE_PATH:
+                        addAllApplicationModules = true;
+                        break;
+                    default :
+                        addModules.add(mod);
+                }
+            }
+        }
+
+        // The root modules to resolve
+        Set<String> roots = new HashSet<>();
+
+        // main/initial module
+        if (mainModule != null) {
+            roots.add(mainModule);
+            if (addAllApplicationModules)
+                fail(ALL_MODULE_PATH + " not allowed with initial module");
+        }
+
+        // If -addmods is specified then those modules need to be resolved
+        if (addModules != null)
+            roots.addAll(addModules);
+
+
+        // -limitmods
+        boolean limitmods = false;
+        propValue = System.getProperty("jdk.launcher.limitmods");
+        if (propValue != null) {
+            Set<String> mods = new HashSet<>();
+            for (String mod: propValue.split(",")) {
+                mods.add(mod);
+            }
+            finder = limitFinder(finder, mods, roots);
+            limitmods = true;
+        }
+
+
+        // If there is no initial module specified then assume that the
+        // initial module is the unnamed module of the application class
+        // loader. By convention, and for compatibility, this is
+        // implemented by putting the names of all modules on the system
+        // module path into the set of modules to resolve.
+        //
+        // If `-addmods ALL-SYSTEM` is used then all modules on the system
+        // module path will be resolved, irrespective of whether an initial
+        // module is specified.
+        //
+        // If `-addmods ALL-MODULE-PATH` is used, and no initial module is
+        // specified, then all modules on the application module path will
+        // be resolved.
+        //
+        if (mainModule == null || addAllSystemModules) {
+            Set<ModuleReference> mrefs;
+            if (addAllApplicationModules) {
+                assert mainModule == null;
+                mrefs = finder.findAll();
+            } else {
+                mrefs = systemModulePath.findAll();
+                if (limitmods) {
+                    ModuleFinder f = finder;
+                    mrefs = mrefs.stream()
+                        .filter(m -> f.find(m.descriptor().name()).isPresent())
+                        .collect(Collectors.toSet());
+                }
+            }
+            // map to module names
+            for (ModuleReference mref : mrefs) {
+                roots.add(mref.descriptor().name());
+            }
+        }
+
+        long t1 = System.nanoTime();
+
+        // run the resolver to create the configuration
+
+        Configuration cf = Configuration.empty()
+                .resolveRequiresAndUses(finder,
+                                        ModuleFinder.empty(),
+                                        roots);
+
+        // time to create configuration
+        PerfCounters.resolveTime.addElapsedTimeFrom(t1);
+
+        // mapping of modules to class loaders
+        Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
+
+        // check that all modules to be mapped to the boot loader will be
+        // loaded from the system module path
+        if (finder != systemModulePath) {
+            for (ResolvedModule resolvedModule : cf.modules()) {
+                ModuleReference mref = resolvedModule.reference();
+                String name = mref.descriptor().name();
+                ClassLoader cl = clf.apply(name);
+                if (cl == null) {
+
+                    if (upgradeModulePath != null
+                            && upgradeModulePath.find(name).isPresent())
+                        fail(name + ": cannot be loaded from upgrade module path");
+
+                    if (!systemModulePath.find(name).isPresent())
+                        fail(name + ": cannot be loaded from application module path");
+                }
+            }
+        }
+
+        long t2 = System.nanoTime();
+
+        // define modules to VM/runtime
+        Layer bootLayer = Layer.empty().defineModules(cf, clf);
+
+        PerfCounters.layerCreateTime.addElapsedTimeFrom(t2);
+
+        long t3 = System.nanoTime();
+
+        // define the module to its class loader, except java.base
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleReference mref = resolvedModule.reference();
+            String name = mref.descriptor().name();
+            ClassLoader cl = clf.apply(name);
+            if (cl == null) {
+                if (!name.equals(JAVA_BASE)) BootLoader.loadModule(mref);
+            } else {
+                ((BuiltinClassLoader)cl).loadModule(mref);
+            }
+        }
+
+        PerfCounters.loadModulesTime.addElapsedTimeFrom(t3);
+
+        // -XaddReads and -XaddExports
+        addExtraReads(bootLayer);
+        addExtraExports(bootLayer);
+
+        // total time to initialize
+        PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
+
+        // remember the ModuleFinder
+        initialFinder = finder;
+
+        return bootLayer;
+    }
+
+    /**
+     * Returns a ModuleFinder that limits observability to the given root
+     * modules, their transitive dependences, plus a set of other modules.
+     */
+    private static ModuleFinder limitFinder(ModuleFinder finder,
+                                            Set<String> roots,
+                                            Set<String> otherMods)
+    {
+        // resolve all root modules
+        Configuration cf = Configuration.empty()
+                .resolveRequires(finder,
+                                 ModuleFinder.empty(),
+                                 roots);
+
+        // module name -> reference
+        Map<String, ModuleReference> map = new HashMap<>();
+        cf.modules().stream()
+            .map(ResolvedModule::reference)
+            .forEach(mref -> map.put(mref.descriptor().name(), mref));
+
+        // set of modules that are observable
+        Set<ModuleReference> mrefs = new HashSet<>(map.values());
+
+        // add the other modules
+        for (String mod : otherMods) {
+            Optional<ModuleReference> omref = finder.find(mod);
+            if (omref.isPresent()) {
+                ModuleReference mref = omref.get();
+                map.putIfAbsent(mod, mref);
+                mrefs.add(mref);
+            } else {
+                // no need to fail
+            }
+        }
+
+        return new ModuleFinder() {
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                return Optional.ofNullable(map.get(name));
+            }
+            @Override
+            public Set<ModuleReference> findAll() {
+                return mrefs;
+            }
+        };
+    }
+
+    /**
+     * Creates a finder from the module path that is the value of the given
+     * system property.
+     */
+    private static ModuleFinder createModulePathFinder(String prop) {
+        String s = System.getProperty(prop);
+        if (s == null) {
+            return null;
+        } else {
+            String[] dirs = s.split(File.pathSeparator);
+            Path[] paths = new Path[dirs.length];
+            int i = 0;
+            for (String dir: dirs) {
+                paths[i++] = Paths.get(dir);
+            }
+            return ModuleFinder.of(paths);
+        }
+    }
+
+
+    /**
+     * Process the -XaddReads options to add any additional read edges that
+     * are specified on the command-line.
+     */
+    private static void addExtraReads(Layer bootLayer) {
+
+        // decode the command line options
+        Map<String, Set<String>> map = decode("jdk.launcher.addreads.");
+
+        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+
+            // the key is $MODULE
+            String mn = e.getKey();
+            Optional<Module> om = bootLayer.findModule(mn);
+            if (!om.isPresent())
+                fail("Unknown module: " + mn);
+            Module m = om.get();
+
+            // the value is the set of other modules (by name)
+            for (String name : e.getValue()) {
+
+                Module other;
+                if (ALL_UNNAMED.equals(name)) {
+                    other = null;  // loose
+                } else {
+                    om = bootLayer.findModule(name);
+                    if (!om.isPresent())
+                        fail("Unknown module: " + name);
+                    other = om.get();
+                }
+
+                Modules.addReads(m, other);
+            }
+        }
+    }
+
+
+    /**
+     * Process the -XaddExports options to add any additional read edges that
+     * are specified on the command-line.
+     */
+    private static void addExtraExports(Layer bootLayer) {
+
+        // decode the command line options
+        Map<String, Set<String>> map = decode("jdk.launcher.addexports.");
+
+        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+
+            // the key is $MODULE/$PACKAGE
+            String key = e.getKey();
+            String[] s = key.split("/");
+            if (s.length != 2)
+                fail("Unable to parse: " + key);
+
+            String mn = s[0];
+            String pn = s[1];
+
+            // The exporting module is in the boot layer
+            Module m;
+            Optional<Module> om = bootLayer.findModule(mn);
+            if (!om.isPresent())
+                fail("Unknown module: " + mn);
+            m = om.get();
+
+            // the value is the set of modules to export to (by name)
+            for (String name : e.getValue()) {
+                boolean allUnnamed = false;
+                Module other = null;
+                if (ALL_UNNAMED.equals(name)) {
+                    allUnnamed = true;
+                } else {
+                    om = bootLayer.findModule(name);
+                    if (om.isPresent()) {
+                        other = om.get();
+                    } else {
+                        fail("Unknown module: " + name);
+                    }
+                }
+
+                if (allUnnamed) {
+                    Modules.addExportsToAllUnnamed(m, pn);
+                } else {
+                    Modules.addExports(m, pn, other);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Decodes the values of -XaddReads or -XaddExports options
+     *
+     * The format of the options is: $KEY=$MODULE(,$MODULE)*
+     *
+     * For transition purposes, this method allows the first usage to be
+     *     $KEY=$MODULE(,$KEY=$MODULE)
+     * This format will eventually be removed.
+     */
+    private static Map<String, Set<String>> decode(String prefix) {
+        int index = 0;
+        String value = System.getProperty(prefix + index);
+        if (value == null)
+            return Collections.emptyMap();
+
+        Map<String, Set<String>> map = new HashMap<>();
+
+        while (value != null) {
+
+            int pos = value.indexOf('=');
+            if (pos == -1)
+                fail("Unable to parse: " + value);
+            if (pos == 0)
+                fail("Missing module name in: " + value);
+
+            // key is <module> or <module>/<package>
+            String key = value.substring(0, pos);
+
+            String rhs = value.substring(pos+1);
+            if (rhs.isEmpty())
+                fail("Unable to parse: " + value);
+
+            // new format $MODULE(,$MODULE)* or old format $(MODULE)=...
+            pos = rhs.indexOf('=');
+
+            // old format only allowed in first -X option
+            if (pos >= 0 && index > 0)
+                fail("Unable to parse: " + value);
+
+            if (pos == -1) {
+
+                // new format: $KEY=$MODULE(,$MODULE)*
+
+                Set<String> values = map.get(key);
+                if (values != null)
+                    fail(key + " specified more than once");
+
+                values = new HashSet<>();
+                map.put(key, values);
+                for (String s : rhs.split(",")) {
+                    if (s.length() > 0) values.add(s);
+                }
+
+            } else {
+
+                // old format: $KEY=$MODULE(,$KEY=$MODULE)*
+
+                assert index == 0;  // old format only allowed in first usage
+
+                for (String expr : value.split(",")) {
+                    if (expr.length() > 0) {
+                        String[] s = expr.split("=");
+                        if (s.length != 2)
+                            fail("Unable to parse: " + expr);
+
+                        map.computeIfAbsent(s[0], k -> new HashSet<>()).add(s[1]);
+                    }
+                }
+            }
+
+            index++;
+            value = System.getProperty(prefix + index);
+        }
+
+        return map;
+    }
+
+
+    /**
+     * Throws a RuntimeException with the given message
+     */
+    static void fail(String m) {
+        throw new RuntimeException(m);
+    }
+
+    static class PerfCounters {
+        static PerfCounter resolveTime
+            = PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime");
+        static PerfCounter layerCreateTime
+            = PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime");
+        static PerfCounter loadModulesTime
+            = PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime");
+        static PerfCounter bootstrapTime
+            = PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime");
+    }
+}
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
new file mode 100644
index 0000000..91d1f8e
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.module.ModuleDescriptor.Version;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.module.Hasher.DependencyHashes;
+
+import static jdk.internal.module.ClassFileAttributes.*;
+
+/**
+ * Utility class to extend a module-info.class with additional attributes.
+ */
+
+public final class ModuleInfoExtender {
+
+    // 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 value of the Version attribute
+    private Version version;
+
+    // the value of the MainClass attribute
+    private String mainClass;
+
+    // the values for the TargetPlatform attribute
+    private String osName;
+    private String osArch;
+    private String osVersion;
+
+    // the hashes for the Hashes attribute
+    private DependencyHashes hashes;
+
+    private ModuleInfoExtender(InputStream in) {
+        this.in = in;
+    }
+
+    /**
+     * Sets the set of packages for the ConcealedPackages attribute
+     */
+    public ModuleInfoExtender conceals(Set<String> packages) {
+        this.conceals = Collections.unmodifiableSet(packages);
+        return this;
+    }
+
+    /**
+     * Sets the value of the Version attribute.
+     */
+    public ModuleInfoExtender version(Version version) {
+        this.version = version;
+        return this;
+    }
+
+    /**
+     * Sets the value of the MainClass attribute.
+     */
+    public ModuleInfoExtender mainClass(String mainClass) {
+        this.mainClass = mainClass;
+        return this;
+    }
+
+    /**
+     * Sets the values for the TargetPlatform attribute.
+     */
+    public ModuleInfoExtender targetPlatform(String osName,
+                                             String osArch,
+                                             String osVersion) {
+        this.osName = osName;
+        this.osArch = osArch;
+        this.osVersion = osVersion;
+        return this;
+    }
+
+    /**
+     * The Hashes attribute will be emitted to the module-info with
+     * the hashes encapsulated in the given {@code DependencyHashes}
+     * object.
+     */
+    public ModuleInfoExtender hashes(DependencyHashes hashes) {
+        this.hashes = hashes;
+        return this;
+    }
+
+    /**
+     * A ClassVisitor that supports adding class file attributes. If an
+     * attribute already exists then the first occurence of the attribute
+     * is replaced.
+     */
+    private static class AttributeAddingClassVisitor extends ClassVisitor {
+        private Map<String, Attribute> attrs = new HashMap<>();
+
+        AttributeAddingClassVisitor(int api, ClassVisitor cv) {
+            super(api, cv);
+        }
+
+        void addAttribute(Attribute attr) {
+            attrs.put(attr.type, attr);
+        }
+
+        @Override
+        public void visitAttribute(Attribute attr) {
+            String name = attr.type;
+            Attribute replacement = attrs.get(name);
+            if (replacement != null) {
+                attr = replacement;
+                attrs.remove(name);
+            }
+            super.visitAttribute(attr);
+        }
+
+        /**
+         * Adds any remaining attributes that weren't replaced to the
+         * class file.
+         */
+        void finish() {
+            attrs.values().forEach(a -> super.visitAttribute(a));
+            attrs.clear();
+        }
+    }
+
+    /**
+     * Outputs the modified module-info.class to the given output stream.
+     * Once this method has been called then the Extender object should
+     * be discarded.
+     */
+    public void write(OutputStream out) throws IOException {
+        ClassWriter cw
+            = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+
+        AttributeAddingClassVisitor cv
+            = new AttributeAddingClassVisitor(Opcodes.ASM5, cw);
+
+        ClassReader cr = new ClassReader(in);
+
+        if (conceals != null)
+            cv.addAttribute(new ConcealedPackagesAttribute(conceals));
+        if (version != null)
+            cv.addAttribute(new VersionAttribute(version));
+        if (mainClass != null)
+            cv.addAttribute(new MainClassAttribute(mainClass));
+        if (osName != null || osArch != null || osVersion != null)
+            cv.addAttribute(new TargetPlatformAttribute(osName, osArch, osVersion));
+        if (hashes != null)
+            cv.addAttribute(new HashesAttribute(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());
+
+        cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
+
+        // add any attributes that didn't replace previous attributes
+        cv.finish();
+
+        // emit to the output stream
+        out.write(cw.toByteArray());
+    }
+
+    /**
+     * Returns an {@code Extender} that may be used to add additional
+     * attributes to the module-info.class read from the given input
+     * stream.
+     */
+    public static ModuleInfoExtender newExtender(InputStream in) {
+        return new ModuleInfoExtender(in);
+    }
+
+}
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
new file mode 100644
index 0000000..f418b66
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.module;
+
+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 jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import static jdk.internal.module.ClassFileAttributes.*;
+import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
+
+/**
+ * Utility class to write a ModuleDescriptor as a module-info.class.
+ */
+
+public final class ModuleInfoWriter {
+
+    private ModuleInfoWriter() { }
+
+    /**
+     * Writes the given module descriptor to a module-info.class file,
+     * returning it in a byte array.
+     */
+    private static byte[] toModuleInfo(ModuleDescriptor descriptor) {
+
+        ClassWriter cw = new ClassWriter(0);
+
+        String name = descriptor.name().replace('.', '/') + "/module-info";
+        cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null);
+
+        cw.visitAttribute(new ModuleAttribute(descriptor));
+        cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals()));
+
+        Optional<Version> oversion = descriptor.version();
+        if (oversion.isPresent())
+            cw.visitAttribute(new VersionAttribute(oversion.get()));
+
+        Optional<String> omain = descriptor.mainClass();
+        if (omain.isPresent())
+            cw.visitAttribute(new MainClassAttribute(omain.get()));
+
+        // write the TargetPlatform attribute if have any of OS name/arch/version
+        String osName = descriptor.osName().orElse(null);
+        String osArch = descriptor.osArch().orElse(null);
+        String osVersion = descriptor.osVersion().orElse(null);
+        if (osName != null || osArch != null || osVersion != null) {
+            cw.visitAttribute(new TargetPlatformAttribute(osName,
+                                                          osArch,
+                                                          osVersion));
+        }
+
+        cw.visitEnd();
+
+        return cw.toByteArray();
+    }
+
+    /**
+     * Writes a module descriptor to the given output stream as a
+     * module-info.class.
+     */
+    public static void write(ModuleDescriptor descriptor, OutputStream out)
+        throws IOException
+    {
+        byte[] bytes = toModuleInfo(descriptor);
+        out.write(bytes);
+    }
+
+    /**
+     * Returns a {@code ByteBuffer} containing the given module descriptor
+     * in module-info.class format.
+     */
+    public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) {
+        byte[] bytes = toModuleInfo(descriptor);
+        return ByteBuffer.wrap(bytes);
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
new file mode 100644
index 0000000..9c3308f
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.lang.module.Configuration;
+import java.lang.module.ResolvedModule;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+import jdk.internal.loader.ClassLoaders;
+
+
+/**
+ * The module to class loader map.  The list of boot modules and platform modules
+ * are generated at build time.
+ */
+final class ModuleLoaderMap {
+    /*
+     * The list of boot modules and platform modules are generated at build time.
+     */
+    private static final String[] BOOT_MODULES
+        = new String[] { "@@BOOT_MODULE_NAMES@@" };
+    private static final String[] PLATFORM_MODULES
+        = new String[] { "@@PLATFORM_MODULE_NAMES@@" };
+
+    /**
+     * Returns the function to map modules in the given configuration to the
+     * built-in class loaders.
+     */
+    static Function<String, ClassLoader> mappingFunction(Configuration cf) {
+
+        Set<String> bootModules = new HashSet<>(BOOT_MODULES.length);
+        for (String mn : BOOT_MODULES) {
+            bootModules.add(mn);
+        }
+
+        Set<String> platformModules = new HashSet<>(PLATFORM_MODULES.length);
+        for (String mn : PLATFORM_MODULES) {
+            platformModules.add(mn);
+        }
+
+        ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
+        ClassLoader appClassLoader = ClassLoaders.appClassLoader();
+
+        Map<String, ClassLoader> map = new HashMap<>();
+
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            String mn = resolvedModule.name();
+            if (!bootModules.contains(mn)) {
+                if (platformModules.contains(mn)) {
+                    map.put(mn, platformClassLoader);
+                } else {
+                    map.put(mn, appClassLoader);
+                }
+            }
+        }
+
+        return new Function<String, ClassLoader> () {
+            @Override
+            public ClassLoader apply(String mn) {
+                return map.get(mn);
+            }
+        };
+    }
+}
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
new file mode 100644
index 0000000..d2224a5
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
@@ -0,0 +1,586 @@
+/*
+ * 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 jdk.internal.module;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+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;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+import sun.misc.Resource;
+import sun.net.www.ParseUtil;
+
+
+/**
+ * Provides support for patching modules in the boot layer with -Xpatch.
+ */
+
+public final class ModulePatcher {
+
+    private static final JavaLangModuleAccess JLMA
+        = SharedSecrets.getJavaLangModuleAccess();
+
+    // the prefix of the system properties that encode the value of -Xpatch
+    private static final String PATCH_PROPERTY_PREFIX = "jdk.launcher.patch.";
+
+    // module name -> sequence of patches (directories or JAR files)
+    private static final Map<String, List<Path>> PATCH_MAP = decodeProperties();
+
+    private ModulePatcher() { }
+
+
+    /**
+     * Decodes the values of -Xpatch options, returning a Map of module name to
+     * list of file paths.
+     *
+     * @throws IllegalArgumentException if the the module name is missing or
+     *         -Xpatch is used more than once to patch the same module
+     */
+    private static Map<String, List<Path>> decodeProperties() {
+
+        int index = 0;
+        String value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
+        if (value == null)
+            return Collections.emptyMap();  // -Xpatch not specified
+
+        Map<String, List<Path>> map = new HashMap<>();
+        while (value != null) {
+            int pos = value.indexOf('=');
+
+            if (pos == -1 && index > 0)
+                throwIAE("Unable to parse: " + value);
+
+            if (pos == 0)
+                throwIAE("Missing module name: " + value);
+
+            if (pos > 0) {
+
+                // new format: <module>=<file>(:<file>)*
+
+                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));
+                    }
+                }
+
+            } else {
+
+                // old format: <dir>(:<dir>)*
+
+                assert index == 0; // old format only allowed in first -Xpatch
+
+                String[] dirs = value.split(File.pathSeparator);
+                for (String d : dirs) {
+                    if (d.length() > 0) {
+                        Path top = Paths.get(d);
+                        try {
+                            Files.list(top).forEach(e -> {
+                                String mn = e.getFileName().toString();
+                                Path dir = top.resolve(mn);
+                                map.computeIfAbsent(mn, k -> new ArrayList<>())
+                                    .add(dir);
+                            });
+                        } catch (IOException ignore) { }
+                    }
+                }
+
+            }
+
+
+            index++;
+            value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
+        }
+
+        return map;
+    }
+
+
+    /**
+     * 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.
+     *
+     * @throws UncheckedIOException if an I/O error is detected
+     */
+    public static ModuleReference interposeIfNeeded(ModuleReference mref) {
+
+        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);
+        if (paths == null)
+            return mref;
+
+
+        // scan the JAR file or directory tree to get the set of packages
+        Set<String> packages = new HashSet<>();
+        try {
+            for (Path file : paths) {
+                if (Files.isRegularFile(file)) {
+
+                    // JAR file
+                    try (JarFile jf = new JarFile(file.toFile())) {
+                        jf.stream()
+                          .filter(e -> e.getName().endsWith(".class"))
+                          .map(e -> toPackageName(file, e))
+                          .filter(pn -> pn.length() > 0)
+                          .forEach(packages::add);
+                    }
+
+                } else if (Files.isDirectory(file)) {
+
+                    // exploded directory
+                    Path top = file;
+                    Files.find(top, Integer.MAX_VALUE,
+                            ((path, attrs) -> attrs.isRegularFile() &&
+                                    path.toString().endsWith(".class")))
+                            .map(path -> toPackageName(top, path))
+                            .filter(pn -> pn.length() > 0)
+                            .forEach(packages::add);
+
+                }
+            }
+
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+
+        // if there are new packages then we need a new ModuleDescriptor
+        Set<String> original = descriptor.packages();
+        packages.addAll(original);
+        if (packages.size() > original.size()) {
+            descriptor = JLMA.newModuleDescriptor(descriptor, packages);
+        }
+
+        // return a new module reference
+        URI location = mref.location().orElse(null);
+        return new ModuleReference(descriptor, location,
+                                   () -> new PatchedModuleReader(paths, mref));
+
+    }
+
+
+    /**
+     * A ModuleReader that reads resources from a patched module.
+     *
+     * This class is public so as to expose the findResource method to the
+     * built-in class loaders and avoid locating the resource twice during
+     * class loading (once to locate the resource, the second to gets the
+     * URL for the CodeSource).
+     */
+    public static class PatchedModuleReader implements ModuleReader {
+        private final List<ResourceFinder> finders;
+        private final ModuleReference mref;
+        private final URL delegateCodeSourceURL;
+        private volatile ModuleReader delegate;
+
+        /**
+         * Creates the ModuleReader to reads resources a patched module.
+         */
+        PatchedModuleReader(List<Path> patches, ModuleReference mref) {
+            List<ResourceFinder> finders = new ArrayList<>();
+            boolean initialized = false;
+            try {
+                for (Path file : patches) {
+                    if (Files.isRegularFile(file)) {
+                        finders.add(new JarResourceFinder(file));
+                    } else {
+                        finders.add(new ExplodedResourceFinder(file));
+                    }
+                }
+                initialized = true;
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            } finally {
+                // close all ResourceFinder in the event of an error
+                if (!initialized) closeAll(finders);
+            }
+
+            this.finders = finders;
+            this.mref = mref;
+            this.delegateCodeSourceURL = codeSourceURL(mref);
+        }
+
+        /**
+         * Closes all resource finders.
+         */
+        private static void closeAll(List<ResourceFinder> finders) {
+            for (ResourceFinder finder : finders) {
+                try { finder.close(); } catch (IOException ioe) { }
+            }
+        }
+
+        /**
+         * Returns the code source URL for the given module.
+         */
+        private static URL codeSourceURL(ModuleReference mref) {
+            try {
+                Optional<URI> ouri = mref.location();
+                if (ouri.isPresent())
+                    return ouri.get().toURL();
+            } catch (MalformedURLException e) { }
+            return null;
+        }
+
+        /**
+         * Returns the ModuleReader to delegate to when the resource is not
+         * found in a patch location.
+         */
+        private ModuleReader delegate() throws IOException {
+            ModuleReader r = delegate;
+            if (r == null) {
+                synchronized (this) {
+                    r = delegate;
+                    if (r == null) {
+                        delegate = r = mref.open();
+                    }
+                }
+            }
+            return r;
+        }
+
+        /**
+         * Finds a resources in the patch locations. Returns null if not found.
+         */
+        private Resource findResourceInPatch(String name) throws IOException {
+            for (ResourceFinder finder : finders) {
+                Resource r = finder.find(name);
+                if (r != null)
+                    return r;
+            }
+            return null;
+        }
+
+        /**
+         * Finds a resource of the given name in the patched module.
+         */
+        public Resource findResource(String name) throws IOException {
+
+            // patch locations
+            Resource r = findResourceInPatch(name);
+            if (r != null)
+                return r;
+
+            // original module
+            ByteBuffer bb = delegate().read(name).orElse(null);
+            if (bb == null)
+                return null;
+
+            return new Resource() {
+                private <T> T shouldNotGetHere(Class<T> type) {
+                    throw new InternalError("should not get here");
+                }
+                @Override
+                public String getName() {
+                    return shouldNotGetHere(String.class);
+                }
+                @Override
+                public URL getURL() {
+                    return shouldNotGetHere(URL.class);
+                }
+                @Override
+                public URL getCodeSourceURL() {
+                    return delegateCodeSourceURL;
+                }
+                @Override
+                public ByteBuffer getByteBuffer() throws IOException {
+                    return bb;
+                }
+                @Override
+                public InputStream getInputStream() throws IOException {
+                    return shouldNotGetHere(InputStream.class);
+                }
+                @Override
+                public int getContentLength() throws IOException {
+                    return shouldNotGetHere(int.class);
+                }
+            };
+        }
+
+        @Override
+        public Optional<URI> find(String name) throws IOException {
+            Resource r = findResourceInPatch(name);
+            if (r != null) {
+                URI uri = URI.create(r.getURL().toString());
+                return Optional.of(uri);
+            } else {
+                return delegate().find(name);
+            }
+        }
+
+        @Override
+        public Optional<InputStream> open(String name) throws IOException {
+            Resource r = findResourceInPatch(name);
+            if (r != null) {
+                return Optional.of(r.getInputStream());
+            } else {
+                return delegate().open(name);
+            }
+        }
+
+        @Override
+        public Optional<ByteBuffer> read(String name) throws IOException {
+            Resource r = findResourceInPatch(name);
+            if (r != null) {
+                ByteBuffer bb = r.getByteBuffer();
+                assert !bb.isDirect();
+                return Optional.of(bb);
+            } else {
+                return delegate().read(name);
+            }
+        }
+
+        @Override
+        public void release(ByteBuffer bb) {
+            if (bb.isDirect()) {
+                try {
+                    delegate().release(bb);
+                } catch (IOException ioe) {
+                    throw new InternalError(ioe);
+                }
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            closeAll(finders);
+            delegate().close();
+        }
+    }
+
+
+    /**
+     * A resource finder that find resources in a patch location.
+     */
+    private static interface ResourceFinder extends Closeable {
+        Resource find(String name) throws IOException;
+    }
+
+
+    /**
+     * A ResourceFinder that finds resources in a JAR file.
+     */
+    private static class JarResourceFinder implements ResourceFinder {
+        private final JarFile jf;
+        private final URL csURL;
+
+        JarResourceFinder(Path path) throws IOException {
+            this.jf = new JarFile(path.toFile());
+            this.csURL = path.toUri().toURL();
+        }
+
+        @Override
+        public void close() throws IOException {
+            jf.close();
+        }
+
+        @Override
+        public Resource find(String name) throws IOException {
+            JarEntry entry = jf.getJarEntry(name);
+            if (entry == null)
+                return null;
+
+            return new Resource() {
+                @Override
+                public String getName() {
+                    return name;
+                }
+                @Override
+                public URL getURL() {
+                    String encodedPath = ParseUtil.encodePath(name, false);
+                    try {
+                        return new URL("jar:" + csURL + "!/" + encodedPath);
+                    } catch (MalformedURLException e) {
+                        return null;
+                    }
+                }
+                @Override
+                public URL getCodeSourceURL() {
+                    return csURL;
+                }
+                @Override
+                public ByteBuffer getByteBuffer() throws IOException {
+                    byte[] bytes = getInputStream().readAllBytes();
+                    return ByteBuffer.wrap(bytes);
+                }
+                @Override
+                public InputStream getInputStream() throws IOException {
+                    return jf.getInputStream(entry);
+                }
+                @Override
+                public int getContentLength() throws IOException {
+                    long size = entry.getSize();
+                    return (size > Integer.MAX_VALUE) ? -1 : (int) size;
+                }
+            };
+        }
+    }
+
+
+    /**
+     * A ResourceFinder that finds resources on the file system.
+     */
+    private static class ExplodedResourceFinder implements ResourceFinder {
+        private final Path dir;
+
+        ExplodedResourceFinder(Path dir) {
+            this.dir = dir;
+        }
+
+        @Override
+        public void close() { }
+
+        @Override
+        public Resource find(String name) throws IOException {
+            Path file = Paths.get(name.replace('/', File.separatorChar));
+            if (file.getRoot() == null) {
+                file = dir.resolve(file);
+            } else {
+                // drop the root component so that the resource is
+                // located relative to the module directory
+                int n = file.getNameCount();
+                if (n == 0)
+                    return null;
+                file = dir.resolve(file.subpath(0, n));
+            }
+
+            if (Files.isRegularFile(file)) {
+                return newResource(name, dir, file);
+            } else {
+                return null;
+            }
+        }
+
+        private Resource newResource(String name, Path top, Path file) {
+            return new Resource() {
+                @Override
+                public String getName() {
+                    return name;
+                }
+                @Override
+                public URL getURL() {
+                    try {
+                        return file.toUri().toURL();
+                    } catch (IOException | IOError e) {
+                        return null;
+                    }
+                }
+                @Override
+                public URL getCodeSourceURL() {
+                    try {
+                        return top.toUri().toURL();
+                    } catch (IOException | IOError e) {
+                        return null;
+                    }
+                }
+                @Override
+                public ByteBuffer getByteBuffer() throws IOException {
+                    return ByteBuffer.wrap(Files.readAllBytes(file));
+                }
+                @Override
+                public InputStream getInputStream() throws IOException {
+                    return Files.newInputStream(file);
+                }
+                @Override
+                public int getContentLength() throws IOException {
+                    long size = Files.size(file);
+                    return (size > Integer.MAX_VALUE) ? -1 : (int)size;
+                }
+            };
+        }
+    }
+
+
+    /**
+     * Derives a package name from a file path to a .class file.
+     */
+    private static String toPackageName(Path top, Path file) {
+        Path entry = top.relativize(file);
+        Path parent = entry.getParent();
+        if (parent == null) {
+            return warnUnnamedPackage(top, entry.toString());
+        } else {
+            return parent.toString().replace(File.separatorChar, '.');
+        }
+    }
+
+    /**
+     * Derives a package name from the name of an entry in a JAR file.
+     */
+    private static String toPackageName(Path file, JarEntry entry) {
+        String name = entry.getName();
+        int index = name.lastIndexOf("/");
+        if (index == -1) {
+            return warnUnnamedPackage(file, name);
+        } else {
+            return name.substring(0, index).replace('/', '.');
+        }
+    }
+
+    private static String warnUnnamedPackage(Path file, String e) {
+        System.err.println("WARNING: " + e + " not allowed in patch: " + file);
+        return "";
+    }
+
+    private static void throwIAE(String msg) {
+        throw new IllegalArgumentException(msg);
+    }
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..b33b1a8
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Module;
+import java.net.URI;
+import java.util.Set;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.ClassLoaders;
+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
+ * to add read edges when agents are instrumenting code that need to link
+ * to supporting classes.
+ *
+ * The parameters that are package names in this API are the fully-qualified
+ * names of the packages as defined in section 6.5.3 of <cite>The Java&trade;
+ * Language Specification </cite>, for example, {@code "java.lang"}.
+ */
+
+public class Modules {
+    private Modules() { }
+
+    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.
+     *
+     * The resulting Module is in a larva state in that it does not not read
+     * any other module and does not have any exports.
+     *
+     * The URI is for information purposes only.
+     */
+    public static Module defineModule(ClassLoader loader,
+                                      ModuleDescriptor descriptor,
+                                      URI uri)
+    {
+        return JLRMA.defineModule(loader, descriptor, uri);
+    }
+
+    /**
+     * Define a new module to the VM. The module has the given set of
+     * concealed packages and is defined to the given class loader.
+     *
+     * The resulting Module is in a larva state in that it does not not read
+     * any other module and does not have any exports.
+     */
+    public static Module defineModule(ClassLoader loader,
+                                      String name,
+                                      Set<String> packages)
+    {
+        ModuleDescriptor descriptor
+            = new ModuleDescriptor.Builder(name).conceals(packages).build();
+
+        return JLRMA.defineModule(loader, descriptor, null);
+    }
+
+    /**
+     * Adds a read-edge so that module {@code m1} reads module {@code m1}.
+     * Same as m1.addReads(m2) but without a caller check.
+     */
+    public static void addReads(Module m1, Module m2) {
+        JLRMA.addReads(m1, m2);
+    }
+
+    /**
+     * Updates module m1 to export a package to module m2.
+     * Same as m1.addExports(pkg, m2) but without a caller check.
+     */
+    public static void addExports(Module m1, String pn, Module m2) {
+        JLRMA.addExports(m1, pn, m2);
+    }
+
+    /**
+     * Updates a module m to export a package to all modules.
+     */
+    public static void addExportsToAll(Module m, String pn) {
+        JLRMA.addExportsToAll(m, pn);
+    }
+
+    /**
+     * Updates module m to export a package to all unnamed modules.
+     */
+    public static void addExportsToAllUnnamed(Module m, String pn) {
+        JLRMA.addExportsToAllUnnamed(m, pn);
+    }
+
+    /**
+     * Adds a package to a module's content.
+     *
+     * This method is a no-op if the module already contains the package.
+     */
+    public static void addPackage(Module m, String pn) {
+        JLRMA.addPackage(m, pn);
+    }
+
+    /**
+     * Called by the VM when code in the given Module has been transformed by
+     * an agent and so may have been instrumented to call into supporting
+     * classes on the boot class path or application class path.
+     */
+    public static void transformedByAgent(Module m) {
+        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
new file mode 100644
index 0000000..5d597f9
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.lang.reflect.Module;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * A services catalog. Each {@code ClassLoader} has an optional {@code
+ * ServicesCatalog} for modules that provide services. This is to support
+ * ClassLoader centric ServiceLoader.load methods.
+ */
+public class ServicesCatalog {
+
+    // use RW locks as register is rare
+    private final ReadWriteLock lock = new ReentrantReadWriteLock();
+    private final Lock readLock = lock.readLock();
+    private final Lock writeLock = lock.writeLock();
+
+    /**
+     * Represents a service provider in the services catalog.
+     */
+    public class ServiceProvider {
+        private final Module module;
+        private final String providerName;
+        ServiceProvider(Module module, String providerName) {
+            this.module = module;
+            this.providerName = providerName;
+        }
+        public Module module() {
+            return module;
+        }
+        public String providerName() {
+            return providerName;
+        }
+    }
+
+    // service providers
+    private final Map<String, Set<ServiceProvider>> loaderServices = new HashMap<>();
+
+    /**
+     * Creates a new module catalog.
+     */
+    public ServicesCatalog() { }
+
+    /**
+     * Registers the module in this module catalog.
+     */
+    public void register(Module m) {
+        ModuleDescriptor descriptor = m.getDescriptor();
+
+        writeLock.lock();
+        try {
+            // extend the services map
+            for (Provides ps : descriptor.provides().values()) {
+                String service = ps.service();
+                Set<String> providerNames = ps.providers();
+
+                // create a new set to replace the existing
+                Set<ServiceProvider> result = new HashSet<>();
+                Set<ServiceProvider> providers = loaderServices.get(service);
+                if (providers != null) {
+                    result.addAll(providers);
+                }
+                for (String pn : providerNames) {
+                    result.add(new ServiceProvider(m, pn));
+                }
+                loaderServices.put(service, Collections.unmodifiableSet(result));
+            }
+
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Returns the (possibly empty) set of service providers that implement the
+     * given service type.
+     *
+     * @see java.util.ServiceLoader
+     */
+    public Set<ServiceProvider> findServices(String service) {
+        readLock.lock();
+        try {
+            return loaderServices.getOrDefault(service, Collections.emptySet());
+        } finally {
+            readLock.unlock();
+        }
+    }
+}
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
new file mode 100644
index 0000000..3bd1371
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.lang.module.ModuleDescriptor;
+
+/*
+ * SystemModules class will be generated at link time to create
+ * ModuleDescriptor for the installed modules directly to improve
+ * the module descriptor reconstitution time.
+ *
+ * This will skip parsing of module-info.class file and validating
+ * names such as module name, package name, service and provider type names.
+ * It also avoids taking a defensive copy of any collection.
+ *
+ * @see jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin
+ */
+public final class SystemModules {
+    /**
+     * Name of the installed modules.
+     *
+     * This array provides a way for InstalledModuleFinder to fallback
+     * and read module-info.class from the run-time image instead of
+     * the fastpath.
+     */
+    public static final String[] MODULE_NAMES = new String[1];
+
+    /**
+     * Number of packages in the boot layer from the installed modules.
+     *
+     * Don't make it final to avoid inlining during compile time as
+     * the value will be changed at jlink time.
+     */
+    public static final int PACKAGES_IN_BOOT_LAYER = 1024;
+
+    /**
+     * Returns a non-empty array of ModuleDescriptors in the run-time image.
+     *
+     * When running an exploded image it returns an empty array.
+     */
+    public static ModuleDescriptor[] modules() {
+        return new ModuleDescriptor[0];
+    }
+}
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java b/jdk/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java
index 1c0d0a1..790bbeb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java
@@ -67,11 +67,11 @@
         this.lb = bb.asLongBuffer();
     }
 
-    static PerfCounter newPerfCounter(String name) {
+    public static PerfCounter newPerfCounter(String name) {
         return new PerfCounter(name, V_Variable);
     }
 
-    static PerfCounter newConstantPerfCounter(String name) {
+    public static PerfCounter newConstantPerfCounter(String name) {
         PerfCounter c = new PerfCounter(name, V_Constant);
         return c;
     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat b/jdk/src/java.base/share/classes/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat
new file mode 100644
index 0000000..a634d5b
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/vm/cds/resources/ModuleLoaderMap.dat
@@ -0,0 +1,4 @@
+BOOT
+@@BOOT_MODULE_NAMES@@
+PLATFORM
+@@PLATFORM_MODULE_NAMES@@
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
new file mode 100644
index 0000000..f54043d
--- /dev/null
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * java.base defines and exports the core APIs of the Java SE platform.
+ */
+
+module java.base {
+
+    exports java.io;
+    exports java.lang;
+    exports java.lang.annotation;
+    exports java.lang.invoke;
+    exports java.lang.module;
+    exports java.lang.ref;
+    exports java.lang.reflect;
+    exports java.math;
+    exports java.net;
+    exports java.net.spi;
+    exports java.nio;
+    exports java.nio.channels;
+    exports java.nio.channels.spi;
+    exports java.nio.charset;
+    exports java.nio.charset.spi;
+    exports java.nio.file;
+    exports java.nio.file.attribute;
+    exports java.nio.file.spi;
+    exports java.security;
+    exports java.security.acl;
+    exports java.security.cert;
+    exports java.security.interfaces;
+    exports java.security.spec;
+    exports java.text;
+    exports java.text.spi;
+    exports java.time;
+    exports java.time.chrono;
+    exports java.time.format;
+    exports java.time.temporal;
+    exports java.time.zone;
+    exports java.util;
+    exports java.util.concurrent;
+    exports java.util.concurrent.atomic;
+    exports java.util.concurrent.locks;
+    exports java.util.function;
+    exports java.util.jar;
+    exports java.util.regex;
+    exports java.util.spi;
+    exports java.util.stream;
+    exports java.util.zip;
+    exports javax.crypto;
+    exports javax.crypto.interfaces;
+    exports javax.crypto.spec;
+    exports javax.net;
+    exports javax.net.ssl;
+    exports javax.security.auth;
+    exports javax.security.auth.callback;
+    exports javax.security.auth.login;
+    exports javax.security.auth.spi;
+    exports javax.security.auth.x500;
+    exports javax.security.cert;
+
+    // see JDK-8144062
+    exports jdk;
+    // see JDK-8044773
+    exports jdk.net;
+
+    // These will move to a jdk.internal module via JEP-260
+    exports sun.misc;
+    exports sun.reflect;
+
+
+    // the service types defined by the APIs in this module
+
+    uses java.lang.System.LoggerFinder;
+    uses java.net.ContentHandlerFactory;
+    uses java.net.spi.URLStreamHandlerProvider;
+    uses java.nio.channels.spi.AsynchronousChannelProvider;
+    uses java.nio.channels.spi.SelectorProvider;
+    uses java.nio.charset.spi.CharsetProvider;
+    uses java.nio.file.spi.FileSystemProvider;
+    uses java.nio.file.spi.FileTypeDetector;
+    uses java.security.Provider;
+    uses java.text.spi.BreakIteratorProvider;
+    uses java.text.spi.CollatorProvider;
+    uses java.text.spi.DateFormatProvider;
+    uses java.text.spi.DateFormatSymbolsProvider;
+    uses java.text.spi.DecimalFormatSymbolsProvider;
+    uses java.text.spi.NumberFormatProvider;
+    uses java.time.chrono.AbstractChronology;
+    uses java.time.chrono.Chronology;
+    uses java.time.zone.ZoneRulesProvider;
+    uses java.util.spi.CalendarDataProvider;
+    uses java.util.spi.CalendarNameProvider;
+    uses java.util.spi.CurrencyNameProvider;
+    uses java.util.spi.LocaleNameProvider;
+    uses java.util.spi.ResourceBundleControlProvider;
+    uses java.util.spi.ResourceBundleProvider;
+    uses java.util.spi.TimeZoneNameProvider;
+    uses javax.security.auth.spi.LoginModule;
+
+
+    // 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.logger to
+        java.logging;
+    exports jdk.internal.org.objectweb.asm to
+        jdk.jlink,
+        jdk.scripting.nashorn,
+        jdk.vm.ci;
+    exports jdk.internal.org.objectweb.asm.tree to
+        jdk.jlink;
+    exports jdk.internal.org.objectweb.asm.util to
+        jdk.jlink,
+        jdk.scripting.nashorn;
+    exports jdk.internal.org.objectweb.asm.tree.analysis to
+        jdk.jlink;
+    exports jdk.internal.org.objectweb.asm.commons to
+        jdk.scripting.nashorn;
+    exports jdk.internal.org.objectweb.asm.signature to
+        jdk.scripting.nashorn;
+    exports jdk.internal.math to
+        java.desktop;
+    exports jdk.internal.module to
+        java.instrument,
+        java.management,
+        java.xml,
+        jdk.dynalink,
+        jdk.jartool,
+        jdk.jlink,
+        jdk.scripting.nashorn;
+    exports jdk.internal.misc to
+        java.corba,
+        java.desktop,
+        java.logging,
+        java.management,
+        java.naming,
+        java.rmi,
+        java.security.jgss,
+        java.sql,
+        java.xml,
+        jdk.charsets,
+        jdk.scripting.nashorn,
+        jdk.vm.ci;
+    exports jdk.internal.perf to
+        java.desktop,
+        java.management,
+        jdk.jvmstat;
+    exports jdk.internal.ref to
+        java.desktop;
+    exports sun.net to
+        java.httpclient;
+    exports sun.net.dns to
+        java.security.jgss,
+        jdk.naming.dns;
+    exports sun.net.spi.nameservice to
+        jdk.naming.dns;
+    exports sun.net.util to
+        java.desktop,
+        jdk.jconsole,
+        jdk.naming.dns;
+    exports sun.net.www to
+        java.desktop,
+        jdk.jartool;
+    exports sun.net.www.protocol.http to
+        java.security.jgss;
+    exports sun.nio.ch to
+        java.management,
+        jdk.crypto.pkcs11,
+        jdk.sctp;
+    exports sun.nio.cs to
+        java.desktop,
+        jdk.charsets;
+    exports sun.reflect.annotation to
+        jdk.compiler;
+    exports sun.reflect.generics.reflectiveObjects to
+        java.desktop;
+    exports sun.reflect.misc to
+        java.corba,
+        java.desktop,
+        java.datatransfer,
+        java.management,
+        java.rmi,
+        java.sql.rowset,
+        java.xml,
+        java.xml.ws;
+    exports sun.security.action to
+        java.desktop,
+        java.security.jgss,
+        jdk.crypto.pkcs11;
+    exports sun.security.internal.interfaces to
+        jdk.crypto.pkcs11;
+    exports sun.security.internal.spec to
+        jdk.crypto.pkcs11;
+    exports sun.security.jca to
+        java.smartcardio,
+        java.xml.crypto,
+        jdk.crypto.ec,
+        jdk.crypto.pkcs11,
+        jdk.naming.dns;
+    exports sun.security.pkcs to
+        jdk.crypto.ec,
+        jdk.jartool;
+    exports sun.security.provider to
+        java.rmi,
+        java.security.jgss,
+        jdk.crypto.pkcs11,
+        jdk.policytool,
+        jdk.security.auth;
+    exports sun.security.provider.certpath to
+        java.naming;
+    exports sun.security.rsa to
+        jdk.crypto.pkcs11;
+    exports sun.security.ssl to
+        java.security.jgss;
+    exports sun.security.tools to
+        jdk.jartool;
+    exports sun.security.util to
+        java.desktop,
+        java.naming,
+        java.rmi,
+        java.security.jgss,
+        java.security.sasl,
+        java.smartcardio,
+        jdk.crypto.ec,
+        jdk.crypto.pkcs11,
+        jdk.jartool,
+        jdk.policytool,
+        jdk.security.auth,
+        jdk.security.jgss;
+    exports sun.security.x509 to
+        jdk.crypto.ec,
+        jdk.crypto.pkcs11,
+        jdk.jartool,
+        jdk.security.auth;
+    exports sun.text.resources to
+        jdk.localedata;
+    exports sun.util.resources to
+        jdk.localedata;
+    exports sun.util.locale.provider to
+        java.desktop,
+        jdk.localedata;
+    exports sun.util.logging to
+        java.desktop,
+        java.httpclient,
+        java.logging,
+        java.prefs;
+
+    // JDK-internal service types
+    uses jdk.internal.logger.DefaultLoggerFinder;
+    uses sun.net.spi.nameservice.NameServiceDescriptor;
+    uses sun.security.ssl.ClientKeyExchangeService;
+    uses sun.util.spi.CalendarProvider;
+    uses sun.util.locale.provider.LocaleDataMetaInfo;
+    uses sun.util.resources.LocaleData.CommonResourceBundleProvider;
+    uses sun.util.resources.LocaleData.SupplementaryResourceBundleProvider;
+
+
+    // Built-in service providers that are located via ServiceLoader
+
+    provides java.nio.file.spi.FileSystemProvider with
+        jdk.internal.jrtfs.JrtFileSystemProvider;
+    provides java.security.Provider with sun.security.provider.Sun;
+    provides java.security.Provider with sun.security.rsa.SunRsaSign;
+    provides java.security.Provider with com.sun.crypto.provider.SunJCE;
+    provides java.security.Provider with com.sun.net.ssl.internal.ssl.Provider;
+}
+
diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java
index e10d2e1..2d6b234 100644
--- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java
@@ -27,6 +27,7 @@
 
 import java.lang.reflect.Modifier;
 import static java.lang.reflect.Modifier.*;
+import java.lang.reflect.Module;
 import sun.reflect.Reflection;
 
 /**
@@ -37,6 +38,7 @@
 
     private VerifyAccess() { }  // cannot instantiate
 
+    private static final int MODULE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.MODULE;
     private static final int PACKAGE_ONLY = 0;
     private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
     private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
@@ -89,7 +91,7 @@
                                              int      allowedModes) {
         if (allowedModes == 0)  return false;
         assert((allowedModes & PUBLIC) != 0 &&
-               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
+               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED)) == 0);
         // The symbolic reference class (refc) must always be fully verified.
         if (!isClassAccessible(refc, lookupClass, allowedModes)) {
             return false;
@@ -157,8 +159,10 @@
      * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
      * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
      * A class or interface C is accessible to a class or interface D
-     * if and only if either of the following conditions are true:<ul>
-     * <li>C is public.
+     * if and only if any of the following conditions are true:<ul>
+     * <li>C is public and in the same module as D.
+     * <li>D is in a module that reads the module containing C, C is public and in a
+     * package that is exported to the module that contains D.
      * <li>C and D are members of the same runtime package.
      * </ul>
      * @param refc the symbolic reference class to which access is being checked (C)
@@ -168,10 +172,52 @@
                                             int allowedModes) {
         if (allowedModes == 0)  return false;
         assert((allowedModes & PUBLIC) != 0 &&
-               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
+               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED|MODULE_ALLOWED)) == 0);
         int mods = getClassModifiers(refc);
-        if (isPublic(mods))
-            return true;
+        if (isPublic(mods)) {
+
+            Module lookupModule = lookupClass.getModule();
+            Module refModule = refc.getModule();
+
+            // early VM startup case, java.base not defined
+            if (lookupModule == null) {
+                assert refModule == null;
+                return true;
+            }
+
+            // trivially allow
+            if ((allowedModes & MODULE_ALLOWED) != 0 &&
+                (lookupModule == refModule))
+                return true;
+
+            // check readability
+            if (lookupModule.canRead(refModule)) {
+
+                // check that refc is in an exported package
+                Class<?> c = refc;
+                while (c.isArray()) {
+                    c = c.getComponentType();
+                }
+                if (c.isPrimitive())
+                    return true;
+                if ((allowedModes & MODULE_ALLOWED) != 0) {
+                    if (refModule.isExported(c.getPackageName(), lookupModule))
+                        return true;
+                } else {
+                    // exported unconditionally
+                    if (refModule.isExported(c.getPackageName()))
+                        return true;
+                }
+
+                // not exported but allow access during VM initialization
+                // because java.base does not have its exports setup
+                if (!jdk.internal.misc.VM.isModuleSystemInited())
+                    return true;
+            }
+
+            // public class not accessible to lookupClass
+            return false;
+        }
         if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
             isSamePackage(lookupClass, refc))
             return true;
@@ -219,6 +265,16 @@
     }
 
     /**
+     * Tests if two classes are in the same module.
+     * @param class1 a class
+     * @param class2 another class
+     * @return whether they are in the same module
+     */
+    public static boolean isSameModule(Class<?> class1, Class<?> class2) {
+        return class1.getModule() == class2.getModule();
+    }
+
+    /**
      * Test if two classes have the same class loader and package qualifier.
      * @param class1 a class
      * @param class2 another class
@@ -244,10 +300,10 @@
     /** Return the package name for this class.
      */
     public static String getPackageName(Class<?> cls) {
-        assert(!cls.isArray());
+        assert (!cls.isArray());
         String name = cls.getName();
         int dot = name.lastIndexOf('.');
-        if (dot < 0)  return "";
+        if (dot < 0) return "";
         return name.substring(0, dot);
     }
 
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 3f9e366..e8a4b78 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -43,24 +43,39 @@
 import java.io.IOException;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.reflect.Layer;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.URI;
 import java.nio.charset.Charset;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.text.Normalizer;
-import java.util.ResourceBundle;
 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.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale.Category;
+import java.util.Optional;
 import java.util.Properties;
+import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.jar.Attributes;
@@ -68,6 +83,7 @@
 import java.util.jar.Manifest;
 import jdk.internal.misc.VM;
 
+
 public enum LauncherHelper {
     INSTANCE;
 
@@ -98,7 +114,6 @@
                 ResourceBundle.getBundle(defaultBundleName);
     }
     private static PrintStream ostream;
-    private static final ClassLoader scloader = ClassLoader.getSystemClassLoader();
     private static Class<?> appClass; // application class, for GUI/reporting purposes
 
     /*
@@ -439,11 +454,12 @@
     }
 
     // From src/share/bin/java.c:
-    //   enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR };
+    //   enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE }
 
     private static final int LM_UNKNOWN = 0;
     private static final int LM_CLASS   = 1;
     private static final int LM_JAR     = 2;
+    private static final int LM_MODULE  = 3;
 
     static void abort(Throwable t, String msgKey, Object... args) {
         if (msgKey != null) {
@@ -460,33 +476,95 @@
     }
 
     /**
-     * This method does the following:
-     * 1. gets the classname from a Jar's manifest, if necessary
-     * 2. loads the class using the System ClassLoader
-     * 3. ensures the availability and accessibility of the main method,
-     *    using signatureDiagnostic method.
-     *    a. does the class exist
-     *    b. is there a main
-     *    c. is the main public
-     *    d. is the main static
-     *    e. does the main take a String array for args
-     * 4. if no main method and if the class extends FX Application, then call
-     *    on FXHelper to determine the main class to launch
-     * 5. and off we go......
+     * This method:
+     * 1. Loads the main class from the module or class path
+     * 2. Checks the public static void main method.
      *
      * @param printToStderr if set, all output will be routed to stderr
      * @param mode LaunchMode as determined by the arguments passed on the
-     * command line
-     * @param what either the jar file to launch or the main class when using
-     * LM_CLASS mode
+     *             command line
+     * @param what the module name[/class], JAR file, or the main class
+     *             depending on the mode
+     *
      * @return the application's main class
      */
     public static Class<?> checkAndLoadMain(boolean printToStderr,
                                             int mode,
                                             String what) {
         initOutput(printToStderr);
+
+        Class<?> mainClass = (mode == LM_MODULE) ? loadModuleMainClass(what)
+                                                 : loadMainClass(mode, what);
+
+        validateMainClass(mainClass);
+
+        // record main class if not already set
+        if (appClass == null)
+            appClass = mainClass;
+
+        return mainClass;
+    }
+
+    /**
+     * Returns the main class for a module. The query is either a module name
+     * or module-name/main-class. For the former then the module's main class
+     * is obtained from the module descriptor (MainClass attribute).
+     */
+    private static Class<?> loadModuleMainClass(String what) {
+        int i = what.indexOf('/');
+        String mainModule;
+        String mainClass;
+        if (i == -1) {
+            mainModule = what;
+            mainClass = null;
+        } else {
+            mainModule = what.substring(0, i);
+            mainClass = what.substring(i+1);
+        }
+
+        // main module is in the boot layer
+        Layer layer = Layer.boot();
+        Optional<Module> om = layer.findModule(mainModule);
+        if (!om.isPresent()) {
+            // should not happen
+            throw new InternalError("Module " + mainModule + " not in boot Layer");
+        }
+        Module m = om.get();
+
+        // get main class
+        if (mainClass == null) {
+            Optional<String> omc = m.getDescriptor().mainClass();
+            if (!omc.isPresent()) {
+                abort(null, "java.launcher.module.error1", mainModule);
+            }
+            mainClass = omc.get();
+        }
+
+        // load the class from the module
+        Class<?> c = Class.forName(m, mainClass);
+        if (c == null &&  System.getProperty("os.name", "").contains("OS X")
+                && Normalizer.isNormalized(mainClass, Normalizer.Form.NFD)) {
+
+            String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC);
+            c = Class.forName(m, cn);
+
+        }
+        if (c == null) {
+            abort(null, "java.launcher.module.error2", mainClass, mainModule);
+        }
+
+        System.setProperty("jdk.module.main.class", c.getName());
+        return c;
+    }
+
+    /**
+     * Loads the main class from the class path (LM_CLASS or LM_JAR).
+     * If the main class extends FX Application then call on FXHelper to
+     * determine the main class to launch.
+     */
+    private static Class<?> loadMainClass(int mode, String what) {
         // get the class name
-        String cn = null;
+        String cn;
         switch (mode) {
             case LM_CLASS:
                 cn = what;
@@ -498,18 +576,21 @@
                 // should never happen
                 throw new InternalError("" + mode + ": Unknown launch mode");
         }
+
+        // load the main class
         cn = cn.replace('/', '.');
         Class<?> mainClass = null;
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
         try {
-            mainClass = scloader.loadClass(cn);
+            mainClass = scl.loadClass(cn);
         } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
             if (System.getProperty("os.name", "").contains("OS X")
-                && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
+                    && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
                 try {
                     // On Mac OS X since all names with diacretic symbols are given as decomposed it
                     // is possible that main class name comes incorrectly from the command line
                     // and we have to re-compose it
-                    mainClass = scloader.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC));
+                    mainClass = scl.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC));
                 } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) {
                     abort(cnfe, "java.launcher.cls.error1", cn);
                 }
@@ -517,7 +598,8 @@
                 abort(cnfe, "java.launcher.cls.error1", cn);
             }
         }
-        // set to mainClass
+
+        // record the main class
         appClass = mainClass;
 
         /*
@@ -531,8 +613,6 @@
             FXHelper.setFXLaunchParameters(what, mode);
             return FXHelper.class;
         }
-
-        validateMainClass(mainClass);
         return mainClass;
     }
 
@@ -693,6 +773,9 @@
 
     static final class FXHelper {
 
+        private static final String JAVAFX_GRAPHICS_MODULE_NAME =
+                "javafx.graphics";
+
         private static final String JAVAFX_LAUNCHER_CLASS_NAME =
                 "com.sun.javafx.application.LauncherImpl";
 
@@ -725,9 +808,20 @@
          * issue with loading the FX runtime or with the launcher method.
          */
         private static void setFXLaunchParameters(String what, int mode) {
-            // Check for the FX launcher classes
+
+            // find the module with the FX launcher
+            Optional<Module> om = Layer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
+            if (!om.isPresent()) {
+                abort(null, "java.launcher.cls.error5");
+            }
+
+            // load the FX launcher class
+            fxLauncherClass = Class.forName(om.get(), JAVAFX_LAUNCHER_CLASS_NAME);
+            if (fxLauncherClass == null) {
+                abort(null, "java.launcher.cls.error5");
+            }
+
             try {
-                fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME);
                 /*
                  * signature must be:
                  * public static void launchApplication(String launchName,
@@ -744,7 +838,7 @@
                 if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) {
                     abort(null, "java.launcher.javafx.error1");
                 }
-            } catch (ClassNotFoundException | NoSuchMethodException ex) {
+            } catch (NoSuchMethodException ex) {
                 abort(ex, "java.launcher.cls.error5", ex);
             }
 
@@ -773,4 +867,97 @@
                     new Object[] {fxLaunchName, fxLaunchMode, args});
         }
     }
+
+    private static void formatCommaList(PrintStream out,
+                                        String prefix,
+                                        Collection<?> list)
+    {
+        if (list.isEmpty())
+            return;
+        out.format("%s", prefix);
+        boolean first = true;
+        for (Object ob : list) {
+            if (first) {
+                out.format(" %s", ob);
+                first = false;
+            } else {
+                out.format(", %s", ob);
+            }
+        }
+        out.format("%n");
+    }
+
+    /**
+     * Called by the launcher to list the observable modules.
+     * If called without any sub-options then the output is a simple list of
+     * the modules. If called with sub-options then the sub-options are the
+     * names of the modules to list (-listmods:java.base,java.desktop for
+     * example).
+     */
+    static void listModules(boolean printToStderr, String optionFlag)
+        throws IOException, ClassNotFoundException
+    {
+        initOutput(printToStderr);
+
+        ModuleFinder finder = jdk.internal.module.ModuleBootstrap.finder();
+
+        int colon = optionFlag.indexOf(':');
+        if (colon == -1) {
+            finder.findAll().stream()
+                .sorted(Comparator.comparing(ModuleReference::descriptor))
+                .forEach(md -> {
+                    ostream.println(midAndLocation(md.descriptor(),
+                                                   md.location()));
+                });
+        } else {
+            String[] names = optionFlag.substring(colon+1).split(",");
+            for (String name: names) {
+                ModuleReference mref = finder.find(name).orElse(null);
+                if (mref == null) {
+                    // not found
+                    continue;
+                }
+
+                ModuleDescriptor md = mref.descriptor();
+                ostream.println(midAndLocation(md, mref.location()));
+
+                for (Requires d : md.requires()) {
+                    ostream.format("  requires %s%n", d);
+                }
+                for (String s : md.uses()) {
+                    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());
+                    if (e.isQualified()) {
+                        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);
+                }
+            }
+        }
+    }
+
+    static String midAndLocation(ModuleDescriptor md, Optional<URI> location ) {
+        URI loc = location.orElse(null);
+        if (loc == null || loc.getScheme().equalsIgnoreCase("jrt"))
+            return md.toNameAndVersion();
+        else
+            return md.toNameAndVersion() + " (" + loc + ")";
+    }
 }
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 7809020..52d621b 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
@@ -27,6 +27,8 @@
 java.launcher.opt.header  =   Usage: {0} [options] class [args...]\n\
 \           (to execute a class)\n   or  {0} [options] -jar jarfile [args...]\n\
 \           (to execute a jar file)\n\
+\   or  {0} [-options] -mp <modulepath> -m <modulename> | <modulename>/<mainclass>\n\
+\           (to execute the main class in a module)\n\
 where options include:\n
 
 java.launcher.opt.datamodel  =\    -d{0}\t  use a {0}-bit data model if available\n
@@ -41,6 +43,22 @@
 \    -classpath <class search path of directories and zip/jar files>\n\
 \                  A {0} separated list of directories, JAR archives,\n\
 \                  and ZIP archives to search for class files.\n\
+\    -mp <module path>\n\
+\    -modulepath <module path>...\n\
+\                  A {0} separated list of directories, each directory\n\
+\                  is a directory of modules.\n\
+\    -upgrademodulepath <module path>...\n\
+\                  A {0} separated list of directories, each directory\n\
+\                  is a directory of modules that replace upgradeable\n\
+\                  modules in the runtime image\n\
+\    -m <modulename> | <modulename>/<mainclass>\n\
+\                  the initial or main module to resolve\n\
+\    -addmods <modulename>[,<modulename>...]\n\
+\                  root modules to resolve in addition to the initial module\n\
+\    -limitmods <modulename>[,<modulename>...]\n\
+\                  limit the universe of observable modules\n\
+\    -listmods[:<modulename>[,<modulename>...]]\n\
+\                  list the observable modules and exit\n\
 \    -D<name>=<value>\n\
 \                  set a system property\n\
 \    -verbose:[class|gc|jni]\n\
@@ -76,13 +94,10 @@
 java.launcher.X.usage=\
 \    -Xmixed           mixed mode execution (default)\n\
 \    -Xint             interpreted mode execution only\n\
-\    -Xbootclasspath:<directories and zip/jar files separated by {0}>\n\
-\                      set search path for bootstrap classes and resources\n\
 \    -Xbootclasspath/a:<directories and zip/jar files separated by {0}>\n\
 \                      append to end of bootstrap class path\n\
-\    -Xbootclasspath/p:<directories and zip/jar files separated by {0}>\n\
-\                      prepend in front of bootstrap class path\n\
 \    -Xdiag            show additional diagnostic messages\n\
+\    -Xdiag:resolver   show resolver diagnostic messages\n\
 \    -Xnoclassgc       disable class garbage collection\n\
 \    -Xincgc           enable incremental garbage collection\n\
 \    -Xloggc:<file>    log GC status to a file with time stamps\n\
@@ -105,6 +120,15 @@
 \                      show all property settings and continue\n\
 \    -XshowSettings:locale\n\
 \                      show all locale related settings and continue\n\
+\    -XaddReads:<module>=<other-module>(,<other-module>)*\n\
+\                      <module> reads other modules,\n\
+\                      regardless of module declaration\n\
+\    -XaddExports:<module>/<package>=<other-module>(,<other-module>)*\n\
+\                      <module> exports <package> to other modules,\n\
+\                      regardless of module declaration\n\
+\    -Xpatch:<module>=<file>({0}<file>)*\n\
+\                      Override or augment a module with classes and resources\n\
+\                      in JAR files or directories\n\
 \    -Xdisable-@files  disable further argument file expansion\n\n\
 The -X options are non-standard and subject to change without notice.\n
 
@@ -142,3 +166,7 @@
 java.launcher.javafx.error1=\
     Error: The JavaFX launchApplication method has the wrong signature, it\n\
     must be declared static and return a value of type void
+java.launcher.module.error1=\
+    module {0} does not have a MainClass attribute, use -m <module>/<main-class>
+java.launcher.module.error2=\
+    Error: Could not find or load main class {0} in module {1}
diff --git a/jdk/src/java.base/share/classes/sun/misc/Launcher.java b/jdk/src/java.base/share/classes/sun/misc/Launcher.java
deleted file mode 100644
index 3784474..0000000
--- a/jdk/src/java.base/share/classes/sun/misc/Launcher.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.io.File;
-import java.io.FilePermission;
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.MalformedURLException;
-import java.net.URLStreamHandler;
-import java.net.URLStreamHandlerFactory;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.AccessControlContext;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.Permission;
-import java.security.ProtectionDomain;
-import java.security.CodeSource;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import sun.net.www.ParseUtil;
-import sun.security.util.SecurityConstants;
-
-/**
- * This class is used by the system to launch the main application.
-Launcher */
-public class Launcher {
-
-    // ensure URLClassPath for boot loader is initialized first
-    static {
-        URLClassPath ucp = BootClassPathHolder.bcp;
-    }
-
-    private static URLStreamHandlerFactory factory = new Factory();
-    private static Launcher launcher = new Launcher();
-
-    public static Launcher getLauncher() {
-        return launcher;
-    }
-
-    private ClassLoader loader;
-
-    public Launcher() {
-        // Create the extension class loader
-        ClassLoader extcl;
-        try {
-            extcl = ExtClassLoader.getExtClassLoader();
-        } catch (IOException e) {
-            throw new InternalError(
-                "Could not create extension class loader", e);
-        }
-
-        // Now create the class loader to use to launch the application
-        try {
-            loader = AppClassLoader.getAppClassLoader(extcl);
-        } catch (IOException e) {
-            throw new InternalError(
-                "Could not create application class loader", e);
-        }
-
-        // Also set the context class loader for the primordial thread.
-        Thread.currentThread().setContextClassLoader(loader);
-
-        // Finally, install a security manager if requested
-        String s = System.getProperty("java.security.manager");
-        if (s != null) {
-            SecurityManager sm = null;
-            if ("".equals(s) || "default".equals(s)) {
-                sm = new java.lang.SecurityManager();
-            } else {
-                try {
-                    sm = (SecurityManager)loader.loadClass(s).newInstance();
-                } catch (IllegalAccessException e) {
-                } catch (InstantiationException e) {
-                } catch (ClassNotFoundException e) {
-                } catch (ClassCastException e) {
-                }
-            }
-            if (sm != null) {
-                System.setSecurityManager(sm);
-            } else {
-                throw new InternalError(
-                    "Could not create SecurityManager: " + s);
-            }
-        }
-    }
-
-    /*
-     * Returns the class loader used to launch the main application.
-     */
-    public ClassLoader getClassLoader() {
-        return loader;
-    }
-
-    /*
-     * The class loader used for loading installed extensions.
-     */
-    static class ExtClassLoader extends URLClassLoader {
-
-        static {
-            ClassLoader.registerAsParallelCapable();
-        }
-
-        /**
-         * create an ExtClassLoader. The ExtClassLoader is created
-         * within a context that limits which files it can read
-         */
-        public static ExtClassLoader getExtClassLoader() throws IOException {
-            try {
-                // Prior implementations of this doPrivileged() block supplied
-                // aa synthesized ACC via a call to the private method
-                // ExtClassLoader.getContext().
-
-                return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<ExtClassLoader>() {
-                        public ExtClassLoader run() throws IOException {
-                            // ext modules linked into image
-                            String home = System.getProperty("java.home");
-                            File dir = new File(new File(home, "lib"), "modules");
-                            File jimage = new File(dir, "extmodules.jimage");
-
-                            File jfxrt = new File(new File(home, "lib"), "jfxrt.jar");
-                            File[] files = jfxrt.exists() ? new File[] {jimage, jfxrt}
-                                                          : new File[] {jimage};
-                            return new ExtClassLoader(files);
-                        }
-                    });
-            } catch (java.security.PrivilegedActionException e) {
-                throw (IOException) e.getException();
-            }
-        }
-
-        void addExtURL(URL url) {
-            super.addURL(url);
-        }
-
-        /*
-         * Creates a new ExtClassLoader for the specified directories.
-         */
-        public ExtClassLoader(File[] files) throws IOException {
-            super(getExtURLs(files), null, factory);
-        }
-
-        private static URL[] getExtURLs(File[] files) throws IOException {
-            int len = files.length;
-            URL[] urls = new URL[len];
-            for (int i=0; i<len; i++) {
-                urls[i] = getFileURL(files[i]);
-            }
-            return urls;
-        }
-
-        private static AccessControlContext getContext(File[] dirs)
-            throws IOException
-        {
-            PathPermissions perms =
-                new PathPermissions(dirs);
-
-            ProtectionDomain domain = new ProtectionDomain(
-                new CodeSource(perms.getCodeBase(),
-                    (java.security.cert.Certificate[]) null),
-                perms);
-
-            AccessControlContext acc =
-                new AccessControlContext(new ProtectionDomain[] { domain });
-
-            return acc;
-        }
-    }
-
-    /**
-     * The class loader used for loading from java.class.path.
-     * runs in a restricted security context.
-     */
-    static class AppClassLoader extends URLClassLoader {
-
-        static {
-            ClassLoader.registerAsParallelCapable();
-        }
-
-        public static ClassLoader getAppClassLoader(final ClassLoader extcl)
-            throws IOException
-        {
-            // modules linked into image are prepended to class path
-            String home = System.getProperty("java.home");
-            File dir = new File(new File(home, "lib"), "modules");
-            String jimage = new File(dir, "appmodules.jimage").getPath();
-
-            String cp = System.getProperty("java.class.path");
-            if (cp == null) {
-                cp = jimage;
-            } else {
-                cp = jimage + File.pathSeparator + cp;
-            }
-            final File[] path = getClassPath(cp, true);
-
-            // Note: on bugid 4256530
-            // Prior implementations of this doPrivileged() block supplied
-            // a rather restrictive ACC via a call to the private method
-            // AppClassLoader.getContext(). This proved overly restrictive
-            // when loading  classes. Specifically it prevent
-            // accessClassInPackage.sun.* grants from being honored.
-            //
-            return AccessController.doPrivileged(
-                new PrivilegedAction<AppClassLoader>() {
-                    public AppClassLoader run() {
-                        URL[] urls = pathToURLs(path);
-                        return new AppClassLoader(urls, extcl);
-                }
-            });
-        }
-
-        /*
-         * Creates a new AppClassLoader
-         */
-        AppClassLoader(URL[] urls, ClassLoader parent) {
-            super(urls, parent, factory);
-        }
-
-        /**
-         * Override loadClass so we can checkPackageAccess.
-         */
-        public Class<?> loadClass(String name, boolean resolve)
-            throws ClassNotFoundException
-        {
-            int i = name.lastIndexOf('.');
-            if (i != -1) {
-                SecurityManager sm = System.getSecurityManager();
-                if (sm != null) {
-                    sm.checkPackageAccess(name.substring(0, i));
-                }
-            }
-            return (super.loadClass(name, resolve));
-        }
-
-        /**
-         * allow any classes loaded from classpath to exit the VM.
-         */
-        protected PermissionCollection getPermissions(CodeSource codesource) {
-            PermissionCollection perms = super.getPermissions(codesource);
-            perms.add(new RuntimePermission("exitVM"));
-            return perms;
-        }
-
-        /**
-         * This class loader supports dynamic additions to the class path
-         * at runtime.
-         *
-         * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
-         */
-        private void appendToClassPathForInstrumentation(String path) {
-            assert(Thread.holdsLock(this));
-
-            // addURL is a no-op if path already contains the URL
-            super.addURL( getFileURL(new File(path)) );
-        }
-
-        /**
-         * create a context that can read any directories (recursively)
-         * mentioned in the class path. In the case of a jar, it has to
-         * be the directory containing the jar, not just the jar, as jar
-         * files might refer to other jar files.
-         */
-
-        private static AccessControlContext getContext(File[] cp)
-            throws java.net.MalformedURLException
-        {
-            PathPermissions perms =
-                new PathPermissions(cp);
-
-            ProtectionDomain domain =
-                new ProtectionDomain(new CodeSource(perms.getCodeBase(),
-                    (java.security.cert.Certificate[]) null),
-                perms);
-
-            AccessControlContext acc =
-                new AccessControlContext(new ProtectionDomain[] { domain });
-
-            return acc;
-        }
-    }
-
-    private static class BootClassPathHolder {
-        static final URLClassPath bcp;
-        static {
-            URL[] urls = AccessController.doPrivileged(
-                    new PrivilegedAction<URL[]>() {
-                        public URL[] run() {
-                            String bootClassPath = System.getProperty("sun.boot.class.path");
-                            if (bootClassPath == null)
-                                return new URL[0];
-                            // Skip empty path in boot class path i.e. not default to use CWD
-                            return pathToURLs(getClassPath(bootClassPath, false));
-                        }
-                    }
-                );
-            bcp = new URLClassPath(urls, factory);
-        }
-    }
-
-    public static URLClassPath getBootstrapClassPath() {
-        return BootClassPathHolder.bcp;
-    }
-
-    private static URL[] pathToURLs(File[] path) {
-        URL[] urls = new URL[path.length];
-        for (int i = 0; i < path.length; i++) {
-            urls[i] = getFileURL(path[i]);
-        }
-        // DEBUG
-        //for (int i = 0; i < urls.length; i++) {
-        //  System.out.println("urls[" + i + "] = " + '"' + urls[i] + '"');
-        //}
-        return urls;
-    }
-
-    private static File[] getClassPath(String cp, boolean defaultToCwd) {
-        File[] path;
-        if (cp != null) {
-            int count = 0, maxCount = 1;
-            int pos = 0, lastPos = 0;
-            // Count the number of separators first
-            while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
-                maxCount++;
-                lastPos = pos + 1;
-            }
-            path = new File[maxCount];
-            lastPos = pos = 0;
-            // Now scan for each path component
-            while ((pos = cp.indexOf(File.pathSeparator, lastPos)) != -1) {
-                if (pos > lastPos) {
-                    path[count++] = new File(cp.substring(lastPos, pos));
-                } else if (defaultToCwd) {
-                    // empty path component translates to "."
-                    path[count++] = new File(".");
-                }
-                lastPos = pos + 1;
-            }
-            // Make sure we include the last path component
-            if (lastPos < cp.length()) {
-                path[count++] = new File(cp.substring(lastPos));
-            } else if (defaultToCwd) {
-                path[count++] = new File(".");
-            }
-            // Trim array to correct size
-            if (count != maxCount) {
-                File[] tmp = new File[count];
-                System.arraycopy(path, 0, tmp, 0, count);
-                path = tmp;
-            }
-        } else {
-            path = new File[0];
-        }
-        // DEBUG
-        //for (int i = 0; i < path.length; i++) {
-        //  System.out.println("path[" + i + "] = " + '"' + path[i] + '"');
-        //}
-        return path;
-    }
-
-    private static URLStreamHandler fileHandler;
-
-    static URL getFileURL(File file) {
-        try {
-            file = file.getCanonicalFile();
-        } catch (IOException e) {}
-
-        try {
-            return ParseUtil.fileToEncodedURL(file);
-        } catch (MalformedURLException e) {
-            // Should never happen since we specify the protocol...
-            throw new InternalError(e);
-        }
-    }
-
-    /*
-     * The stream handler factory for loading system protocol handlers.
-     */
-    private static class Factory implements URLStreamHandlerFactory {
-        private static String PREFIX = "sun.net.www.protocol";
-
-        public URLStreamHandler createURLStreamHandler(String protocol) {
-            String name = PREFIX + "." + protocol + ".Handler";
-            try {
-                Class<?> c = Class.forName(name);
-                return (URLStreamHandler)c.newInstance();
-            } catch (ReflectiveOperationException e) {
-                throw new InternalError("could not load " + protocol +
-                                        "system protocol handler", e);
-            }
-        }
-    }
-}
-
-class PathPermissions extends PermissionCollection {
-    // use serialVersionUID from JDK 1.2.2 for interoperability
-    private static final long serialVersionUID = 8133287259134945693L;
-
-    private File path[];
-    private Permissions perms;
-
-    URL codeBase;
-
-    PathPermissions(File path[])
-    {
-        this.path = path;
-        this.perms = null;
-        this.codeBase = null;
-    }
-
-    URL getCodeBase()
-    {
-        return codeBase;
-    }
-
-    public void add(java.security.Permission permission) {
-        throw new SecurityException("attempt to add a permission");
-    }
-
-    private synchronized void init()
-    {
-        if (perms != null)
-            return;
-
-        perms = new Permissions();
-
-        // this is needed to be able to create the classloader itself!
-        perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
-
-        // add permission to read any "java.*" property
-        perms.add(new java.util.PropertyPermission("java.*",
-            SecurityConstants.PROPERTY_READ_ACTION));
-
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            public Void run() {
-                for (int i=0; i < path.length; i++) {
-                    File f = path[i];
-                    String path;
-                    try {
-                        path = f.getCanonicalPath();
-                    } catch (IOException ioe) {
-                        path = f.getAbsolutePath();
-                    }
-                    if (i == 0) {
-                        codeBase = Launcher.getFileURL(new File(path));
-                    }
-                    if (f.isDirectory()) {
-                        if (path.endsWith(File.separator)) {
-                            perms.add(new FilePermission(path+"-",
-                                SecurityConstants.FILE_READ_ACTION));
-                        } else {
-                            perms.add(new FilePermission(
-                                path + File.separator+"-",
-                                SecurityConstants.FILE_READ_ACTION));
-                        }
-                    } else {
-                        int endIndex = path.lastIndexOf(File.separatorChar);
-                        if (endIndex != -1) {
-                            path = path.substring(0, endIndex+1) + "-";
-                            perms.add(new FilePermission(path,
-                                SecurityConstants.FILE_READ_ACTION));
-                        } else {
-                            // XXX?
-                        }
-                    }
-                }
-                return null;
-            }
-        });
-    }
-
-    public boolean implies(java.security.Permission permission) {
-        if (perms == null)
-            init();
-        return perms.implies(permission);
-    }
-
-    public java.util.Enumeration<Permission> elements() {
-        if (perms == null)
-            init();
-        synchronized (perms) {
-            return perms.elements();
-        }
-    }
-
-    public String toString() {
-        if (perms == null)
-            init();
-        return perms.toString();
-    }
-}
diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
index ac86bdc..8c4c736 100644
--- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
+++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
@@ -25,7 +25,6 @@
 
 package sun.misc;
 
-import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
@@ -56,7 +55,6 @@
 import java.util.Set;
 import java.util.Stack;
 import java.util.StringTokenizer;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.jar.JarFile;
 import java.util.zip.ZipEntry;
 import java.util.jar.JarEntry;
@@ -65,14 +63,10 @@
 import java.util.jar.Attributes.Name;
 import java.util.zip.ZipFile;
 
-import jdk.internal.jimage.ImageLocation;
-import jdk.internal.jimage.ImageReader;
 import jdk.internal.misc.JavaUtilZipFileAccess;
 import jdk.internal.misc.SharedSecrets;
-
 import sun.net.util.URLUtil;
 import sun.net.www.ParseUtil;
-import sun.net.www.protocol.jrt.JavaRuntimeURLConnection;
 
 /**
  * This class is used to maintain a search path of URLs for loading classes
@@ -387,10 +381,6 @@
                             return new Loader(url);
                         }
                     } else {
-                        if (file != null && "file".equals(url.getProtocol())) {
-                            if (file.endsWith(".jimage"))
-                                return new JImageLoader(url);
-                        }
                         return new JarLoader(url, jarHandler, lmap);
                     }
                 }
@@ -446,13 +436,14 @@
      * Return null on security check failure.
      * Called by java.net.URLClassLoader.
      */
-    public URL checkURL(URL url) {
-        try {
-            check(url);
-        } catch (Exception e) {
-            return null;
+    public static URL checkURL(URL url) {
+        if (url != null) {
+            try {
+                check(url);
+            } catch (Exception e) {
+                return null;
+            }
         }
-
         return url;
     }
 
@@ -461,7 +452,7 @@
      * Throw exception on failure.
      * Called internally within this file.
      */
-    static void check(URL url) throws IOException {
+    public static void check(URL url) throws IOException {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             URLConnection urlConnection = url.openConnection();
@@ -1086,132 +1077,4 @@
             return null;
         }
     }
-
-    /**
-     * A Loader of classes and resources from a jimage file located in the
-     * runtime image.
-     */
-    private static class JImageLoader
-        extends Loader implements JavaRuntimeURLConnection.ResourceFinder
-    {
-        private static final AtomicInteger NEXT_INDEX = new AtomicInteger();
-
-        private final ImageReader jimage;
-        private final int index;
-
-        JImageLoader(URL url) throws IOException {
-            super(url);
-
-            // get path to image file and check that it's in the runtime
-            String urlPath = url.getFile().replace('/', File.separatorChar);
-
-            File filePath = new File(ParseUtil.decode(urlPath));
-            File home = new File(JAVA_HOME).getCanonicalFile();
-            File parent = filePath.getParentFile();
-            while (parent != null) {
-                if (parent.equals(home))
-                    break;
-                parent = parent.getParentFile();
-            }
-            if (parent == null)
-                throw new IOException(filePath + " not in runtime image");
-
-            this.jimage = ImageReader.open(filePath.toString());
-            this.index = NEXT_INDEX.getAndIncrement();
-
-            // register with the jimage protocol handler
-            JavaRuntimeURLConnection.register(this);
-        }
-
-        /**
-         * Maps the given resource name to a module.
-         */
-        private String nameToModule(String name) {
-            int pos = name.lastIndexOf('/');
-            if (pos > 0) {
-                String pkg = name.substring(0, pos);
-                String module = jimage.getModule(pkg);
-                if (module != null)
-                    return module;
-            }
-            // cannot map to module
-            return "UNNAMED" + index;
-        }
-
-        /**
-         * Constructs a URL for the resource name.
-         */
-        private URL toURL(String name) {
-            String module = nameToModule(name);
-            String encodedName = ParseUtil.encodePath(name, false);
-            try {
-                return new URL("jrt:/" + module + "/" + encodedName);
-            } catch (MalformedURLException e) {
-                throw new InternalError(e);
-            }
-        }
-
-        @Override
-        URL findResource(String name, boolean check) {
-            ImageLocation location = jimage.findLocation(name);
-            if (location == null)
-                return null;
-            URL url = toURL(name);
-            if (check) {
-                try {
-                    URLClassPath.check(url);
-                } catch (IOException | SecurityException e) {
-                    return null;
-                }
-            }
-            return url;
-        }
-
-        @Override
-        Resource getResource(String name, boolean check) {
-            ImageLocation location = jimage.findLocation(name);
-            if (location == null)
-                return null;
-            URL url = toURL(name);
-            if (check) {
-                try {
-                    URLClassPath.check(url);
-                } catch (IOException | SecurityException e) {
-                    return null;
-                }
-            }
-            return new Resource() {
-                @Override
-                public String getName() { return name; }
-                @Override
-                public URL getURL() { return url; }
-                @Override
-                public URL getCodeSourceURL() {
-                    try {
-                        return new URL("jrt:/" + nameToModule(name));
-                    } catch (MalformedURLException e) {
-                        throw new InternalError(e);
-                    }
-                }
-                @Override
-                public InputStream getInputStream() throws IOException {
-                    byte[] resource = jimage.getResource(location);
-                    return new ByteArrayInputStream(resource);
-                }
-                public int getContentLength() {
-                    long size = location.getUncompressedSize();
-                    return (size > Integer.MAX_VALUE) ? -1 : (int)size;
-                }
-            };
-        }
-
-        @Override
-        public Resource find(String module, String name) throws IOException {
-            String m = nameToModule(name);
-            if (!m.equals(module))
-                return null;
-            // URLConnection will do the permission check
-            return getResource(name, false);
-        }
-    }
 }
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jmod/Handler.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jmod/Handler.java
new file mode 100644
index 0000000..95bc217
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jmod/Handler.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.www.protocol.jmod;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+/**
+ * Placeholder protocol handler for the jmod protocol.
+ */
+
+public class Handler extends URLStreamHandler {
+    public Handler() { }
+
+    @Override
+    protected URLConnection openConnection(URL url) throws IOException {
+        String s = url.toString();
+        int index = s.indexOf("!/");
+        if (index == -1)
+            throw new MalformedURLException("no !/ found in url spec:" + s);
+
+        throw new IOException("Can't connect to jmod URL");
+    }
+}
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
index 33b6840..8f6a8c3 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java
@@ -25,6 +25,7 @@
 
 package sun.net.www.protocol.jrt;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FilePermission;
 import java.io.IOException;
@@ -35,8 +36,12 @@
 import java.security.Permission;
 import java.security.PrivilegedAction;
 import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
 
+import jdk.internal.jimage.ImageLocation;
+import jdk.internal.jimage.ImageReader;
+import jdk.internal.jimage.ImageReaderFactory;
+
+import sun.misc.URLClassPath;
 import sun.misc.Resource;
 import sun.net.www.ParseUtil;
 import sun.net.www.URLConnection;
@@ -47,33 +52,8 @@
  */
 public class JavaRuntimeURLConnection extends URLConnection {
 
-    /**
-     * Finds resource {@code name} in module {@code module}.
-     */
-    public interface ResourceFinder {
-        Resource find(String module, String name) throws IOException;
-    }
-
-    /**
-     * The list of resource finders for jimages in the runtime image.
-     */
-    private static final List<ResourceFinder> finders = new CopyOnWriteArrayList<>();
-
-    /**
-     * Called on behalf of the boot, extension and system class loaders to
-     * register a resource finder.
-     */
-    public static void register(ResourceFinder finder) {
-        finders.add(finder);
-    }
-
-    private static Resource find(String module, String name) throws IOException {
-        for (ResourceFinder finder: finders) {
-            Resource r = finder.find(module, name);
-            if (r != null) return r;
-        }
-        return null;
-    }
+    // ImageReader to access resources in jimage
+    private static final ImageReader reader = ImageReaderFactory.getImageReader();
 
     // the module and resource name in the URL
     private final String module;
@@ -105,6 +85,44 @@
         }
     }
 
+    /**
+     * Finds a resource in a module, returning {@code null} if the resource
+     * is not found.
+     */
+    private static Resource findResource(String module, String name) {
+        if (reader != null) {
+            URL url = toJrtURL(module, name);
+            ImageLocation location = reader.findLocation(module, name);
+            if (location != null && URLClassPath.checkURL(url) != null) {
+                return new Resource() {
+                    @Override
+                    public String getName() {
+                        return name;
+                    }
+                    @Override
+                    public URL getURL() {
+                        return url;
+                    }
+                    @Override
+                    public URL getCodeSourceURL() {
+                        return toJrtURL(module);
+                    }
+                    @Override
+                    public InputStream getInputStream() throws IOException {
+                        byte[] resource = reader.getResource(location);
+                        return new ByteArrayInputStream(resource);
+                    }
+                    @Override
+                    public int getContentLength() {
+                        long size = location.getUncompressedSize();
+                        return (size > Integer.MAX_VALUE) ? -1 : (int) size;
+                    }
+                };
+            }
+        }
+        return null;
+    }
+
     @Override
     public synchronized void connect() throws IOException {
         if (!connected) {
@@ -112,7 +130,7 @@
                 String s = (module == null) ? "" : module;
                 throw new IOException("cannot connect to jrt:/" + s);
             }
-            resource = find(module, name);
+            resource = findResource(module, name);
             if (resource == null)
                 throw new IOException(module + "/" + name + " not found");
             connected = true;
@@ -155,4 +173,26 @@
         }
         return p;
     }
+
+    /**
+     * Returns a jrt URL for the given module and resource name.
+     */
+    private static URL toJrtURL(String module, String name) {
+        try {
+            return new URL("jrt:/" + module + "/" + name);
+        } catch (MalformedURLException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Returns a jrt URL for the given module.
+     */
+    private static URL toJrtURL(String module) {
+        try {
+            return new URL("jrt:/" + module);
+        } catch (MalformedURLException e) {
+            throw new InternalError(e);
+        }
+    }
 }
diff --git a/jdk/src/java.base/share/classes/sun/reflect/Reflection.java b/jdk/src/java.base/share/classes/sun/reflect/Reflection.java
index 07ff364..084995f 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/Reflection.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/Reflection.java
@@ -25,9 +25,13 @@
 
 package sun.reflect;
 
+
 import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.VM;
 
@@ -80,13 +84,6 @@
     @HotSpotIntrinsicCandidate
     public static native int getClassAccessFlags(Class<?> c);
 
-    /** A quick "fast-path" check to try to avoid getCallerClass()
-        calls. */
-    public static boolean quickCheckMemberAccess(Class<?> memberClass,
-                                                 int modifiers)
-    {
-        return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);
-    }
 
     public static void ensureMemberAccess(Class<?> currentClass,
                                           Class<?> memberClass,
@@ -99,12 +96,7 @@
         }
 
         if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {
-            throw new IllegalAccessException("Class " + currentClass.getName() +
-                                             " can not access a member of class " +
-                                             memberClass.getName() +
-                                             " with modifiers \"" +
-                                             Modifier.toString(modifiers) +
-                                             "\"");
+            throwIllegalAccessException(currentClass, memberClass, target, modifiers);
         }
     }
 
@@ -128,6 +120,10 @@
             return true;
         }
 
+        if (!verifyModuleAccess(currentClass, memberClass)) {
+            return false;
+        }
+
         if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
             isSameClassPackage = isSameClassPackage(currentClass, memberClass);
             gotIsSameClassPackage = true;
@@ -186,59 +182,45 @@
         return true;
     }
 
-    private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
-        return isSameClassPackage(c1.getClassLoader(), c1.getName(),
-                                  c2.getClassLoader(), c2.getName());
+    /**
+     * Returns {@code true} if memberClass's's module exports memberClass's
+     * package to currentClass's module.
+     */
+    public static boolean verifyModuleAccess(Class<?> currentClass,
+                                             Class<?> memberClass) {
+        return verifyModuleAccess(currentClass.getModule(), memberClass);
     }
 
-    /** Returns true if two classes are in the same package; classloader
-        and classname information is enough to determine a class's package */
-    private static boolean isSameClassPackage(ClassLoader loader1, String name1,
-                                              ClassLoader loader2, String name2)
-    {
-        if (loader1 != loader2) {
-            return false;
-        } else {
-            int lastDot1 = name1.lastIndexOf('.');
-            int lastDot2 = name2.lastIndexOf('.');
-            if ((lastDot1 == -1) || (lastDot2 == -1)) {
-                // One of the two doesn't have a package.  Only return true
-                // if the other one also doesn't have a package.
-                return (lastDot1 == lastDot2);
-            } else {
-                int idx1 = 0;
-                int idx2 = 0;
+    public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
+        Module memberModule = memberClass.getModule();
 
-                // Skip over '['s
-                if (name1.charAt(idx1) == '[') {
-                    do {
-                        idx1++;
-                    } while (name1.charAt(idx1) == '[');
-                    if (name1.charAt(idx1) != 'L') {
-                        // Something is terribly wrong.  Shouldn't be here.
-                        throw new InternalError("Illegal class name " + name1);
-                    }
-                }
-                if (name2.charAt(idx2) == '[') {
-                    do {
-                        idx2++;
-                    } while (name2.charAt(idx2) == '[');
-                    if (name2.charAt(idx2) != 'L') {
-                        // Something is terribly wrong.  Shouldn't be here.
-                        throw new InternalError("Illegal class name " + name2);
-                    }
-                }
+        // module may be null during startup (initLevel 0)
+        if (currentModule == memberModule)
+           return true;  // same module (named or unnamed)
 
-                // Check that package part is identical
-                int length1 = lastDot1 - idx1;
-                int length2 = lastDot2 - idx2;
-
-                if (length1 != length2) {
-                    return false;
-                }
-                return name1.regionMatches(false, idx1, name2, idx2, length1);
-            }
+        // memberClass may be primitive or array class
+        Class<?> c = memberClass;
+        while (c.isArray()) {
+            c = c.getComponentType();
         }
+        if (c.isPrimitive())
+            return true;
+
+        // check that memberModule exports the package to currentModule
+        return memberModule.isExported(c.getPackageName(), currentModule);
+    }
+
+    /**
+     * Returns true if two classes in the same package.
+     */
+    private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
+        if (c1.getClassLoader() != c2.getClassLoader())
+            return false;
+        while (c1.isArray())
+            c1 = c1.getComponentType();
+        while (c2.isArray())
+            c2 = c2.getComponentType();
+        return Objects.equals(c1.getPackageName(), c2.getPackageName());
     }
 
     static boolean isSubclassOf(Class<?> queryClass,
@@ -332,7 +314,7 @@
 
     /**
      * Tests if the given method is caller-sensitive and the declaring class
-     * is defined by either the bootstrap class loader or extension class loader.
+     * is defined by either the bootstrap class loader or platform class loader.
      */
     public static boolean isCallerSensitive(Method m) {
         final ClassLoader loader = m.getDeclaringClass().getClassLoader();
@@ -352,4 +334,92 @@
         }
         return false;
     }
+
+
+    // true to print a stack trace when IAE is thrown
+    private static volatile boolean printStackWhenAccessFails;
+
+    // true if printStackWhenAccessFails has been initialized
+    private static volatile boolean printStackWhenAccessFailsSet;
+
+    private static void printStackTraceIfNeeded(Throwable e) {
+        if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
+            // can't use method reference here, might be too early in startup
+            PrivilegedAction<Boolean> pa = new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    String s;
+                    s = System.getProperty("sun.reflect.debugModuleAccessChecks");
+                    return (s != null && !s.equalsIgnoreCase("false"));
+                }
+            };
+            printStackWhenAccessFails = AccessController.doPrivileged(pa);
+            printStackWhenAccessFailsSet = true;
+        }
+        if (printStackWhenAccessFails) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Throws IllegalAccessException with the an exception message based on
+     * the access that is denied.
+     */
+    private static void throwIllegalAccessException(Class<?> currentClass,
+                                                    Class<?> memberClass,
+                                                    Object target,
+                                                    int modifiers)
+        throws IllegalAccessException
+    {
+        String currentSuffix = "";
+        String memberSuffix = "";
+        Module m1 = currentClass.getModule();
+        if (m1.isNamed())
+            currentSuffix = " (in " + m1 + ")";
+        Module m2 = memberClass.getModule();
+        if (m2.isNamed())
+            memberSuffix = " (in " + m2 + ")";
+
+        Class<?> c = memberClass;
+        while (c.isArray()) {
+            c = c.getComponentType();
+        }
+        String memberPackageName = c.getPackageName();
+
+        String msg = currentClass + currentSuffix + " cannot access ";
+        if (m2.isExported(memberPackageName, m1)) {
+
+            // module access okay so include the modifiers in the message
+            msg += "a member of " + memberClass + memberSuffix +
+                    " with modifiers \"" + Modifier.toString(modifiers) + "\"";
+
+        } else {
+            // module access failed
+            msg += memberClass + memberSuffix+ " because "
+                   + m2 + " does not export " + memberPackageName;
+            if (m2.isNamed()) msg += " to " + m1;
+        }
+
+        throwIllegalAccessException(msg);
+    }
+
+    /**
+     * Throws IllegalAccessException with the given exception message.
+     */
+    public static void throwIllegalAccessException(String msg)
+        throws IllegalAccessException
+    {
+        IllegalAccessException e = new IllegalAccessException(msg);
+        printStackTraceIfNeeded(e);
+        throw e;
+    }
+
+    /**
+     * Throws InaccessibleObjectException with the given exception message.
+     */
+    public static void throwInaccessibleObjectException(String msg) {
+        InaccessibleObjectException e = new InaccessibleObjectException(msg);
+        printStackTraceIfNeeded(e);
+        throw e;
+    }
+
 }
diff --git a/jdk/src/java.base/share/classes/sun/reflect/misc/MethodUtil.java b/jdk/src/java.base/share/classes/sun/reflect/misc/MethodUtil.java
index f1100d8..d3d34da 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/MethodUtil.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/MethodUtil.java
@@ -25,6 +25,7 @@
 
 package sun.reflect.misc;
 
+import java.lang.reflect.Module;
 import java.io.EOFException;
 import java.security.AllPermission;
 import java.security.AccessController;
@@ -39,7 +40,6 @@
 import java.net.URLConnection;
 import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -329,24 +329,26 @@
             throw new ClassNotFoundException(name);
         }
         String path = name.replace('.', '/').concat(".class");
-        URL res = getResource(path);
-        if (res != null) {
-            try {
-                return defineClass(name, res);
-            } catch (IOException e) {
-                throw new ClassNotFoundException(name, e);
+        try {
+            InputStream in = Object.class.getModule().getResourceAsStream(path);
+            if (in != null) {
+                try (in) {
+                    byte[] b = in.readAllBytes();
+                    return defineClass(name, b);
+                }
             }
-        } else {
-            throw new ClassNotFoundException(name);
+        } catch (IOException e) {
+            throw new ClassNotFoundException(name, e);
         }
+
+        throw new ClassNotFoundException(name);
     }
 
 
     /*
      * Define the proxy classes
      */
-    private Class<?> defineClass(String name, URL url) throws IOException {
-        byte[] b = getBytes(url);
+    private Class<?> defineClass(String name, byte[] b) throws IOException {
         CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null);
         if (!name.equals(TRAMPOLINE)) {
             throw new IOException("MethodUtil: bad name " + name);
@@ -354,29 +356,6 @@
         return defineClass(name, b, 0, b.length, cs);
     }
 
-
-    /*
-     * Returns the contents of the specified URL as an array of bytes.
-     */
-    private static byte[] getBytes(URL url) throws IOException {
-        URLConnection uc = url.openConnection();
-        if (uc instanceof java.net.HttpURLConnection) {
-            java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc;
-            int code = huc.getResponseCode();
-            if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
-                throw new IOException("open HTTP connection failed.");
-            }
-        }
-        int len = uc.getContentLength();
-        try (InputStream in = new BufferedInputStream(uc.getInputStream())) {
-            byte[] b = in.readAllBytes();
-            if (len != -1 && b.length != len)
-                throw new EOFException("Expected:" + len + ", read:" + b.length);
-            return b;
-        }
-    }
-
-
     protected PermissionCollection getPermissions(CodeSource codesource)
     {
         PermissionCollection perms = super.getPermissions(codesource);
diff --git a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
index c90a630..97bd9c2 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
@@ -30,7 +30,6 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
-import java.util.Arrays;
 import sun.reflect.Reflection;
 import sun.security.util.SecurityConstants;
 
@@ -45,12 +44,6 @@
         return Class.forName(name);
     }
 
-    public static Object newInstance(Class<?> cls)
-        throws InstantiationException, IllegalAccessException {
-        checkPackageAccess(cls);
-        return cls.newInstance();
-    }
-
     /*
      * Reflection.ensureMemberAccess is overly-restrictive
      * due to a bug. We awkwardly work around it for now.
@@ -286,7 +279,7 @@
         String name = cls.getName();
         int i = name.lastIndexOf('.');
         String pkg = (i != -1) ? name.substring(0, i) : "";
-        return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE);
+        return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE);
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java
index 1db2d08..9082670 100644
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java
@@ -36,8 +36,10 @@
 /**
  * List of Providers. Used to represent the provider preferences.
  *
- * The system starts out with a ProviderList that only has the classNames
- * of the Providers. Providers are loaded on demand only when needed.
+ * The system starts out with a ProviderList that only has the names
+ * of the Providers.
+ * When using ServiceLoader to load the providers, Providers are created
+ * semi-eagerly as we iterate through them looking for a match.
  *
  * For compatibility reasons, Providers that could not be loaded are ignored
  * and internally presented as the instance EMPTY_PROVIDER. However, those
diff --git a/jdk/src/java.base/share/classes/sun/security/jca/Providers.java b/jdk/src/java.base/share/classes/sun/security/jca/Providers.java
index 94e7738..ec66be4 100644
--- a/jdk/src/java.base/share/classes/sun/security/jca/Providers.java
+++ b/jdk/src/java.base/share/classes/sun/security/jca/Providers.java
@@ -86,10 +86,7 @@
         "SunRsaSign",
         // Note: when SunEC is in a signed JAR file, it's not signed
         // by EC algorithms. So it's still safe to be listed here.
-        // Need to use class name here, otherwise it cannot be loaded for
-        // jar verification. Only those providers in java.base are created
-        // directly by ProviderConfig class.
-        "sun.security.ec.SunEC",
+        "SunEC",
     };
 
     // Return Sun provider.
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
index a9af102..5861b6c 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java
@@ -275,7 +275,6 @@
 
     // contains the policy grant entries, PD cache, and alias mapping
     private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
-    private boolean constructed = false;
 
     private boolean expandProperties = true;
     private boolean allowSystemProperties = true;
@@ -910,9 +909,8 @@
                NoSuchMethodException,
                InvocationTargetException
     {
-        //XXX we might want to keep a hash of created factories...
         Class<?> pc = Class.forName(type, false, null);
-        Permission answer = getKnownInstance(pc, name, actions);
+        Permission answer = getKnownPermission(pc, name, actions);
         if (answer != null) {
             return answer;
         }
@@ -955,12 +953,12 @@
     }
 
     /**
-     * Creates one of the well-known permissions directly instead of
-     * via reflection. Keep list short to not penalize non-JDK-defined
-     * permissions.
+     * Creates one of the well-known permissions in the java.base module
+     * directly instead of via reflection. Keep list short to not penalize
+     * permissions from other modules.
      */
-    private static final Permission getKnownInstance(Class<?> claz,
-        String name, String actions) {
+    private static Permission getKnownPermission(Class<?> claz, String name,
+                                                 String actions) {
         if (claz.equals(FilePermission.class)) {
             return new FilePermission(name, actions);
         } else if (claz.equals(SocketPermission.class)) {
@@ -973,6 +971,21 @@
             return new NetPermission(name, actions);
         } else if (claz.equals(AllPermission.class)) {
             return SecurityConstants.ALL_PERMISSION;
+        } else if (claz.equals(SecurityPermission.class)) {
+            return new SecurityPermission(name, actions);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Creates one of the well-known principals in the java.base module
+     * directly instead of via reflection. Keep list short to not penalize
+     * principals from other modules.
+     */
+    private static Principal getKnownPrincipal(Class<?> claz, String name) {
+        if (claz.equals(X500Principal.class)) {
+            return new X500Principal(name);
         } else {
             return null;
         }
@@ -1305,15 +1318,19 @@
             try {
                 ClassLoader cl = Thread.currentThread().getContextClassLoader();
                 Class<?> pClass = Class.forName(pppe.principalClass, false, cl);
-                if (!Principal.class.isAssignableFrom(pClass)) {
-                    // not the right subtype
-                    throw new ClassCastException(pppe.principalClass +
-                                                 " is not a Principal");
-                }
+                Principal p = getKnownPrincipal(pClass, pppe.principalName);
+                if (p == null) {
+                    if (!Principal.class.isAssignableFrom(pClass)) {
+                        // not the right subtype
+                        throw new ClassCastException(pppe.principalClass +
+                                                     " is not a Principal");
+                    }
 
-                Constructor<?> c = pClass.getConstructor(PARAMS1);
-                Principal p = (Principal)c.newInstance(new Object[] {
-                                                       pppe.principalName });
+                    Constructor<?> c = pClass.getConstructor(PARAMS1);
+                    p = (Principal)c.newInstance(new Object[] {
+                                                 pppe.principalName });
+
+                }
 
                 if (debug != null) {
                     debug.println("found Principal " + p.getClass().getName());
diff --git a/jdk/src/java.base/share/classes/sun/security/util/SecurityConstants.java b/jdk/src/java.base/share/classes/sun/security/util/SecurityConstants.java
index 8a06fa8..4a928b1 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/SecurityConstants.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/SecurityConstants.java
@@ -98,7 +98,7 @@
     public static final NetPermission GET_RESPONSECACHE_PERMISSION =
        new NetPermission("getResponseCache");
 
-    // java.lang.SecurityManager, sun.applet.AppletPanel, sun.misc.Launcher
+    // java.lang.SecurityManager, sun.applet.AppletPanel
     public static final RuntimePermission CREATE_CLASSLOADER_PERMISSION =
         new RuntimePermission("createClassLoader");
 
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorInfoProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorInfoProvider.java
new file mode 100644
index 0000000..9a6f05e
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorInfoProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface BreakIteratorInfoProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java
new file mode 100644
index 0000000..4bbb1ce
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorRulesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface BreakIteratorRulesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/CollationDataProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/CollationDataProvider.java
new file mode 100644
index 0000000..e73b958
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/CollationDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface CollationDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/FormatDataProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/FormatDataProvider.java
new file mode 100644
index 0000000..4f78996
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/FormatDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface FormatDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java
new file mode 100644
index 0000000..261e980
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface JavaTimeSupplementaryProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/text/resources/cldr/FormatDataProvider.java b/jdk/src/java.base/share/classes/sun/text/resources/cldr/FormatDataProvider.java
new file mode 100644
index 0000000..573b9e8
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/resources/cldr/FormatDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources.cldr;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface FormatDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template b/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template
deleted file mode 100644
index 0f34122..0000000
--- a/jdk/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package sun.util;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.ResourceBundle.Control;
-
-/**
- * This is a convenient class for loading some of internal resources faster
- * if they are built with Resources.gmk defined in J2SE workspace. Also,
- * they have to be in class file format.
- *
- * "LOCALE_LIST" will be replaced at built time by a list of locales we
- * defined in Defs.gmk. We want to exclude these locales from search to
- * gain better performance. For example, since we know if the resource
- * is built with Resources.gmk, they are not going to provide basename_en.class
- * & basename_en_US.class resources, in that case, continuing searching them
- * is expensive. By excluding them from the candidate locale list, these
- * resources won't be searched.
- *
- * @since 1.6.
- */
-public class CoreResourceBundleControl extends ResourceBundle.Control {
-    /* the candidate locale list to search */
-    private final Collection<Locale> excludedJDKLocales;
-    /* singlton instance of the resource bundle control. */
-    private static CoreResourceBundleControl resourceBundleControlInstance =
-        new CoreResourceBundleControl();
-
-    protected CoreResourceBundleControl() {
-        excludedJDKLocales = Arrays.asList(#LOCALE_LIST#);
-    }
-
-    /**
-     * This method is to provide a customized ResourceBundle.Control to speed
-     * up the search of resources in JDK.
-     *
-     * @return the instance of resource bundle control.
-     */
-    public static CoreResourceBundleControl getRBControlInstance() {
-        return resourceBundleControlInstance;
-    }
-
-    /**
-     * This method is to provide a customized ResourceBundle.Control to speed
-     * up the search of resources in JDK, with the bundle's package name check.
-     *
-     * @param bundleName bundle name to check
-     * @return the instance of resource bundle control if the bundle is JDK's,
-     *    otherwise returns null.
-     */
-    public static CoreResourceBundleControl getRBControlInstance(String bundleName) {
-        if (bundleName.startsWith("com.sun.") ||
-            bundleName.startsWith("java.") ||
-            bundleName.startsWith("javax.") ||
-            bundleName.startsWith("sun.")) {
-            return resourceBundleControlInstance;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * @return a list of candidate locales to search from.
-     * @exception NullPointerException if baseName or locale is null.
-     */
-    @Override
-    public List<Locale> getCandidateLocales(String baseName, Locale locale) {
-        List<Locale> candidates = super.getCandidateLocales(baseName, locale);
-        candidates.removeAll(excludedJDKLocales);
-        return candidates;
-    }
-
-    /**
-     * @ returns TTL_DONT_CACHE so that ResourceBundle instance won't be cached.
-     * User of this CoreResourceBundleControl should probably maintain a hard reference
-     * to the ResourceBundle object themselves.
-     */
-    @Override
-    public long getTimeToLive(String baseName, Locale locale) {
-        return ResourceBundle.Control.TTL_DONT_CACHE;
-    }
-}
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java
index b612a0d..ddb4bb5 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -40,7 +40,9 @@
 package sun.util.locale.provider;
 
 import java.io.BufferedInputStream;
+import java.io.InputStream;
 import java.io.IOException;
+import java.lang.reflect.Module;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
@@ -135,25 +137,29 @@
     // deserialization
     //=========================================================================
 
-    BreakDictionary(String dictionaryName)
+    BreakDictionary(Module module, String dictionaryName)
         throws IOException, MissingResourceException {
 
-        readDictionaryFile(dictionaryName);
+        readDictionaryFile(module, dictionaryName);
     }
 
-    private void readDictionaryFile(final String dictionaryName)
+    private void readDictionaryFile(final Module module, final String dictionaryName)
         throws IOException, MissingResourceException {
 
         BufferedInputStream in;
         try {
-            in = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<BufferedInputStream>() {
-                    @Override
-                    public BufferedInputStream run() throws Exception {
-                        return new BufferedInputStream(getClass().getResourceAsStream("/sun/text/resources/" + dictionaryName));
-                    }
+            PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
+                InputStream is = module.getResourceAsStream("sun/text/resources/" + dictionaryName);
+                if (is == null) {
+                    // Try to load the file with "java.base" module instance. Assumption
+                    // here is that the fall back data files to be read should reside in
+                    // java.base.
+                    is = BreakDictionary.class.getModule().getResourceAsStream("sun/text/resources/" + dictionaryName);
                 }
-            );
+
+                return new BufferedInputStream(is);
+            };
+            in = AccessController.doPrivileged(pa);
         }
         catch (PrivilegedActionException e) {
             throw new InternalError(e.toString(), e);
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java
index 2d37412..2de50a9 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -30,6 +30,7 @@
 import java.text.spi.BreakIteratorProvider;
 import java.util.Locale;
 import java.util.MissingResourceException;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -155,9 +156,7 @@
                                                   int type,
                                                   String dataName,
                                                   String dictionaryName) {
-        if (locale == null) {
-            throw new NullPointerException();
-        }
+        Objects.requireNonNull(locale);
 
         LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
         String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
@@ -166,10 +165,12 @@
         try {
             switch (classNames[type]) {
             case "RuleBasedBreakIterator":
-                return new RuleBasedBreakIterator(dataFile);
+                return new RuleBasedBreakIterator(
+                    lr.getBreakIteratorDataModule(), dataFile);
             case "DictionaryBasedBreakIterator":
                 String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
-                return new DictionaryBasedBreakIterator(dataFile, dictionaryFile);
+                return new DictionaryBasedBreakIterator(
+                    lr.getBreakIteratorDataModule(), dataFile, dictionaryFile);
             default:
                 throw new IllegalArgumentException("Invalid break iterator class \"" +
                                 classNames[type] + "\"");
@@ -187,5 +188,5 @@
     @Override
     public boolean isSupportedLocale(Locale locale) {
         return LocaleProviderAdapter.forType(type).isSupportedProviderLocale(locale, langtags);
-}
+    }
 }
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java
index 7d0b8c4..f7eff4e 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -41,6 +41,7 @@
 package sun.util.locale.provider;
 
 import java.io.IOException;
+import java.lang.reflect.Module;
 import java.text.CharacterIterator;
 import java.util.ArrayList;
 import java.util.List;
@@ -108,20 +109,18 @@
 
     /**
      * Constructs a DictionaryBasedBreakIterator.
-     * @param description Same as the description parameter on RuleBasedBreakIterator,
-     * except for the special meaning of "<dictionary>".  This parameter is just
-     * passed through to RuleBasedBreakIterator's constructor.
+     * @param module The module where the dictionary file resides
      * @param dictionaryFilename The filename of the dictionary file to use
      */
-    DictionaryBasedBreakIterator(String dataFile, String dictionaryFile)
+    DictionaryBasedBreakIterator(Module module, String dataFile, String dictionaryFile)
                                         throws IOException {
-        super(dataFile);
+        super(module, dataFile);
         byte[] tmp = super.getAdditionalData();
         if (tmp != null) {
             prepareCategoryFlags(tmp);
             super.setAdditionalData(null);
         }
-        dictionary = new BreakDictionary(dictionaryFile);
+        dictionary = new BreakDictionary(module, dictionaryFile);
     }
 
     private void prepareCategoryFlags(byte[] data) {
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 c9cdba7..c16c012 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
@@ -431,25 +431,21 @@
 
         // Use ServiceLoader to dynamically acquire installed locales' tags.
         try {
-            String nonBaseTags = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
-                @Override
-                public String run() {
-                    String tags = null;
-                    for (LocaleDataMetaInfo ldmi :
-                         ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
-                        if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
-                            String t = ldmi.availableLanguageTags(category);
-                            if (t != null) {
-                                if (tags == null) {
-                                    tags = t;
-                                } else {
-                                    tags += " " + t;
-                                }
+            String nonBaseTags = AccessController.doPrivileged((PrivilegedExceptionAction<String>) () -> {
+                StringBuilder tags = new StringBuilder();
+                for (LocaleDataMetaInfo ldmi :
+                        ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
+                    if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
+                        String t = ldmi.availableLanguageTags(category);
+                        if (t != null) {
+                            if (tags.length() > 0) {
+                                tags.append(' ');
                             }
+                            tags.append(t);
                         }
                     }
-                    return tags;
                 }
+                return tags.toString();
             });
 
             if (nonBaseTags != null) {
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java
index 25ce39f..2269d60 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java
@@ -42,6 +42,7 @@
 
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
+import java.lang.reflect.Module;
 import java.text.MessageFormat;
 import java.util.Calendar;
 import java.util.LinkedHashSet;
@@ -117,6 +118,10 @@
        return biInfo;
     }
 
+    Module getBreakIteratorDataModule() {
+       return localeData.getBreakIteratorInfo(locale).getClass().getModule();
+    }
+
     int getCalendarData(String key) {
         Integer caldata;
         String cacheKey = CALENDAR_DATA  + key;
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
new file mode 100644
index 0000000..114a7fa
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/ResourceBundleProviderSupport.java
@@ -0,0 +1,149 @@
+/*
+ * 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/locale/provider/RuleBasedBreakIterator.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java
index a1962e46..7c00ee0 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -41,7 +41,9 @@
 package sun.util.locale.provider;
 
 import java.io.BufferedInputStream;
+import java.io.InputStream;
 import java.io.IOException;
+import java.lang.reflect.Module;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
@@ -313,12 +315,12 @@
     //=======================================================================
 
     /**
-     * Constructs a RuleBasedBreakIterator according to the datafile
+     * Constructs a RuleBasedBreakIterator according to the module and the datafile
      * provided.
      */
-    RuleBasedBreakIterator(String datafile)
+    RuleBasedBreakIterator(Module module, String datafile)
         throws IOException, MissingResourceException {
-        readTables(datafile);
+        readTables(module, datafile);
     }
 
     /**
@@ -369,10 +371,10 @@
      *   }
      * </pre>
      */
-    protected final void readTables(String datafile)
+    protected final void readTables(Module module, String datafile)
         throws IOException, MissingResourceException {
 
-        byte[] buffer = readFile(datafile);
+        byte[] buffer = readFile(module, datafile);
 
         /* Read header_info. */
         int stateTableLength = getInt(buffer, 0);
@@ -436,21 +438,24 @@
         numCategories = stateTable.length / endStates.length;
     }
 
-    protected byte[] readFile(final String datafile)
+    protected byte[] readFile(final Module module, final String datafile)
         throws IOException, MissingResourceException {
 
         BufferedInputStream is;
         try {
-            is = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<BufferedInputStream>() {
-                    @Override
-                    public BufferedInputStream run() throws Exception {
-                        return new BufferedInputStream(getClass().getResourceAsStream("/sun/text/resources/" + datafile));
-                    }
+            PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
+                InputStream in = module.getResourceAsStream("sun/text/resources/" + datafile);
+                if (in == null) {
+                    // Try to load the file with "java.base" module instance. Assumption
+                    // here is that the fall back data files to be read should reside in
+                    // java.base.
+                    in = RuleBasedBreakIterator.class.getModule().getResourceAsStream("sun/text/resources/" + datafile);
                 }
-            );
-        }
-        catch (PrivilegedActionException e) {
+
+                return new BufferedInputStream(in);
+            };
+            is = AccessController.doPrivileged(pa);
+        } catch (PrivilegedActionException e) {
             throw new InternalError(e.toString(), e);
         }
 
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
new file mode 100644
index 0000000..5966bb5
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/Bundles.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ */
+
+package sun.util.resources;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.Objects;
+import java.util.ResourceBundle;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.spi.ResourceBundleProvider;
+import jdk.internal.misc.JavaUtilResourceBundleAccess;
+import jdk.internal.misc.SharedSecrets;
+import sun.util.locale.provider.ResourceBundleProviderSupport;
+
+
+/**
+ */
+public abstract class Bundles {
+
+    /** initial size of the bundle cache */
+    private static final int INITIAL_CACHE_SIZE = 32;
+
+    /** constant indicating that no resource bundle exists */
+    private static final ResourceBundle NONEXISTENT_BUNDLE = new ResourceBundle() {
+            @Override
+            public Enumeration<String> getKeys() { return null; }
+            @Override
+            protected Object handleGetObject(String key) { return null; }
+            @Override
+            public String toString() { return "NONEXISTENT_BUNDLE"; }
+        };
+
+    private static final JavaUtilResourceBundleAccess bundleAccess
+                            = SharedSecrets.getJavaUtilResourceBundleAccess();
+
+    /**
+     * The cache is a map from cache keys (with bundle base name, locale, and
+     * class loader) to either a resource bundle or NONEXISTENT_BUNDLE wrapped by a
+     * BundleReference.
+     *
+     * The cache is a ConcurrentMap, allowing the cache to be searched
+     * concurrently by multiple threads.  This will also allow the cache keys
+     * to be reclaimed along with the ClassLoaders they reference.
+     *
+     * This variable would be better named "cache", but we keep the old
+     * name for compatibility with some workarounds for bug 4212439.
+     */
+    private static final ConcurrentMap<CacheKey, BundleReference> cacheList
+                            = new ConcurrentHashMap<>(INITIAL_CACHE_SIZE);
+
+    /**
+     * Queue for reference objects referring to class loaders or bundles.
+     */
+    private static final ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
+
+    private Bundles() {
+    }
+
+    public static ResourceBundle of(String baseName, Locale locale, Strategy strategy) {
+        return loadBundleOf(baseName, locale, strategy);
+    }
+
+    private static ResourceBundle loadBundleOf(String baseName,
+                                               Locale targetLocale,
+                                               Strategy strategy) {
+        Objects.requireNonNull(baseName);
+        Objects.requireNonNull(targetLocale);
+        Objects.requireNonNull(strategy);
+
+        CacheKey cacheKey = new CacheKey(baseName, targetLocale);
+
+        ResourceBundle bundle = null;
+
+        // Quick lookup of the cache.
+        BundleReference bundleRef = cacheList.get(cacheKey);
+        if (bundleRef != null) {
+            bundle = bundleRef.get();
+        }
+
+        // If this bundle and all of its parents are valid,
+        // then return this bundle.
+        if (isValidBundle(bundle)) {
+            return bundle;
+        }
+
+        // Get the providers for loading the "leaf" bundle (i.e., bundle for
+        // targetLocale). If no providers are required for the bundle,
+        // none of its parents will require providers.
+        Class<? extends ResourceBundleProvider> type
+                = strategy.getResourceBundleProviderType(baseName, targetLocale);
+        if (type != null) {
+            @SuppressWarnings("unchecked")
+            ServiceLoader<ResourceBundleProvider> providers
+                = (ServiceLoader<ResourceBundleProvider>) ServiceLoader.loadInstalled(type);
+            cacheKey.setProviders(providers);
+        }
+
+        List<Locale> candidateLocales = strategy.getCandidateLocales(baseName, targetLocale);
+        bundle = findBundleOf(cacheKey, strategy, baseName, candidateLocales, 0);
+        if (bundle == null) {
+            throwMissingResourceException(baseName, targetLocale, cacheKey.getCause());
+        }
+        return bundle;
+    }
+
+    private static ResourceBundle findBundleOf(CacheKey cacheKey,
+                                               Strategy strategy,
+                                               String baseName,
+                                               List<Locale> candidateLocales,
+                                               int index) {
+        ResourceBundle parent = null;
+        Locale targetLocale = candidateLocales.get(index);
+        if (index != candidateLocales.size() - 1) {
+            parent = findBundleOf(cacheKey, strategy, baseName, candidateLocales, index + 1);
+        }
+
+        // Before we do the real loading work, see whether we need to
+        // do some housekeeping: If resource bundles have been nulled out,
+        // remove all related information from the cache.
+        cleanupCache();
+
+        // find an individual ResourceBundle in the cache
+        cacheKey.setLocale(targetLocale);
+        ResourceBundle bundle = findBundleInCache(cacheKey);
+        if (bundle != null) {
+            if (bundle == NONEXISTENT_BUNDLE) {
+                return parent;
+            }
+            if (bundleAccess.getParent(bundle) == parent) {
+                return bundle;
+            }
+            // Remove bundle from the cache.
+            BundleReference bundleRef = cacheList.get(cacheKey);
+            if (bundleRef != null && bundleRef.get() == bundle) {
+                cacheList.remove(cacheKey, bundleRef);
+            }
+        }
+
+        // Determine if providers should be used for loading the bundle.
+        // An assumption here is that if the leaf bundle of a look-up path is
+        // in java.base, all bundles of the path are in java.base.
+        // (e.g., en_US of path en_US -> en -> root is in java.base and the rest
+        // are in java.base as well)
+        // This assumption isn't valid for general bundle loading.
+        ServiceLoader<ResourceBundleProvider> providers = cacheKey.getProviders();
+        if (providers != null) {
+            if (strategy.getResourceBundleProviderType(baseName, targetLocale) == null) {
+                providers = null;
+            }
+        }
+
+        CacheKey constKey = (CacheKey) cacheKey.clone();
+        try {
+            if (providers != null) {
+                bundle = loadBundleFromProviders(baseName, targetLocale, providers, cacheKey);
+            } else {
+                try {
+                    bundle = ResourceBundleProviderSupport
+                                 .loadResourceBundle(Bundles.class.getModule(),
+                                      strategy.toBundleName(baseName, targetLocale));
+                } catch (Exception e) {
+                    cacheKey.setCause(e);
+                }
+            }
+        } finally {
+            if (constKey.getCause() instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
+        }
+
+        if (bundle == null) {
+            // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
+            // instance for the locale.
+            putBundleInCache(cacheKey, NONEXISTENT_BUNDLE);
+            return parent;
+        }
+
+        if (parent != null && bundleAccess.getParent(bundle) == null) {
+            bundleAccess.setParent(bundle, parent);
+        }
+        bundleAccess.setLocale(bundle, targetLocale);
+        bundleAccess.setName(bundle, baseName);
+        bundle = putBundleInCache(cacheKey, bundle);
+        return bundle;
+    }
+
+    private static void cleanupCache() {
+        Object ref;
+        while ((ref = referenceQueue.poll()) != null) {
+            cacheList.remove(((CacheKeyReference)ref).getCacheKey());
+        }
+    }
+
+    /**
+     * Loads ResourceBundle from service providers.
+     */
+    private static ResourceBundle loadBundleFromProviders(String baseName,
+                                                          Locale locale,
+                                                          ServiceLoader<ResourceBundleProvider> providers,
+                                                          CacheKey cacheKey)
+    {
+        return AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    public ResourceBundle run() {
+                        for (Iterator<ResourceBundleProvider> itr = providers.iterator(); itr.hasNext(); ) {
+                            try {
+                                ResourceBundleProvider provider = itr.next();
+                                ResourceBundle bundle = provider.getBundle(baseName, locale);
+                                if (bundle != null) {
+                                    return bundle;
+                                }
+                            } catch (ServiceConfigurationError | SecurityException e) {
+                                if (cacheKey != null) {
+                                    cacheKey.setCause(e);
+                                }
+                            }
+                        }
+                        return null;
+                    }
+                });
+
+    }
+
+    private static boolean isValidBundle(ResourceBundle bundle) {
+        return bundle != null && bundle != NONEXISTENT_BUNDLE;
+    }
+
+    /**
+     * Throw a MissingResourceException with proper message
+     */
+    private static void throwMissingResourceException(String baseName,
+                                                      Locale locale,
+                                                      Throwable cause) {
+        // If the cause is a MissingResourceException, avoid creating
+        // a long chain. (6355009)
+        if (cause instanceof MissingResourceException) {
+            cause = null;
+        }
+        MissingResourceException e;
+        e = new MissingResourceException("Can't find bundle for base name "
+                                         + baseName + ", locale " + locale,
+                                         baseName + "_" + locale, // className
+                                         "");
+        e.initCause(cause);
+        throw e;
+    }
+
+    /**
+     * Finds a bundle in the cache.
+     *
+     * @param cacheKey the key to look up the cache
+     * @return the ResourceBundle found in the cache or null
+     */
+    private static ResourceBundle findBundleInCache(CacheKey cacheKey) {
+        BundleReference bundleRef = cacheList.get(cacheKey);
+        if (bundleRef == null) {
+            return null;
+        }
+        return bundleRef.get();
+    }
+
+    /**
+     * Put a new bundle in the cache.
+     *
+     * @param cacheKey the key for the resource bundle
+     * @param bundle the resource bundle to be put in the cache
+     * @return the ResourceBundle for the cacheKey; if someone has put
+     * the bundle before this call, the one found in the cache is
+     * returned.
+     */
+    private static ResourceBundle putBundleInCache(CacheKey cacheKey,
+                                                   ResourceBundle bundle) {
+        CacheKey key = (CacheKey) cacheKey.clone();
+        BundleReference bundleRef = new BundleReference(bundle, referenceQueue, key);
+
+        // Put the bundle in the cache if it's not been in the cache.
+        BundleReference result = cacheList.putIfAbsent(key, bundleRef);
+
+        // If someone else has put the same bundle in the cache before
+        // us, we should use the one in the cache.
+        if (result != null) {
+            ResourceBundle rb = result.get();
+            if (rb != null) {
+                // Clear the back link to the cache key
+                bundle = rb;
+                // Clear the reference in the BundleReference so that
+                // it won't be enqueued.
+                bundleRef.clear();
+            } else {
+                // Replace the invalid (garbage collected)
+                // instance with the valid one.
+                cacheList.put(key, bundleRef);
+            }
+        }
+        return bundle;
+    }
+
+
+    /**
+     * The Strategy interface defines methods that are called by Bundles.of during
+     * the resource bundle loading process.
+     */
+    public static interface Strategy {
+        /**
+         * Returns a list of locales to be looked up for bundle loading.
+         */
+        public List<Locale> getCandidateLocales(String baseName, Locale locale);
+
+        /**
+         * Returns the bundle name for the given baseName and locale.
+         */
+        public String toBundleName(String baseName, Locale locale);
+
+        /**
+         * Returns the service provider type for the given baseName
+         * and locale, or null if no service providers should be used.
+         */
+        public Class<? extends ResourceBundleProvider> getResourceBundleProviderType(String baseName,
+                                                                                     Locale locale);
+    }
+
+    /**
+     * The common interface to get a CacheKey in LoaderReference and
+     * BundleReference.
+     */
+    private static interface CacheKeyReference {
+        public CacheKey getCacheKey();
+    }
+
+    /**
+     * References to bundles are soft references so that they can be garbage
+     * collected when they have no hard references.
+     */
+    private static class BundleReference extends SoftReference<ResourceBundle>
+                                         implements CacheKeyReference {
+        private final CacheKey cacheKey;
+
+        BundleReference(ResourceBundle referent, ReferenceQueue<Object> q, CacheKey key) {
+            super(referent, q);
+            cacheKey = key;
+        }
+
+        @Override
+        public CacheKey getCacheKey() {
+            return cacheKey;
+        }
+    }
+
+    /**
+     * Key used for cached resource bundles.  The key checks the base
+     * name, the locale, and the class loader to determine if the
+     * resource is a match to the requested one. The loader may be
+     * null, but the base name and the locale must have a non-null
+     * value.
+     */
+    private static class CacheKey implements Cloneable {
+        // These two are the actual keys for lookup in Map.
+        private String name;
+        private Locale locale;
+
+        // Placeholder for an error report by a Throwable
+        private Throwable cause;
+
+        // Hash code value cache to avoid recalculating the hash code
+        // of this instance.
+        private int hashCodeCache;
+
+        // The service loader to load bundles or null if no service loader
+        // is required.
+        private ServiceLoader<ResourceBundleProvider> providers;
+
+        CacheKey(String baseName, Locale locale) {
+            this.name = baseName;
+            this.locale = locale;
+            calculateHashCode();
+        }
+
+        String getName() {
+            return name;
+        }
+
+        CacheKey setName(String baseName) {
+            if (!this.name.equals(baseName)) {
+                this.name = baseName;
+                calculateHashCode();
+            }
+            return this;
+        }
+
+        Locale getLocale() {
+            return locale;
+        }
+
+        CacheKey setLocale(Locale locale) {
+            if (!this.locale.equals(locale)) {
+                this.locale = locale;
+                calculateHashCode();
+            }
+            return this;
+        }
+
+        ServiceLoader<ResourceBundleProvider> getProviders() {
+            return providers;
+        }
+
+        void setProviders(ServiceLoader<ResourceBundleProvider> providers) {
+            this.providers = providers;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            try {
+                final CacheKey otherEntry = (CacheKey)other;
+                //quick check to see if they are not equal
+                if (hashCodeCache != otherEntry.hashCodeCache) {
+                    return false;
+                }
+                return locale.equals(otherEntry.locale)
+                        && name.equals(otherEntry.name);
+            } catch (NullPointerException | ClassCastException e) {
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCodeCache;
+        }
+
+        private void calculateHashCode() {
+            hashCodeCache = name.hashCode() << 3;
+            hashCodeCache ^= locale.hashCode();
+        }
+
+        @Override
+        public Object clone() {
+            try {
+                CacheKey clone = (CacheKey) super.clone();
+                // Clear the reference to a Throwable
+                clone.cause = null;
+                // Clear the reference to a ServiceLoader
+                clone.providers = null;
+                return clone;
+            } catch (CloneNotSupportedException e) {
+                //this should never happen
+                throw new InternalError(e);
+            }
+        }
+
+        private void setCause(Throwable cause) {
+            if (this.cause == null) {
+                this.cause = cause;
+            } else {
+                // Override the cause if the previous one is
+                // ClassNotFoundException.
+                if (this.cause instanceof ClassNotFoundException) {
+                    this.cause = cause;
+                }
+            }
+        }
+
+        private Throwable getCause() {
+            return cause;
+        }
+
+        @Override
+        public String toString() {
+            String l = locale.toString();
+            if (l.isEmpty()) {
+                if (!locale.getVariant().isEmpty()) {
+                    l = "__" + locale.getVariant();
+                } else {
+                    l = "\"\"";
+                }
+            }
+            return "CacheKey[" + name + ", lc=" + l + ")]";
+        }
+    }
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/CalendarDataProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/CalendarDataProvider.java
new file mode 100644
index 0000000..f74aba1
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/CalendarDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface CalendarDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNamesProvider.java
new file mode 100644
index 0000000..be81006
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/CurrencyNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface CurrencyNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java
index 51fa739..ddc2439 100644
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -46,14 +46,17 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.spi.ResourceBundleProvider;
 import sun.util.locale.provider.JRELocaleProviderAdapter;
 import sun.util.locale.provider.LocaleProviderAdapter;
-import sun.util.locale.provider.ResourceBundleBasedAdapter;
 import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR;
 import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE;
+import sun.util.locale.provider.ResourceBundleBasedAdapter;
 
 /**
  * Provides information about and access to resource bundles in the
@@ -65,6 +68,14 @@
  */
 
 public class LocaleData {
+    private static final ResourceBundle.Control defaultControl
+        = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
+
+    private static final String DOTCLDR      = ".cldr";
+
+    // Map of key (base name + locale) to candidates
+    private static final Map<String, List<Locale>> CANDIDATES_MAP = new ConcurrentHashMap<>();
+
     private final LocaleProviderAdapter.Type type;
 
     public LocaleData(LocaleProviderAdapter.Type type) {
@@ -163,8 +174,7 @@
         return AccessController.doPrivileged(new PrivilegedAction<>() {
             @Override
             public ResourceBundle run() {
-                return ResourceBundle
-                        .getBundle(baseName, locale, LocaleDataResourceBundleControl.INSTANCE);
+                return Bundles.of(baseName, locale, LocaleDataStrategy.INSTANCE);
             }
         });
     }
@@ -175,9 +185,8 @@
            public OpenListResourceBundle run() {
                OpenListResourceBundle rb = null;
                try {
-                   rb = (OpenListResourceBundle) ResourceBundle.getBundle(baseName,
-                           locale, SupplementaryResourceBundleControl.INSTANCE);
-
+                   rb = (OpenListResourceBundle) Bundles.of(baseName, locale,
+                                                            SupplementaryStrategy.INSTANCE);
                } catch (MissingResourceException e) {
                    // return null if no supplementary is available
                }
@@ -186,12 +195,51 @@
         });
     }
 
-    private static class LocaleDataResourceBundleControl extends ResourceBundle.Control {
-        /* Singlton instance of ResourceBundle.Control. */
-        private static final LocaleDataResourceBundleControl INSTANCE =
-            new LocaleDataResourceBundleControl();
+    private static abstract class LocaleDataResourceBundleProvider
+                                            implements ResourceBundleProvider {
+        abstract protected boolean isSupportedInModule(String baseName, Locale locale);
 
-        private LocaleDataResourceBundleControl() {
+        /**
+         * Changes baseName to its module dependent package name and
+         * calls the super class implementation. For example,
+         * if the baseName is "sun.text.resources.FormatData" and locale is ja_JP,
+         * the baseName is changed to "sun.text.resources.ext.FormatData". If
+         * baseName contains ".cldr", such as "sun.text.resources.cldr.FormatData",
+         * the name is changed to "sun.text.resources.cldr.ext.FormatData".
+         */
+        protected String toBundleName(String baseName, Locale locale) {
+            return LocaleDataStrategy.INSTANCE.toBundleName(baseName, locale);
+        }
+    }
+
+    /**
+     * A ResourceBundleProvider implementation for loading locale data
+     * resource bundles except for the java.time supplementary data.
+     */
+    public static abstract class CommonResourceBundleProvider extends LocaleDataResourceBundleProvider {
+        @Override
+        protected boolean isSupportedInModule(String baseName, Locale locale) {
+            return LocaleDataStrategy.INSTANCE.inJavaBaseModule(baseName, locale);
+        }
+    }
+
+    /**
+     * A ResourceBundleProvider implementation for loading supplementary
+     * resource bundles for java.time.
+     */
+    public static abstract class SupplementaryResourceBundleProvider extends LocaleDataResourceBundleProvider {
+        @Override
+        protected boolean isSupportedInModule(String baseName, Locale locale) {
+            return SupplementaryStrategy.INSTANCE.inJavaBaseModule(baseName, locale);
+        }
+    }
+
+    // Bundles.Strategy implementations
+
+    private static class LocaleDataStrategy implements Bundles.Strategy {
+        private static final LocaleDataStrategy INSTANCE = new LocaleDataStrategy();
+
+        private LocaleDataStrategy() {
         }
 
         /*
@@ -205,66 +253,49 @@
          * @exception NullPointerException if baseName or locale is null.
          */
         @Override
-         public List<Locale> getCandidateLocales(String baseName, Locale locale) {
-            LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE;
-            LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
-            List<Locale> candidates = adapter instanceof ResourceBundleBasedAdapter ?
-                ((ResourceBundleBasedAdapter)adapter).getCandidateLocales(baseName, locale) :
-                super.getCandidateLocales(baseName, locale);
+        public List<Locale> getCandidateLocales(String baseName, Locale locale) {
+            String key = baseName + '-' + locale.toLanguageTag();
+            List<Locale> candidates = CANDIDATES_MAP.get(key);
+            if (candidates == null) {
+                LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE;
+                LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
+                candidates = adapter instanceof ResourceBundleBasedAdapter ?
+                    ((ResourceBundleBasedAdapter)adapter).getCandidateLocales(baseName, locale) :
+                    defaultControl.getCandidateLocales(baseName, locale);
 
-            // Weed out Locales which are known to have no resource bundles
-            int lastDot = baseName.lastIndexOf('.');
-            String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName;
-            Set<String> langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category);
-            if (!langtags.isEmpty()) {
-                for (Iterator<Locale> itr = candidates.iterator(); itr.hasNext();) {
-                    if (!adapter.isSupportedProviderLocale(itr.next(), langtags)) {
-                        itr.remove();
+                // Weed out Locales which are known to have no resource bundles
+                int lastDot = baseName.lastIndexOf('.');
+                String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName;
+                Set<String> langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category);
+                if (!langtags.isEmpty()) {
+                    for (Iterator<Locale> itr = candidates.iterator(); itr.hasNext();) {
+                        if (!adapter.isSupportedProviderLocale(itr.next(), langtags)) {
+                            itr.remove();
+                        }
                     }
                 }
-            }
-
-            // Force fallback to Locale.ENGLISH for CLDR time zone names support
-            if (locale.getLanguage() != "en"
-                    && type == CLDR && category.equals("TimeZoneNames")) {
-                candidates.add(candidates.size() - 1, Locale.ENGLISH);
+                // Force fallback to Locale.ENGLISH for CLDR time zone names support
+                if (locale.getLanguage() != "en"
+                        && type == CLDR && category.equals("TimeZoneNames")) {
+                    candidates.add(candidates.size() - 1, Locale.ENGLISH);
+                }
+                CANDIDATES_MAP.putIfAbsent(key, candidates);
             }
             return candidates;
         }
 
-        /*
-         * Overrides "getFallbackLocale" to return null so
-         * that the fallback locale will be null.
-         * @param baseName the resource bundle base name.
-         *        locale   the requested locale for the resource bundle.
-         * @return null for the fallback locale.
-         * @exception NullPointerException if baseName or locale is null.
-         */
-        @Override
-        public Locale getFallbackLocale(String baseName, Locale locale) {
-            if (baseName == null || locale == null) {
-                throw new NullPointerException();
-            }
-            return null;
+        boolean inJavaBaseModule(String baseName, Locale locale) {
+            // TODO: avoid hard-coded Locales
+            return locale.equals(Locale.ROOT) ||
+                (locale.getLanguage() == "en" &&
+                    (locale.getCountry().isEmpty() ||
+                     locale.getCountry() == "US"));
         }
 
-        private static final String DOTCLDR      = ".cldr";
-
-        /**
-         * Changes baseName to its module dependent package name and
-         * calls the super class implementation. For example,
-         * if the baseName is "sun.text.resources.FormatData" and locale is ja_JP,
-         * the baseName is changed to "sun.text.resources.ext.FormatData". If
-         * baseName contains "cldr", such as "sun.text.resources.cldr.FormatData",
-         * the name is changed to "sun.text.resources.cldr.ext.FormatData".
-         */
         @Override
         public String toBundleName(String baseName, Locale locale) {
             String newBaseName = baseName;
-            String lang = locale.getLanguage();
-            String ctry = locale.getCountry();
-            if (lang.length() > 0 &&
-                (lang != "en" || (ctry.length() > 0 && ctry != "US"))) {
+            if (!inJavaBaseModule(baseName, locale)) {
                 if (baseName.startsWith(JRE.getUtilResourcesPackage())
                         || baseName.startsWith(JRE.getTextResourcesPackage())) {
                     // Assume the lengths are the same.
@@ -274,19 +305,26 @@
                     if (baseName.indexOf(DOTCLDR, index) > 0) {
                         index += DOTCLDR.length();
                     }
-                    newBaseName = baseName.substring(0, index + 1) + "ext" +
-                                      baseName.substring(index);
+                    newBaseName = baseName.substring(0, index + 1) + "ext"
+                                      + baseName.substring(index);
                 }
             }
-            return super.toBundleName(newBaseName, locale);
+            return defaultControl.toBundleName(newBaseName, locale);
+        }
+
+        @Override
+        public Class<? extends ResourceBundleProvider> getResourceBundleProviderType(String baseName,
+                                                                                     Locale locale) {
+            return inJavaBaseModule(baseName, locale) ?
+                        null : CommonResourceBundleProvider.class;
         }
     }
 
-    private static class SupplementaryResourceBundleControl extends LocaleDataResourceBundleControl {
-        private static final SupplementaryResourceBundleControl INSTANCE =
-                new SupplementaryResourceBundleControl();
+    private static class SupplementaryStrategy extends LocaleDataStrategy {
+        private static final SupplementaryStrategy INSTANCE
+                = new SupplementaryStrategy();
 
-        private SupplementaryResourceBundleControl() {
+        private SupplementaryStrategy() {
         }
 
         @Override
@@ -296,9 +334,16 @@
         }
 
         @Override
-        public long getTimeToLive(String baseName, Locale locale) {
-            assert baseName.contains("JavaTimeSupplementary");
-            return TTL_DONT_CACHE;
+        public Class<? extends ResourceBundleProvider> getResourceBundleProviderType(String baseName,
+                                                                                     Locale locale) {
+            return inJavaBaseModule(baseName, locale) ?
+                    null : SupplementaryResourceBundleProvider.class;
+        }
+
+        @Override
+        boolean inJavaBaseModule(String baseName, Locale locale) {
+            // TODO: avoid hard-coded Locales
+            return locale.equals(Locale.ROOT) || locale.getLanguage() == "en";
         }
     }
 }
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/LocaleDataProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/LocaleDataProvider.java
new file mode 100644
index 0000000..8369917
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface LocaleDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/LocaleNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/LocaleNamesProvider.java
new file mode 100644
index 0000000..b231ab0
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface LocaleNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesProvider.java
new file mode 100644
index 0000000..839b38e
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface TimeZoneNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/cldr/CalendarDataProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/cldr/CalendarDataProvider.java
new file mode 100644
index 0000000..d614174
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/cldr/CalendarDataProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.cldr;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface CalendarDataProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/cldr/CurrencyNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/cldr/CurrencyNamesProvider.java
new file mode 100644
index 0000000..b2c8f08
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/cldr/CurrencyNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.cldr;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface CurrencyNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/cldr/LocaleNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/cldr/LocaleNamesProvider.java
new file mode 100644
index 0000000..05f6366
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/cldr/LocaleNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.cldr;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface LocaleNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/cldr/TimeZoneNamesProvider.java b/jdk/src/java.base/share/classes/sun/util/resources/cldr/TimeZoneNamesProvider.java
new file mode 100644
index 0000000..d0f95bf
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/resources/cldr/TimeZoneNamesProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.cldr;
+
+import java.util.spi.ResourceBundleProvider;
+
+/**
+ * An interface for the internal locale data provider for which {@code ResourceBundle}
+ * searches.
+ */
+public interface TimeZoneNamesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/src/java.base/share/conf/security/java.policy b/jdk/src/java.base/share/conf/security/java.policy
index 8ea3687..a6b3b1b 100644
--- a/jdk/src/java.base/share/conf/security/java.policy
+++ b/jdk/src/java.base/share/conf/security/java.policy
@@ -1,40 +1,13 @@
 // permissions required by each component
+
+grant codeBase "jrt:/java.activation" {
+        permission java.security.AllPermission;
+};
+
 grant codeBase "jrt:/java.corba" {
         permission java.security.AllPermission;
 };
 
-grant codeBase "jrt:/jdk.zipfs" {
-        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
-        permission java.lang.RuntimePermission "fileSystemProvider";
-        permission java.util.PropertyPermission "*", "read";
-};
-
-grant codeBase "jrt:/jdk.localedata" {
-        permission java.lang.RuntimePermission "accessClassInPackage.sun.text.*";
-        permission java.lang.RuntimePermission "accessClassInPackage.sun.util.*";
-        permission java.util.PropertyPermission "*", "read";
-};
-
-grant codeBase "jrt:/jdk.naming.dns" {
-        permission java.security.AllPermission;
-};
-
-grant codeBase "jrt:/jdk.dynalink" {
-        permission java.security.AllPermission;
-};
-
-grant codeBase "jrt:/jdk.scripting.nashorn" {
-        permission java.security.AllPermission;
-};
-
-grant codeBase "jrt:/jdk.scripting.nashorn.shell" {
-        permission java.security.AllPermission;
-};
-
-grant codeBase "jrt:/jdk.internal.le" {
-        permission java.security.AllPermission;
-};
-
 grant codeBase "jrt:/jdk.crypto.ucrypto" {
         permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*";
         permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
@@ -72,16 +45,36 @@
         permission java.io.FilePermission "<<ALL FILES>>", "read";
 };
 
-grant codeBase "jrt:/java.xml.ws" {
-        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
-        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
-        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*";
-        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.org.apache.xerces.internal.*";
-        permission java.lang.RuntimePermission "accessDeclaredMembers";
-        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+grant codeBase "jrt:/jdk.dynalink" {
+        permission java.security.AllPermission;
+};
+
+grant codeBase "jrt:/jdk.internal.le" {
+        permission java.security.AllPermission;
+};
+
+grant codeBase "jrt:/jdk.jsobject" {
+        permission java.security.AllPermission;
+};
+
+grant codeBase "jrt:/jdk.localedata" {
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.text.*";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.util.*";
         permission java.util.PropertyPermission "*", "read";
 };
 
+grant codeBase "jrt:/jdk.naming.dns" {
+        permission java.security.AllPermission;
+};
+
+grant codeBase "jrt:/jdk.scripting.nashorn" {
+        permission java.security.AllPermission;
+};
+
+grant codeBase "jrt:/jdk.scripting.nashorn.shell" {
+        permission java.security.AllPermission;
+};
+
 grant codeBase "jrt:/java.xml.bind" {
         permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
         permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
@@ -91,8 +84,20 @@
         permission java.util.PropertyPermission "*", "read";
 };
 
-grant codeBase "jrt:/java.activation" {
-        permission java.security.AllPermission;
+grant codeBase "jrt:/java.xml.ws" {
+        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
+        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
+        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*";
+        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.org.apache.xerces.internal.*";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.util.PropertyPermission "*", "read";
+};
+
+grant codeBase "jrt:/jdk.zipfs" {
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
+        permission java.lang.RuntimePermission "fileSystemProvider";
+        permission java.util.PropertyPermission "*", "read";
 };
 
 // default permissions granted to all domains
diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security
index fdcfe2b..2e8356b 100644
--- a/jdk/src/java.base/share/conf/security/java.security
+++ b/jdk/src/java.base/share/conf/security/java.security
@@ -66,28 +66,28 @@
 # List of providers and their preference orders (see above):
 #
 #ifdef solaris
-security.provider.tbd=com.oracle.security.ucrypto.UcryptoProvider
-security.provider.tbd=sun.security.pkcs11.SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
+security.provider.tbd=OracleUcrypto
+security.provider.tbd=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
 #endif
-security.provider.tbd=sun.security.provider.Sun
-security.provider.tbd=sun.security.rsa.SunRsaSign
-security.provider.tbd=sun.security.ec.SunEC
-security.provider.tbd=com.sun.net.ssl.internal.ssl.Provider
-security.provider.tbd=com.sun.crypto.provider.SunJCE
-security.provider.tbd=sun.security.jgss.SunProvider
-security.provider.tbd=com.sun.security.sasl.Provider
-security.provider.tbd=org.jcp.xml.dsig.internal.dom.XMLDSigRI
-security.provider.tbd=sun.security.smartcardio.SunPCSC
-security.provider.tbd=sun.security.provider.certpath.ldap.JdkLDAP
-security.provider.tbd=com.sun.security.sasl.gsskerb.JdkSASL
+security.provider.tbd=SUN
+security.provider.tbd=SunRsaSign
+security.provider.tbd=SunEC
+security.provider.tbd=SunJSSE
+security.provider.tbd=SunJCE
+security.provider.tbd=SunJGSS
+security.provider.tbd=SunSASL
+security.provider.tbd=XMLDSig
+security.provider.tbd=SunPCSC
+security.provider.tbd=JdkLDAP
+security.provider.tbd=JdkSASL
 #ifdef windows
-security.provider.tbd=sun.security.mscapi.SunMSCAPI
+security.provider.tbd=SunMSCAPI
 #endif
 #ifdef macosx
-security.provider.tbd=apple.security.AppleProvider
+security.provider.tbd=Apple
 #endif
 #ifndef solaris
-security.provider.tbd=sun.security.pkcs11.SunPKCS11
+security.provider.tbd=SunPKCS11
 #endif
 
 #
@@ -271,6 +271,7 @@
                jdk.internal.,\
                jdk.nashorn.internal.,\
                jdk.nashorn.tools.,\
+               jdk.rmi.rmic.,\
                jdk.tools.jimage.,\
                com.sun.activation.registries.,\
                com.sun.java.accessibility.util.internal.,\
@@ -327,6 +328,7 @@
                    jdk.internal.,\
                    jdk.nashorn.internal.,\
                    jdk.nashorn.tools.,\
+                   jdk.rmi.rmic.,\
                    jdk.tools.jimage.,\
                    com.sun.activation.registries.,\
                    com.sun.java.accessibility.util.internal.,\
diff --git a/jdk/src/java.base/share/native/include/jni.h b/jdk/src/java.base/share/native/include/jni.h
index c09658a..dc86df3 100644
--- a/jdk/src/java.base/share/native/include/jni.h
+++ b/jdk/src/java.base/share/native/include/jni.h
@@ -765,6 +765,17 @@
 
     jobjectRefType (JNICALL *GetObjectRefType)
         (JNIEnv* env, jobject obj);
+
+    /* Module Features */
+
+    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);
 };
 
 /*
@@ -1857,6 +1868,20 @@
         return functions->GetObjectRefType(this, obj);
     }
 
+    /* Module Features */
+
+    jobject GetModule(jclass clazz) {
+        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 99f7c7f..84a00c74 100644
--- a/jdk/src/java.base/share/native/include/jvm.h
+++ b/jdk/src/java.base/share/native/include/jvm.h
@@ -393,6 +393,41 @@
                           const char *source);
 
 /*
+ * Module support funcions
+ */
+
+JNIEXPORT void JNICALL
+JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
+                 jobjectArray packages);
+
+JNIEXPORT void JNICALL
+JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
+
+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);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+
+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);
+
+JNIEXPORT jobject JNICALL
+JVM_GetModuleByPackageName(JNIEnv *env, jobject cl, jstring pkg);
+
+/*
  * Reflection support functions
  */
 
diff --git a/jdk/src/java.base/share/native/include/jvmti.h b/jdk/src/java.base/share/native/include/jvmti.h
index ee708cb..684fd2d 100644
--- a/jdk/src/java.base/share/native/include/jvmti.h
+++ b/jdk/src/java.base/share/native/include/jvmti.h
@@ -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
@@ -23,8 +23,7 @@
  * questions.
  */
 
-    /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
-
+ /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
 
     /* Include file for the Java(tm) Virtual Machine Tool Interface */
 
@@ -42,8 +41,9 @@
     JVMTI_VERSION_1_0 = 0x30010000,
     JVMTI_VERSION_1_1 = 0x30010100,
     JVMTI_VERSION_1_2 = 0x30010200,
+    JVMTI_VERSION_9   = 0x30090000,
 
-    JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1  /* version: 1.2.1 */
+    JVMTI_VERSION = 0x30000000 + (9 * 0x10000) + (0 * 0x100) + 0  /* version: 9.0.0 */
 };
 
 JNIEXPORT jint JNICALL
@@ -703,7 +703,8 @@
     unsigned int can_retransform_any_class : 1;
     unsigned int can_generate_resource_exhaustion_heap_events : 1;
     unsigned int can_generate_resource_exhaustion_threads_events : 1;
-    unsigned int : 7;
+    unsigned int can_generate_early_vmstart : 1;
+    unsigned int : 6;
     unsigned int : 16;
     unsigned int : 16;
     unsigned int : 16;
@@ -1011,8 +1012,10 @@
     jthread event_thread,
      ...);
 
-  /*   3 :  RESERVED */
-  void *reserved3;
+  /*   3 : Get All Modules */
+  jvmtiError (JNICALL *GetAllModules) (jvmtiEnv* env,
+    jint* module_count_ptr,
+    jobject** modules_ptr);
 
   /*   4 : Get All Threads */
   jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
@@ -1675,7 +1678,7 @@
   /*   132 : Set System Property */
   jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
     const char* property,
-    const char* value);
+    const char* value_ptr);
 
   /*   133 : Get Phase */
   jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
@@ -2137,6 +2140,11 @@
     return functions->ClearFieldModificationWatch(this, klass, field);
   }
 
+  jvmtiError GetAllModules(jint* module_count_ptr,
+            jobject** modules_ptr) {
+    return functions->GetAllModules(this, module_count_ptr, modules_ptr);
+  }
+
   jvmtiError GetLoadedClasses(jint* class_count_ptr,
             jclass** classes_ptr) {
     return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
@@ -2484,8 +2492,8 @@
   }
 
   jvmtiError SetSystemProperty(const char* property,
-            const char* value) {
-    return functions->SetSystemProperty(this, property, value);
+            const char* value_ptr) {
+    return functions->SetSystemProperty(this, property, value_ptr);
   }
 
   jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
@@ -2531,4 +2539,3 @@
 #endif /* __cplusplus */
 
 #endif /* !_JAVA_JVMTI_H_ */
-
diff --git a/jdk/src/java.base/share/native/launcher/defines.h b/jdk/src/java.base/share/native/launcher/defines.h
index 4411ee0..e3b1888 100644
--- a/jdk/src/java.base/share/native/launcher/defines.h
+++ b/jdk/src/java.base/share/native/launcher/defines.h
@@ -53,9 +53,10 @@
  * value of -cp option to the launcher.
  */
 #ifndef APP_CLASSPATH
-#define APP_CLASSPATH        { "/lib/tools.jar", "/classes" }
-#endif /* APP_CLASSPATH */
+static const char* const_appclasspath[] = { NULL };
+#else
 static const char* const_appclasspath[] = APP_CLASSPATH;
+#endif /* APP_CLASSPATH */
 #else  /* !JAVA_ARGS */
 #define HAS_JAVA_ARGS JNI_FALSE
 #ifdef PROGNAME
@@ -64,7 +65,7 @@
 static char* const_progname = NULL;
 #endif
 static const char** const_jargs = NULL;
-static const char** const_appclasspath = NULL;
+static const char* const_appclasspath[] = { NULL };
 #endif /* JAVA_ARGS */
 
 #ifdef LAUNCHER_NAME
diff --git a/jdk/src/java.base/share/native/launcher/main.c b/jdk/src/java.base/share/native/launcher/main.c
index cfbabde..9c24c2e 100644
--- a/jdk/src/java.base/share/native/launcher/main.c
+++ b/jdk/src/java.base/share/native/launcher/main.c
@@ -83,7 +83,7 @@
 int WINAPI
 WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
 {
-    int margc;
+    int margc, appclassc;
     char** margv;
     const jboolean const_javaw = JNI_TRUE;
 
@@ -93,7 +93,7 @@
 int
 main(int argc, char **argv)
 {
-    int margc;
+    int margc, appclassc;
     char** margv;
     const jboolean const_javaw = JNI_FALSE;
 #endif /* JAVAW */
@@ -148,9 +148,14 @@
         margv = args->elements;
     }
 #endif /* WIN32 */
+    if (const_appclasspath[0] == NULL) {
+        appclassc = 0;
+    } else {
+        appclassc = sizeof(const_appclasspath) / sizeof(char *);
+    }
     return JLI_Launch(margc, margv,
                    sizeof(const_jargs) / sizeof(char *), const_jargs,
-                   sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
+                   appclassc, const_appclasspath,
                    VERSION_STRING,
                    DOT_VERSION,
                    (const_progname != NULL) ? const_progname : *margv,
diff --git a/jdk/src/java.base/share/native/libjava/BootLoader.c b/jdk/src/java.base/share/native/libjava/BootLoader.c
new file mode 100644
index 0000000..532e338
--- /dev/null
+++ b/jdk/src/java.base/share/native/libjava/BootLoader.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include "jvm.h"
+#include "jni_util.h"
+#include "jdk_internal_loader_BootLoader.h"
+
+JNIEXPORT jstring JNICALL
+Java_jdk_internal_loader_BootLoader_getSystemPackageLocation(JNIEnv *env, jclass cls, jstring str)
+{
+    return JVM_GetSystemPackage(env, str);
+}
+
+JNIEXPORT jobject JNICALL
+Java_jdk_internal_loader_BootLoader_getSystemPackageNames(JNIEnv *env, jclass cls)
+{
+    return JVM_GetSystemPackages(env);
+}
+
+JNIEXPORT void JNICALL
+Java_jdk_internal_loader_BootLoader_setBootLoaderUnnamedModule0(JNIEnv *env, jclass cls, jobject module)
+{
+    JVM_SetBootLoaderUnnamedModule(env, module);
+}
+
diff --git a/jdk/src/java.base/share/native/libjava/Module.c b/jdk/src/java.base/share/native/libjava/Module.c
new file mode 100644
index 0000000..c31491e
--- /dev/null
+++ b/jdk/src/java.base/share/native/libjava/Module.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_lang_reflect_Module.h"
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_defineModule0(JNIEnv *env, jclass cls, jobject module,
+                                            jstring version, jstring location,
+                                            jobjectArray packages)
+{
+    JVM_DefineModule(env, module, version, location, packages);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_addReads0(JNIEnv *env, jclass cls, jobject from, jobject to)
+{
+    JVM_AddReadsModule(env, from, to);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_addExports0(JNIEnv *env, jclass cls, jobject from,
+                                          jstring pkg, jobject to)
+{
+    JVM_AddModuleExports(env, from, pkg, to);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_addExportsToAll0(JNIEnv *env, jclass cls, jobject from,
+                                               jstring pkg)
+{
+    JVM_AddModuleExportsToAll(env, from, pkg);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_addExportsToAllUnnamed0(JNIEnv *env, jclass cls,
+                                                      jobject from, jstring pkg)
+{
+    JVM_AddModuleExportsToAllUnnamed(env, from, pkg);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_reflect_Module_addPackage0(JNIEnv *env, jclass cls, jobject m, jstring pkg)
+{
+    JVM_AddModulePackage(env, m, pkg);
+}
diff --git a/jdk/src/java.base/share/native/libjava/Package.c b/jdk/src/java.base/share/native/libjava/Package.c
deleted file mode 100644
index 72ebcc9..0000000
--- a/jdk/src/java.base/share/native/libjava/Package.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdlib.h>
-#include "jvm.h"
-#include "jni_util.h"
-#include "java_lang_Package.h"
-
-JNIEXPORT jstring JNICALL
-Java_java_lang_Package_getSystemPackage0(JNIEnv *env, jclass cls, jstring str)
-{
-    return JVM_GetSystemPackage(env, str);
-}
-
-JNIEXPORT jobject JNICALL
-Java_java_lang_Package_getSystemPackages0(JNIEnv *env, jclass cls)
-{
-    return JVM_GetSystemPackages(env);
-}
diff --git a/jdk/src/java.base/share/native/libjava/Proxy.c b/jdk/src/java.base/share/native/libjava/Proxy.c
deleted file mode 100644
index bdfbd90..0000000
--- a/jdk/src/java.base/share/native/libjava/Proxy.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdlib.h>
-
-#include "jni.h"
-#include "jni_util.h"
-
-#include "java_lang_reflect_Proxy.h"
-
-/* defined in libverify.so/verify.dll (src file common/check_format.c) */
-extern jboolean VerifyFixClassname(char *utf_name);
-
-/*
- * Class:     java_lang_reflect_Proxy
- * Method:    defineClass0
- * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BII)Ljava/lang/Class;
- *
- * The implementation of this native static method is a copy of that of
- * the native instance method Java_java_lang_ClassLoader_defineClass0()
- * with the implicit "this" parameter becoming the "loader" parameter.
- */
-JNIEXPORT jclass JNICALL
-Java_java_lang_reflect_Proxy_defineClass0(JNIEnv *env,
-                                          jclass ignore,
-                                          jobject loader,
-                                          jstring name,
-                                          jbyteArray data,
-                                          jint offset,
-                                          jint length)
-{
-    jbyte *body;
-    char *utfName;
-    jclass result = 0;
-    char buf[128];
-
-    if (data == NULL) {
-        JNU_ThrowNullPointerException(env, 0);
-        return 0;
-    }
-
-    /* Work around 4153825. malloc crashes on Solaris when passed a
-     * negative size.
-     */
-    if (length < 0) {
-        JNU_ThrowArrayIndexOutOfBoundsException(env, 0);
-        return 0;
-    }
-
-    body = (jbyte *)malloc(length);
-
-    if (body == 0) {
-        JNU_ThrowOutOfMemoryError(env, 0);
-        return 0;
-    }
-
-    (*env)->GetByteArrayRegion(env, data, offset, length, body);
-
-    if ((*env)->ExceptionOccurred(env))
-        goto free_body;
-
-    if (name != NULL) {
-        jsize len = (*env)->GetStringUTFLength(env, name);
-        jsize unicode_len = (*env)->GetStringLength(env, name);
-        if (len >= (jsize)sizeof(buf)) {
-            utfName = malloc(len + 1);
-            if (utfName == NULL) {
-                JNU_ThrowOutOfMemoryError(env, NULL);
-                goto free_body;
-            }
-        } else {
-            utfName = buf;
-        }
-        (*env)->GetStringUTFRegion(env, name, 0, unicode_len, utfName);
-        VerifyFixClassname(utfName);
-    } else {
-        utfName = NULL;
-    }
-
-    result = (*env)->DefineClass(env, utfName, loader, body, length);
-
-    if (utfName && utfName != buf)
-        free(utfName);
-
- free_body:
-    free(body);
-    return result;
-}
diff --git a/jdk/src/java.base/share/native/libjava/Reflection.c b/jdk/src/java.base/share/native/libjava/Reflection.c
index 35cc512..02b9013 100644
--- a/jdk/src/java.base/share/native/libjava/Reflection.c
+++ b/jdk/src/java.base/share/native/libjava/Reflection.c
@@ -23,23 +23,24 @@
  * questions.
  */
 
+#include "jni.h"
 #include "jvm.h"
 #include "sun_reflect_Reflection.h"
 
-JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__
-(JNIEnv *env, jclass unused)
+JNIEXPORT jclass JNICALL
+Java_sun_reflect_Reflection_getCallerClass__(JNIEnv *env, jclass unused)
 {
     return JVM_GetCallerClass(env, JVM_CALLER_DEPTH);
 }
 
-JNIEXPORT jclass JNICALL Java_sun_reflect_Reflection_getCallerClass__I
-(JNIEnv *env, jclass unused, jint depth)
+JNIEXPORT jclass JNICALL
+Java_sun_reflect_Reflection_getCallerClass__I(JNIEnv *env, jclass unused, jint depth)
 {
     return JVM_GetCallerClass(env, depth);
 }
 
-JNIEXPORT jint JNICALL Java_sun_reflect_Reflection_getClassAccessFlags
-(JNIEnv *env, jclass unused, jclass cls)
+JNIEXPORT jint JNICALL
+Java_sun_reflect_Reflection_getClassAccessFlags(JNIEnv *env, jclass unused, jclass cls)
 {
     return JVM_GetClassAccessFlags(env, cls);
 }
diff --git a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp
deleted file mode 100644
index c852c31..0000000
--- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- *   - Neither the name of Oracle nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string.h>
-
-#include "jni.h"
-#include "jni_util.h"
-
-#include "endian.hpp"
-#include "imageDecompressor.hpp"
-#include "imageFile.hpp"
-#include "inttypes.hpp"
-#include "jimage.hpp"
-#include "osSupport.hpp"
-
-#include "jdk_internal_jimage_ImageNativeSubstrate.h"
-
-extern bool MemoryMapImage;
-
-/////////////////////////////////////////////////////////////////////////////
-
-// Static function for primitive throw since libjimage is not linked with libjava
-static void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg)
-{
-    jclass cls = (env)->FindClass(name);
-
-    if (cls != 0) /* Otherwise an exception has already been thrown */
-        (env)->ThrowNew(cls, msg);
-}
-
-// jdk.internal.jimage /////////////////////////////////////////////////////////
-
-// Java entry to open an image file for sharing.
-
-static jlong JIMAGE_Open(JNIEnv *env, const char *nativePath, jboolean big_endian) {
-    // Open image file for reading.
-    ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
-    // Return image ID as a jlong.
-    return ImageFileReader::readerToID(reader);
-}
-
-// Java entry for closing a shared image file.
-
-static void JIMAGE_Close(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader the close.
-    if (reader != NULL) {
-        ImageFileReader::close(reader);
-    }
-}
-
-// Java entry for accessing the base address of the image index.
-
-static jlong JIMAGE_GetIndexAddress(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader return index base address (as jlong) else zero.
-    return reader != NULL ? (jlong) reader->get_index_address() : 0L;
-}
-
-// Java entry for accessing the base address of the image data.
-
-static jlong JIMAGE_GetDataAddress(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader return data base address (as jlong) else zero.
-    return MemoryMapImage && reader != NULL ? (jlong) reader->get_data_address() : 0L;
-}
-
-// Java entry for reading an uncompressed resource from the image.
-
-static jboolean JIMAGE_Read(JNIEnv *env, jlong id, jlong offset,
-        unsigned char* uncompressedAddress, jlong uncompressed_size) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);\
-  // If not a valid reader the fail the read.
-    if (reader == NULL) return false;
-    // Get the file offset of resource data.
-    u8 file_offset = reader->get_index_size() + offset;
-    // Check validity of arguments.
-    if (offset < 0 ||
-            uncompressed_size < 0 ||
-            file_offset > reader->file_size() - uncompressed_size) {
-        return false;
-    }
-    // Read file content into buffer.
-    return (jboolean) reader->read_at((u1*) uncompressedAddress, uncompressed_size,
-            file_offset);
-}
-
-// Java entry for reading a compressed resource from the image.
-
-static jboolean JIMAGE_ReadCompressed(JNIEnv *env,
-        jlong id, jlong offset,
-        unsigned char* compressedAddress, jlong compressed_size,
-        unsigned char* uncompressedAddress, jlong uncompressed_size) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If not a valid reader the fail the read.
-    if (reader == NULL) return false;
-    // Get the file offset of resource data.
-    u8 file_offset = reader->get_index_size() + offset;
-    // Check validity of arguments.
-    if (offset < 0 ||
-            compressed_size < 0 ||
-            uncompressed_size < 0 ||
-            file_offset > reader->file_size() - compressed_size) {
-        return false;
-    }
-
-    // Read file content into buffer.
-    bool is_read = reader->read_at(compressedAddress, compressed_size,
-            file_offset);
-    // If successfully read then decompress.
-    if (is_read) {
-        const ImageStrings strings = reader->get_strings();
-        ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
-                (u4) uncompressed_size, &strings);
-    }
-    return (jboolean) is_read;
-}
-
-// Java entry for retrieving UTF-8 bytes from image string table.
-
-static const char* JIMAGE_GetStringBytes(JNIEnv *env, jlong id, jint offset) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Manage image string table.
-    ImageStrings strings = reader->get_strings();
-    // Retrieve string adrress from table.
-    const char* data = strings.get(offset);
-    return data;
-}
-
-// Utility function to copy location information into a jlong array.
-// WARNING: This function is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-
-static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
-    // Copy attributes from location.
-    for (int kind = ImageLocation::ATTRIBUTE_END + 1;
-            kind < ImageLocation::ATTRIBUTE_COUNT;
-            kind++) {
-        rawAttributes[kind] = location.get_attribute(kind);
-    }
-}
-
-// Java entry for retrieving location attributes for attribute offset.
-
-static jlong* JIMAGE_GetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Retrieve first byte address of resource's location attribute stream.
-    u1* data = reader->get_location_offset_data(offset);
-    // Fail if not valid offset.
-    if (data == NULL) return NULL;
-    // Expand stream into array.
-    ImageLocation location(data);
-    image_expand_location(env, rawAttributes, location);
-    return rawAttributes;
-}
-
-// Java entry for retrieving location attributes count for attribute offset.
-
-static jsize JIMAGE_GetAttributesCount(JNIEnv *env) {
-    return ImageLocation::ATTRIBUTE_COUNT;
-}
-
-// Java entry for retrieving location attributes for named resource.
-
-static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Convert byte array to a cstring.
-    char* path = new char[size + 1];
-    if (path == NULL) {
-        return NULL;
-    }
-    memcpy(path, rawBytes, size);
-    path[size] = '\0';
-    // Locate resource location data.
-    ImageLocation location;
-    bool found = reader->find_location(path, location);
-    delete[] path;
-    // Resource not found.
-    if (!found) return NULL;
-    // Expand stream into array.
-    image_expand_location(env, rawAttributes, location);
-    return rawAttributes;
-}
-
-// Java entry for retrieving all the attribute stream offsets from an image.
-
-static jint* JIMAGE_AttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Determine endian for reader.
-    Endian* endian = reader->endian();
-    // Get base address of attribute stream offsets table.
-    u4* offsets_table = reader->offsets_table();
-    // Allocate int array result.
-    // Copy values to result (converting endian.)
-    for (u4 i = 0; i < length; i++) {
-        rawOffsets[i] = endian->get(offsets_table[i]);
-    }
-    return rawOffsets;
-}
-
-// Java entry for retrieving all the attribute stream offsets length from an image.
-
-static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return 0;
-    // Get perfect hash table length.
-    u4 length = reader->table_length();
-    return (jint) length;
-}
-
-JNIEXPORT jint JNICALL
-DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
-    JNIEnv *env;
-
-    if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) {
-        return JNI_EVERSION; /* JNI version not supported */
-    }
-
-    return JNI_VERSION_1_2;
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env,
-        jclass cls, jstring path, jboolean big_endian) {
-    const char *nativePath;
-    jlong ret;
-
-    nativePath = env->GetStringUTFChars(path, NULL);
-    ret = JIMAGE_Open(env, nativePath, big_endian);
-    env->ReleaseStringUTFChars(path, nativePath);
-    return ret;
-}
-
-JNIEXPORT void JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env,
-        jclass cls, jlong id) {
-    JIMAGE_Close(env, id);
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env,
-        jclass cls, jlong id) {
-    return JIMAGE_GetIndexAddress(env, id);
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env,
-        jclass cls, jlong id) {
-    return JIMAGE_GetDataAddress(env, id);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env,
-        jclass cls, jlong id, jlong offset,
-        jobject uncompressedBuffer, jlong uncompressed_size) {
-    unsigned char* uncompressedAddress;
-
-    uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
-    if (uncompressedAddress == NULL) {
-        return JNI_FALSE;
-    }
-    return JIMAGE_Read(env, id, offset, uncompressedAddress, uncompressed_size);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env,
-        jclass cls, jlong id, jlong offset,
-        jobject compressedBuffer, jlong compressed_size,
-        jobject uncompressedBuffer, jlong uncompressed_size) {
-    // Get address of read direct buffer.
-    unsigned char* compressedAddress;
-    unsigned char* uncompressedAddress;
-
-    compressedAddress = (unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
-    // Get address of decompression direct buffer.
-    uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
-    if (compressedAddress == NULL || uncompressedAddress == NULL) {
-        return JNI_FALSE;
-    }
-    return JIMAGE_ReadCompressed(env, id, offset, compressedAddress, compressed_size,
-            uncompressedAddress, uncompressed_size);
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env,
-        jclass cls, jlong id, jint offset) {
-    const char* data;
-    size_t size;
-    jbyteArray byteArray;
-    jbyte* rawBytes;
-
-    data = JIMAGE_GetStringBytes(env, id, offset);
-    // Determine String length.
-    size = strlen(data);
-    // Allocate byte array.
-    byteArray = env->NewByteArray((jsize) size);
-    if (byteArray == NULL) {
-        return NULL;
-    }
-    // Get array base address.
-    rawBytes = env->GetByteArrayElements(byteArray, NULL);
-    // Copy bytes from image string table.
-    memcpy(rawBytes, data, size);
-    // Release byte array base address.
-    env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
-    return byteArray;
-}
-
-JNIEXPORT jlongArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env,
-        jclass cls, jlong id, jint offset) {
-    // Allocate a jlong large enough for all location attributes.
-    jlongArray attributes;
-    jlong* rawAttributes;
-    jlong* ret;
-
-    attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
-    if (attributes == NULL) {
-        return NULL;
-    }
-    // Get base address for jlong array.
-    rawAttributes = env->GetLongArrayElements(attributes, NULL);
-    ret = JIMAGE_GetAttributes(env, rawAttributes, id, offset);
-    // Release jlong array base address.
-    env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
-    return ret == NULL ? NULL : attributes;
-}
-
-JNIEXPORT jlongArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env,
-        jclass cls, jlong id, jbyteArray utf8) {
-    // Allocate a jlong large enough for all location attributes.
-    jsize count;
-    jlongArray attributes;
-    jlong* rawAttributes;
-    jsize size;
-    jbyte* rawBytes;
-    jlong* ret;
-
-    count = JIMAGE_GetAttributesCount(env);
-    attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
-    if (attributes == NULL) {
-        return NULL;
-    }
-    // Get base address for jlong array.
-    rawAttributes = env->GetLongArrayElements(attributes, NULL);
-    size = env->GetArrayLength(utf8);
-    rawBytes = env->GetByteArrayElements(utf8, NULL);
-    ret = JIMAGE_FindAttributes(env, rawAttributes, rawBytes, size, id);
-    env->ReleaseByteArrayElements(utf8, rawBytes, 0);
-    // Release jlong array base address.
-    env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
-    return ret == NULL ? NULL : attributes;
-
-}
-
-JNIEXPORT jintArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env,
-        jclass cls, jlong id) {
-    unsigned int length;
-    jintArray offsets;
-    jint* rawOffsets;
-    jint* ret;
-
-    length = JIMAGE_AttributeOffsetsLength(env, id);
-    offsets = env->NewIntArray(length);
-    if (offsets == NULL) {
-        return NULL;
-    }
-    // Get base address of result.
-    rawOffsets = env->GetIntArrayElements(offsets, NULL);
-    ret = JIMAGE_AttributeOffsets(env, rawOffsets, length, id);
-    if (length == 0) {
-        return NULL;
-    }
-    // Release result base address.
-    env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
-    return ret == NULL ? NULL : offsets;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_open
- * Signature: (Ljava/lang/String;)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open
-(JNIEnv *env, jclass, jstring path) {
-    const char *nativePath = env->GetStringUTFChars(path, NULL);
-    if (nativePath == NULL)
-        return 0; // Exception already thrown
-    jint error;
-    jlong ret = (jlong) JIMAGE_Open(nativePath, &error);
-    env->ReleaseStringUTFChars(path, nativePath);
-    return ret;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_Close
- * Signature: (J)J
- */
-JNIEXPORT void JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close
-(JNIEnv *env, jclass, jlong jimageHandle) {
-    JIMAGE_Close((JImageFile*) jimageHandle);
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_FindResource
- * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[J)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource
-(JNIEnv *env, jclass, jlong jimageHandle, jstring moduleName,
-        jstring version, jstring path, jlongArray output_size) {
-    const char *native_module = NULL;
-    const char *native_version = NULL;
-    const char *native_path = NULL;
-    jlong * native_array = NULL;
-    jlong size = 0;
-    jlong ret = 0;
-
-    if (moduleName == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "moduleName");
-        return 0;
-    }
-    if (version == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "version");
-        return 0;
-    }
-    if (path == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "path");
-        return 0;
-    }
-    if (output_size == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "size");
-        return 0;
-    }
-
-    do {
-        native_module = env->GetStringUTFChars(moduleName, NULL);
-        if (native_module == NULL)
-            break;
-        native_version = env->GetStringUTFChars(version, NULL);
-        if (native_version == NULL)
-            break;
-        native_path = env->GetStringUTFChars(path, NULL);
-        if (native_path == NULL)
-            break;
-        if (env->GetArrayLength(output_size) < 1)
-            break;
-        // Get base address for jlong array.
-        native_array = env->GetLongArrayElements(output_size, NULL);
-        if (native_array == NULL)
-            break;
-
-        ret = (jlong) JIMAGE_FindResource((JImageFile *) jimageHandle,
-                native_module, native_version, native_path, &size);
-        if (ret != 0)
-            *native_array = size;
-    } while (0);
-
-    if (native_array != NULL)
-        env->ReleaseLongArrayElements(output_size, native_array, 0);
-    if (native_path != NULL)
-        env->ReleaseStringUTFChars(path, native_path);
-    if (native_version != NULL)
-        env->ReleaseStringUTFChars(path, native_version);
-    if (native_module != NULL)
-        env->ReleaseStringUTFChars(path, native_module);
-
-    return ret;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_GetResource
- * Signature: (JJ[BJ)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource
-(JNIEnv *env, jclass, jlong jimageHandle, jlong jlocationHandle, jbyteArray buffer, jlong size) {
-    jbyte * native_buffer = NULL;
-    jlong actual_size = 0;
-    do {
-        if (env->GetArrayLength(buffer) < size)
-            break;
-
-        native_buffer = env->GetByteArrayElements(buffer, NULL);
-        if (native_buffer == NULL)
-            break;
-
-        actual_size = JIMAGE_GetResource((JImageFile*) jimageHandle,
-                (JImageLocationRef) jlocationHandle,
-                (char *) native_buffer, size);
-    } while (0);
-    // Release byte array
-    if (native_buffer != NULL)
-        env->ReleaseByteArrayElements(buffer, native_buffer, 0);
-
-    return actual_size;
-}
-
-// Structure passed from iterator to a visitor to accumulate the results
-
-struct VisitorData {
-    JNIEnv *env;
-    int size; // current number of strings
-    int max; // Maximum number of strings
-    jobjectArray array; // String array to store the strings
-};
-
-// Visitor to accumulate fully qualified resource names
-
-static bool resourceVisitor(JImageFile* image,
-        const char* module, const char* version, const char* package,
-        const char* name, const char* extension, void* arg) {
-    struct VisitorData *vdata = (struct VisitorData *) arg;
-    JNIEnv* env = vdata->env;
-    if (vdata->size < vdata->max) {
-        // Store if there is room in the array
-        // Concatenate to get full path
-        char fullpath[IMAGE_MAX_PATH];
-        size_t moduleLen = strlen(module);
-        size_t packageLen = strlen(package);
-        size_t nameLen = strlen(name);
-        size_t extLen = strlen(extension);
-        size_t index;
-
-        if (1 + moduleLen + 1 + packageLen + 1 + nameLen + 1 + extLen + 1 > IMAGE_MAX_PATH) {
-            ThrowByName(env, "java/lang/InternalError", "concatenated name too long");
-            return true;
-        }
-
-        index = 0;
-        if (moduleLen > 0) {
-            fullpath[index++] = '/';
-            memcpy(&fullpath[index], module, moduleLen);
-            index += moduleLen;
-            fullpath[index++] = '/';
-        }
-        if (packageLen > 0) {
-            memcpy(&fullpath[index], package, packageLen);
-            index += packageLen;
-            fullpath[index++] = '/';
-        }
-        memcpy(&fullpath[index], name, nameLen);
-        index += nameLen;
-        if (extLen > 0) {
-            fullpath[index++] = '.';
-            memcpy(&fullpath[index], extension, extLen);
-            index += extLen;
-        }
-        fullpath[index++] = '\0';
-
-        jobject str = env->NewStringUTF(fullpath);
-        if (env->ExceptionCheck()) {
-            return true;
-        }
-
-        env->SetObjectArrayElement(vdata->array, vdata->size, str);
-        if (env->ExceptionCheck()) {
-            return true;
-        }
-    }
-    vdata->size++; // always count so the total size is returned
-    return true;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_Resources
- * Signature: (J)V
- */
-JNIEXPORT jint JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources
-(JNIEnv *env, jclass, jlong jimageHandle,
-        jobjectArray outputNames) {
-    struct VisitorData vdata;
-    vdata.env = env;
-    vdata.max = 0;
-    vdata.size = 0;
-    vdata.array = outputNames;
-
-    vdata.max = (outputNames != NULL) ? env->GetArrayLength(outputNames) : 0;
-    JIMAGE_ResourceIterator((JImageFile*) jimageHandle, &resourceVisitor, &vdata);
-    return vdata.size;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_PackageToModule
- * Signature: (JLjava/lang/String;)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule
-(JNIEnv *env, jclass, jlong jimageHandle, jstring package_name) {
-    const char *native_package = NULL;
-    const char *native_module = NULL;
-    jstring module = NULL;
-
-    native_package = env->GetStringUTFChars(package_name, NULL);
-    if (env->ExceptionCheck()) {
-        return NULL;
-    }
-
-
-    native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package);
-    if (native_module != NULL) {
-        module = env->NewStringUTF(native_module);
-    }
-    env->ReleaseStringUTFChars(package_name, native_package);
-    return module;
-}
-
-JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved) {
-    ImageDecompressor::image_decompressor_close();
-}
diff --git a/jdk/src/java.base/share/native/libjimage/NativeImageBuffer.cpp b/jdk/src/java.base/share/native/libjimage/NativeImageBuffer.cpp
new file mode 100644
index 0000000..95fdeeb
--- /dev/null
+++ b/jdk/src/java.base/share/native/libjimage/NativeImageBuffer.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include "jni.h"
+#include "jni_util.h"
+
+#include "endian.hpp"
+#include "imageDecompressor.hpp"
+#include "imageFile.hpp"
+#include "inttypes.hpp"
+#include "jimage.hpp"
+#include "osSupport.hpp"
+
+#include "jdk_internal_jimage_NativeImageBuffer.h"
+
+
+JNIEXPORT jobject JNICALL
+Java_jdk_internal_jimage_NativeImageBuffer_getNativeMap(JNIEnv *env,
+        jclass cls, jstring path) {
+    const char *nativePath = env->GetStringUTFChars(path, NULL);
+    ImageFileReader* reader = ImageFileReader::find_image(nativePath);
+    env->ReleaseStringUTFChars(path, nativePath);
+
+    if (reader != NULL) {
+        return env->NewDirectByteBuffer(reader->get_index_address(), (jlong)reader->map_size());
+    }
+
+    return 0;
+}
diff --git a/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp b/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp
index fd788fb..72de36d 100644
--- a/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp
+++ b/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp
@@ -111,32 +111,66 @@
     return NULL;
 }
 
+// Sparc to read unaligned content
+// u8 l = (*(u8*) ptr);
+// If ptr is not aligned, sparc will fail.
+u8 ImageDecompressor::getU8(u1* ptr, Endian *endian) {
+    u8 ret;
+    if (endian->is_big_endian()) {
+        ret = (u8)ptr[0] << 56 | (u8)ptr[1] << 48 | (u8)ptr[2]<<40 | (u8)ptr[3]<<32 |
+                ptr[4]<<24 | ptr[5]<<16 | ptr[6]<<8 | ptr[7];
+    } else {
+        ret = ptr[0] | ptr[1]<<8 | ptr[2]<<16 | ptr[3]<<24 | (u8)ptr[4]<<32 |
+                (u8)ptr[5]<<40 | (u8)ptr[6]<<48 | (u8)ptr[7]<<56;
+    }
+    return ret;
+}
+
+u4 ImageDecompressor::getU4(u1* ptr, Endian *endian) {
+    u4 ret;
+    if (endian->is_big_endian()) {
+        ret = ptr[0] << 24 | ptr[1]<<16 | (ptr[2]<<8) | ptr[3];
+    } else {
+        ret = ptr[0] | ptr[1]<<8 | (ptr[2]<<16) | ptr[3]<<24;
+    }
+    return ret;
+}
+
 /*
  * Decompression entry point. Called from ImageFileReader::get_resource.
  */
 void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
-                u4 uncompressed_size, const ImageStrings* strings) {
+                u8 uncompressed_size, const ImageStrings* strings, Endian *endian) {
     bool has_header = false;
     u1* decompressed_resource = compressed;
     u1* compressed_resource = compressed;
-
     // Resource could have been transformed by a stack of decompressors.
     // Iterate and decompress resources until there is no more header.
     do {
         ResourceHeader _header;
-        memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
+        u1* compressed_resource_base = compressed_resource;
+        _header._magic = getU4(compressed_resource, endian);
+        compressed_resource += 4;
+        _header._size = getU8(compressed_resource, endian);
+        compressed_resource += 8;
+        _header._uncompressed_size = getU8(compressed_resource, endian);
+        compressed_resource += 8;
+        _header._decompressor_name_offset = getU4(compressed_resource, endian);
+        compressed_resource += 4;
+        _header._decompressor_config_offset = getU4(compressed_resource, endian);
+        compressed_resource += 4;
+        _header._is_terminal = *compressed_resource;
+        compressed_resource += 1;
         has_header = _header._magic == ResourceHeader::resource_header_magic;
         if (has_header) {
             // decompressed_resource array contains the result of decompression
-            decompressed_resource = new u1[_header._uncompressed_size];
+            decompressed_resource = new u1[(size_t) _header._uncompressed_size];
             // Retrieve the decompressor name
             const char* decompressor_name = strings->get(_header._decompressor_name_offset);
             assert(decompressor_name && "image decompressor not found");
             // Retrieve the decompressor instance
             ImageDecompressor* decompressor = get_decompressor(decompressor_name);
             assert(decompressor && "image decompressor not found");
-            u1* compressed_resource_base = compressed_resource;
-            compressed_resource += ResourceHeader::resource_header_length;
             // Ask the decompressor to decompress the compressed content
             decompressor->decompress_resource(compressed_resource, decompressed_resource,
                 &_header, strings);
@@ -146,8 +180,8 @@
             compressed_resource = decompressed_resource;
         }
     } while (has_header);
-    memcpy(uncompressed, decompressed_resource, uncompressed_size);
-    delete[] decompressed_resource;
+    memcpy(uncompressed, decompressed_resource, (size_t) uncompressed_size);
+    delete decompressed_resource;
 }
 
 // Zip decompressor
@@ -299,14 +333,14 @@
             }
         }
     }
-    u4 remain = header->_size - (int)(data - data_base);
-    u4 computed = (u4)(uncompressed_resource - uncompressed_base) + remain;
+    u8 remain = header->_size - (int)(data - data_base);
+    u8 computed = (u8)(uncompressed_resource - uncompressed_base) + remain;
     if (header->_uncompressed_size != computed)
-        printf("Failure, expecting %d but getting %d\n", header->_uncompressed_size,
+        printf("Failure, expecting %llu but getting %llu\n", header->_uncompressed_size,
                 computed);
     assert(header->_uncompressed_size == computed &&
                 "Constant Pool reconstruction failed");
-    memcpy(uncompressed_resource, data, remain);
+    memcpy(uncompressed_resource, data, (size_t) remain);
 }
 
 /*
diff --git a/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp b/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp
index 3848952..8fad624 100644
--- a/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp
+++ b/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp
@@ -54,13 +54,11 @@
  *   have been used to compress the resource.
  */
 struct ResourceHeader {
-    /* Length of header, needed to retrieve content offset */
-    static const u1 resource_header_length = 21;
     /* magic bytes that identifies a compressed resource header*/
     static const u4 resource_header_magic = 0xCAFEFAFA;
     u4 _magic; // Resource header
-    u4 _size;    // Resource size
-    u4 _uncompressed_size;  // Expected uncompressed size
+    u8 _size;    // Resource size
+    u8 _uncompressed_size;  // Expected uncompressed size
     u4 _decompressor_name_offset;    // Strings table decompressor offset
     u4 _decompressor_config_offset; // Strings table config offset
     u1 _is_terminal; // Last decompressor 1, otherwise 0.
@@ -101,6 +99,8 @@
      */
     inline const char* get_name() const { return _name; }
 
+    static u8 getU8(u1* ptr, Endian *endian);
+    static u4 getU4(u1* ptr, Endian *endian);
 
 protected:
     ImageDecompressor(const char* name) : _name(name) {
@@ -113,7 +113,7 @@
     static void image_decompressor_close();
     static ImageDecompressor* get_decompressor(const char * decompressor_name) ;
     static void decompress_resource(u1* compressed, u1* uncompressed,
-        u4 uncompressed_size, const ImageStrings* strings);
+        u8 uncompressed_size, const ImageStrings* strings, Endian* _endian);
 };
 
 /**
diff --git a/jdk/src/java.base/share/native/libjimage/imageFile.cpp b/jdk/src/java.base/share/native/libjimage/imageFile.cpp
index 769ad18..d8b2a9d 100644
--- a/jdk/src/java.base/share/native/libjimage/imageFile.cpp
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.cpp
@@ -41,7 +41,7 @@
 #include "osSupport.hpp"
 
 // Map the full jimage, only with 64 bit addressing.
-bool MemoryMapImage = sizeof(void *) == 8;
+bool ImageFileReader::memory_map_image = sizeof(void *) == 8;
 
 #ifdef WIN32
 const char FileSeparator = '\\';
@@ -144,142 +144,69 @@
 }
 
 // ImageModuleData constructor maps out sub-tables for faster access.
-ImageModuleData::ImageModuleData(const ImageFileReader* image_file,
-                const char* module_data_name) :
+ImageModuleData::ImageModuleData(const ImageFileReader* image_file) :
         _image_file(image_file),
-        _endian(image_file->endian()),
-        _strings(image_file->get_strings()) {
-    // Retrieve the resource containing the module data for the image file.
-    ImageLocation location;
-    bool found = image_file->find_location(module_data_name, location);
-    if (found) {
-        u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
-        _data = new u1[(size_t)data_size];
-        assert(_data != NULL && "allocation failed");
-        _image_file->get_resource(location, _data);
-        // Map out the header.
-        _header = (Header*)_data;
-        // Get the package to module entry count.
-        u4 ptm_count = _header->ptm_count(_endian);
-        // Get the module to package entry count.
-        u4 mtp_count = _header->mtp_count(_endian);
-        // Compute the offset of the package to module perfect hash redirect.
-        u4 ptm_redirect_offset = sizeof(Header);
-        // Compute the offset of the package to module data.
-        u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
-        // Compute the offset of the module to package perfect hash redirect.
-        u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
-        // Compute the offset of the module to package data.
-        u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
-        // Compute the offset of the module to package tables.
-        u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
-        // Compute the address of the package to module perfect hash redirect.
-        _ptm_redirect = (s4*)(_data + ptm_redirect_offset);
-        // Compute the address of the package to module data.
-        _ptm_data = (PTMData*)(_data + ptm_data_offset);
-        // Compute the address of the module to package perfect hash redirect.
-        _mtp_redirect = (s4*)(_data + mtp_redirect_offset);
-        // Compute the address of the module to package data.
-        _mtp_data = (MTPData*)(_data + mtp_data_offset);
-        // Compute the address of the module to package tables.
-        _mtp_packages = (s4*)(_data + mtp_packages_offset);
-    } else {
-        // No module data present.
-        _data = NULL;
-        _header = NULL;
-        _ptm_redirect = NULL;
-        _ptm_data = NULL;
-        _mtp_redirect = NULL;
-        _mtp_data = NULL;
-        _mtp_packages = NULL;
-    }
+        _endian(image_file->endian()) {
 }
 
 // Release module data resource.
 ImageModuleData::~ImageModuleData() {
-    if (_data) {
-        delete[] _data;
-    }
 }
 
-// Return the name of the module data resource.  Ex. "./lib/modules/file.jimage"
-// yields "file.jdata"
-void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) {
-    // Locate the last slash in the file name path.
-    const char* slash = strrchr(image_file_name, FileSeparator);
-    // Trim the path to name and extension.
-    const char* name = slash ? slash + 1 : (char *)image_file_name;
-    // Locate the extension period.
-    const char* dot = strrchr(name, '.');
-    assert(dot && "missing extension on jimage name");
-    // Trim to only base name.
-    int length = (int)(dot - name);
-    strncpy(buffer, name, length);
-    buffer[length] = '\0';
-    // Append extension.
-    strcat(buffer, ".jdata");
-}
 
 // Return the module in which a package resides.    Returns NULL if not found.
 const char* ImageModuleData::package_to_module(const char* package_name) {
-    // Test files may contain no module data.
-    if (_data != NULL) {
-        // Search the package to module table.
-        s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
-                                      _header->ptm_count(_endian));
-        // If entry is found.
-        if (index != ImageStrings::NOT_FOUND) {
-            // Retrieve the package to module entry.
-            PTMData* data = _ptm_data + index;
-            // Verify that it is the correct data.
-            if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
-                return NULL;
-            }
-            // Return the module name.
-            return get_string(data->module_name_offset(_endian));
-        }
+    // replace all '/' by '.'
+    char* replaced = new char[(int) strlen(package_name) + 1];
+    assert(replaced != NULL && "allocation failed");
+    int i;
+    for (i = 0; package_name[i] != '\0'; i++) {
+      replaced[i] = package_name[i] == '/' ? '.' : package_name[i];
     }
-    return NULL;
-}
+    replaced[i] = '\0';
 
-// Returns all the package names in a module in a NULL terminated array.
-// Returns NULL if module not found.
-const char** ImageModuleData::module_to_packages(const char* module_name) {
-    // Test files may contain no module data.
-    if (_data != NULL) {
-        // Search the module to package table.
-        s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
-                                      _header->mtp_count(_endian));
-        // If entry is found.
-        if (index != ImageStrings::NOT_FOUND) {
-            // Retrieve the module to package entry.
-            MTPData* data = _mtp_data + index;
-            // Verify that it is the correct data.
-            if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
-                return NULL;
-            }
-            // Construct an array of all the package entries.
-            u4 count = data->package_count(_endian);
-            const char** packages = new const char*[count + 1];
-            assert(packages != NULL && "allocation failed");
-            s4 package_offset = data->package_offset(_endian);
-            for (u4 i = 0; i < count; i++) {
-                u4 package_name_offset = mtp_package(package_offset + i);
-                const char* package_name = get_string(package_name_offset);
-                packages[i] = package_name;
-            }
-            packages[count] = NULL;
-            return packages;
-        }
+    // build path /packages/<package_name>
+    const char* radical = "/packages/";
+    char* path = new char[(int) strlen(radical) + (int) strlen(package_name) + 1];
+    assert(path != NULL && "allocation failed");
+    strcpy(path, radical);
+    strcat(path, replaced);
+    delete[] replaced;
+
+    // retrieve package location
+    ImageLocation location;
+    bool found = _image_file->find_location(path, location);
+    if (!found) {
+        delete[] path;
+        return NULL;
     }
-    return NULL;
+
+    // retrieve offsets to module name
+    int size = (int)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+    u1* content = new u1[size];
+    assert(content != NULL && "allocation failed");
+    _image_file->get_resource(location, content);
+    u1* ptr = content;
+    // sequence of sizeof(8) isEmpty|offset. Use the first module that is not empty.
+    u4 offset = 0;
+    for (i = 0; i < size; i+=8) {
+        u4 isEmpty = _endian->get(*((u4*)ptr));
+        ptr += 4;
+        if (!isEmpty) {
+            offset = _endian->get(*((u4*)ptr));
+            break;
+        }
+        ptr += 4;
+    }
+    delete[] content;
+    return _image_file->get_strings().get(offset);
 }
 
 // Manage a table of open image files.  This table allows multiple access points
 // to share an open image.
 ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
     _table = new ImageFileReader*[_max];
-    assert( _table != NULL && "allocation failed");
+    assert(_table != NULL && "allocation failed");
 }
 
 ImageFileReaderTable::~ImageFileReaderTable() {
@@ -326,26 +253,34 @@
 
 SimpleCriticalSection _reader_table_lock;
 
+// Locate an image if file already open.
+ImageFileReader* ImageFileReader::find_image(const char* name) {
+    // Lock out _reader_table.
+    SimpleCriticalSectionLock cs(&_reader_table_lock);
+    // Search for an exist image file.
+    for (u4 i = 0; i < _reader_table.count(); i++) {
+        // Retrieve table entry.
+        ImageFileReader* reader = _reader_table.get(i);
+        // If name matches, then reuse (bump up use count.)
+        assert(reader->name() != NULL && "reader->name must not be null");
+        if (strcmp(reader->name(), name) == 0) {
+            reader->inc_use();
+            return reader;
+        }
+    }
+
+    return NULL;
+}
+
 // Open an image file, reuse structure if file already open.
 ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
-    {
-        // Lock out _reader_table.
-        SimpleCriticalSectionLock cs(&_reader_table_lock);
-        // Search for an exist image file.
-        for (u4 i = 0; i < _reader_table.count(); i++) {
-            // Retrieve table entry.
-            ImageFileReader* reader = _reader_table.get(i);
-            // If name matches, then reuse (bump up use count.)
-            assert(reader->name() != NULL && "reader->name must not be null");
-            if (strcmp(reader->name(), name) == 0) {
-                reader->inc_use();
-                return reader;
-            }
-        }
-    } // Unlock the mutex
+    ImageFileReader* reader = find_image(name);
+    if (reader != NULL) {
+        return reader;
+    }
 
     // Need a new image reader.
-    ImageFileReader* reader = new ImageFileReader(name, big_endian);
+    reader = new ImageFileReader(name, big_endian);
     if (reader == NULL || !reader->open()) {
         // Failed to open.
         delete reader;
@@ -385,21 +320,21 @@
 }
 
 // Return an id for the specifed ImageFileReader.
-u8 ImageFileReader::readerToID(ImageFileReader *reader) {
+u8 ImageFileReader::reader_to_ID(ImageFileReader *reader) {
     // ID is just the cloaked reader address.
     return (u8)reader;
 }
 
 // Validate the image id.
-bool ImageFileReader::idCheck(u8 id) {
+bool ImageFileReader::id_check(u8 id) {
     // Make sure the ID is a managed (_reader_table) reader.
     SimpleCriticalSectionLock cs(&_reader_table_lock);
     return _reader_table.contains((ImageFileReader*)id);
 }
 
 // Return an id for the specifed ImageFileReader.
-ImageFileReader* ImageFileReader::idToReader(u8 id) {
-    assert(idCheck(id) && "invalid image id");
+ImageFileReader* ImageFileReader::id_to_reader(u8 id) {
+    assert(id_check(id) && "invalid image id");
     return (ImageFileReader*)id;
 }
 
@@ -429,8 +364,6 @@
 
 // Open image file for read access.
 bool ImageFileReader::open() {
-    char buffer[IMAGE_MAX_PATH];
-
     // If file exists open for reading.
     _fd = osSupport::openReadOnly(_name);
     if (_fd == -1) {
@@ -454,19 +387,17 @@
     if (_file_size < _index_size) {
         return false;
     }
-    // Determine how much of the image is memory mapped.
-    size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size);
     // Memory map image (minimally the index.)
-    _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size);
+    _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, (size_t)map_size());
     assert(_index_data && "image file not memory mapped");
     // Retrieve length of index perfect hash table.
     u4 length = table_length();
     // Compute offset of the perfect hash table redirect table.
     u4 redirect_table_offset = (u4)header_size;
     // Compute offset of index attribute offsets.
-    u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
+    u4 offsets_table_offset = redirect_table_offset + length * (u4)sizeof(s4);
     // Compute offset of index location attribute data.
-    u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
+    u4 location_bytes_offset = offsets_table_offset + length * (u4)sizeof(u4);
     // Compute offset of index string table.
     u4 string_bytes_offset = location_bytes_offset + locations_size();
     // Compute address of the perfect hash table redirect table.
@@ -479,8 +410,7 @@
     _string_bytes = _index_data + string_bytes_offset;
 
     // Initialize the module data
-    ImageModuleData::module_data_name(buffer, _name);
-    module_data = new ImageModuleData(this, buffer);
+    module_data = new ImageModuleData(this);
     // Successful open (if memory allocation succeeded).
     return module_data != NULL;
 }
@@ -660,10 +590,10 @@
     if (compressed_size != 0) {
         u1* compressed_data;
         // If not memory mapped read in bytes.
-        if (!MemoryMapImage) {
+        if (!memory_map_image) {
             // Allocate buffer for compression.
-            compressed_data = new u1[(u4)compressed_size];
-            assert (compressed_data != NULL && "allocation failed");
+            compressed_data = new u1[(size_t)compressed_size];
+            assert(compressed_data != NULL && "allocation failed");
             // Read bytes from offset beyond the image index.
             bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
             assert(is_read && "error reading from image or short read");
@@ -673,10 +603,10 @@
         // Get image string table.
         const ImageStrings strings = get_strings();
         // Decompress resource.
-        ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size,
-                        &strings);
+        ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
+                        &strings, _endian);
         // If not memory mapped then release temporary buffer.
-        if (!MemoryMapImage) {
+        if (!memory_map_image) {
                 delete[] compressed_data;
         }
     } else {
diff --git a/jdk/src/java.base/share/native/libjimage/imageFile.hpp b/jdk/src/java.base/share/native/libjimage/imageFile.hpp
index 9cb7eb4..9e02d87 100644
--- a/jdk/src/java.base/share/native/libjimage/imageFile.hpp
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.hpp
@@ -303,101 +303,17 @@
 };
 
 //
-// NOTE: needs revision.
-// Each loader requires set of module meta data to identify which modules and
-// packages are managed by that loader.  Currently, there is one image file per
-// builtin loader, so only one  module meta data resource per file.
-//
-// Each element in the module meta data is a native endian 4 byte integer.  Note
-// that entries with zero offsets for string table entries should be ignored (
-// padding for hash table lookup.)
-//
-// Format:
-//      Count of package to module entries
-//      Count of module to package entries
-//      Perfect Hash redirect table[Count of package to module entries]
-//      Package to module entries[Count of package to module entries]
-//          Offset to package name in string table
-//          Offset to module name in string table
-//      Perfect Hash redirect table[Count of module to package entries]
-//      Module to package entries[Count of module to package entries]
-//          Offset to module name in string table
-//          Count of packages in module
-//          Offset to first package in packages table
-//      Packages[]
-//          Offset to package name in string table
-//
 // Manage the image module meta data.
 class ImageModuleData {
-    class Header {
-    private:
-        u4 _ptm_count;          // Count of package to module entries
-        u4 _mtp_count;          // Count of module to package entries
-    public:
-        inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); }
-        inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); }
-    };
-
-    // Hashtable entry
-    class HashData {
-    private:
-        u4 _name_offset;        // Name offset in string table
-    public:
-        inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); }
-    };
-
-    // Package to module hashtable entry
-    class PTMData : public HashData {
-    private:
-        u4 _module_name_offset; // Module name offset in string table
-    public:
-        inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); }
-    };
-
-    // Module to package hashtable entry
-    class MTPData : public HashData {
-    private:
-        u4 _package_count;       // Number of packages in module
-        u4 _package_offset;      // Offset in package list
-    public:
-        inline u4 package_count(Endian* endian)  const { return endian->get(_package_count); }
-        inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); }
-    };
-
     const ImageFileReader* _image_file; // Source image file
-    Endian* _endian;       // Endian handler
-    ImageStrings _strings; // Image file strings
-    u1* _data;             // Module data resource data
-    u8 _data_size;         // Size of resource data
-    Header* _header;       // Module data header
-    s4* _ptm_redirect;     // Package to module hashtable redirect
-    PTMData* _ptm_data;    // Package to module data
-    s4* _mtp_redirect;     // Module to packages hashtable redirect
-    MTPData* _mtp_data;    // Module to packages data
-    s4* _mtp_packages;     // Package data (name offsets)
-
-    // Return a string from the string table.
-    inline const char* get_string(u4 offset) {
-        return _strings.get(offset);
-    }
-
-    inline u4 mtp_package(u4 index) {
-        return _endian->get(_mtp_packages[index]);
-    }
+    Endian* _endian;                    // Endian handler
 
 public:
-    ImageModuleData(const ImageFileReader* image_file, const char* module_data_name);
+    ImageModuleData(const ImageFileReader* image_file);
     ~ImageModuleData();
 
-    // Return the name of the module data resource.
-    static void module_data_name(char* buffer, const char* image_file_name);
-
     // Return the module in which a package resides.    Returns NULL if not found.
     const char* package_to_module(const char* package_name);
-
-    // Returns all the package names in a module in a NULL terminated array.
-    // Returns NULL if module not found.
-    const char** module_to_packages(const char* module_name);
 };
 
 // Image file header, starting at offset 0.
@@ -491,6 +407,9 @@
     // multiple uses (ex. loader.)
     static ImageFileReaderTable _reader_table;
 
+    // true if image should be fully memory mapped.
+    static bool memory_map_image;
+
     char* _name;         // Name of image
     s4 _use;             // Use count
     int _fd;             // File descriptor
@@ -526,6 +445,9 @@
         MINOR_VERSION = 0
     };
 
+    // Locate an image if file already open.
+    static ImageFileReader* find_image(const char* name);
+
     // Open an image file, reuse structure if file already open.
     static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
 
@@ -533,13 +455,13 @@
     static void close(ImageFileReader *reader);
 
     // Return an id for the specifed ImageFileReader.
-    static u8 readerToID(ImageFileReader *reader);
+    static u8 reader_to_ID(ImageFileReader *reader);
 
     // Validate the image id.
-    static bool idCheck(u8 id);
+    static bool id_check(u8 id);
 
     // Return an id for the specifed ImageFileReader.
-    static ImageFileReader* idToReader(u8 id);
+    static ImageFileReader* id_to_reader(u8 id);
 
     // Open image file for read access.
     bool open();
@@ -562,6 +484,11 @@
         return _file_size;
     }
 
+    // Retrieve the size of the mapped image.
+    inline u8 map_size() const {
+        return (u8)(memory_map_image ? _file_size : _index_size);
+    }
+
     // Return first address of index data.
     inline u1* get_index_address() const {
         return _index_data;
diff --git a/jdk/src/java.base/share/native/libjimage/jimage.cpp b/jdk/src/java.base/share/native/libjimage/jimage.cpp
index 4ed00d2..4816a17 100644
--- a/jdk/src/java.base/share/native/libjimage/jimage.cpp
+++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp
@@ -48,7 +48,7 @@
  *
  *  Ex.
  *   jint error;
- *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
+ *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
  *   if (image == NULL) {
  *     tty->print_cr("JImage failed to open: %d", error);
  *     ...
diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp
index 0650f23..d215e30 100644
--- a/jdk/src/java.base/share/native/libjimage/jimage.hpp
+++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp
@@ -62,7 +62,7 @@
  *
  *  Ex.
  *   jint error;
- *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
+ *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
  *   if (image == NULL) {
  *     tty->print_cr("JImage failed to open: %d", error);
  *     ...
diff --git a/jdk/src/java.base/share/native/libjli/args.c b/jdk/src/java.base/share/native/libjli/args.c
index e275ccf..268046c 100644
--- a/jdk/src/java.base/share/native/libjli/args.c
+++ b/jdk/src/java.base/share/native/libjli/args.c
@@ -105,9 +105,15 @@
     if (*arg++ == '-') {
         expectingNoDashArg = JNI_FALSE;
         if (JLI_StrCmp(arg, "cp") == 0 ||
-            JLI_StrCmp(arg, "classpath") == 0) {
+            JLI_StrCmp(arg, "classpath") == 0 ||
+            JLI_StrCmp(arg, "addmods") == 0 ||
+            JLI_StrCmp(arg, "limitmods") == 0 ||
+            JLI_StrCmp(arg, "mp") == 0 ||
+            JLI_StrCmp(arg, "modulepath") == 0 ||
+            JLI_StrCmp(arg, "upgrademodulepath") == 0) {
             expectingNoDashArg = JNI_TRUE;
-        } else if (JLI_StrCmp(arg, "jar") == 0) {
+        } else if (JLI_StrCmp(arg, "jar") == 0 ||
+                   JLI_StrCmp(arg, "m") == 0) {
             // This is tricky, we do expect NoDashArg
             // But that is considered main class to stop expansion
             expectingNoDashArg = JNI_FALSE;
diff --git a/jdk/src/java.base/share/native/libjli/emessages.h b/jdk/src/java.base/share/native/libjli/emessages.h
index 75b646f..9e3a755 100644
--- a/jdk/src/java.base/share/native/libjli/emessages.h
+++ b/jdk/src/java.base/share/native/libjli/emessages.h
@@ -41,6 +41,10 @@
 #define ARG_ERROR1      "Error: %s requires class path specification"
 #define ARG_ERROR2      "Error: %s requires jar file specification"
 #define ARG_ERROR3      "Error: The -J option should not be followed by a space."
+#define ARG_ERROR4      "Error: %s requires module path specification"
+#define ARG_ERROR5      "Error: %s requires module id"
+#define ARG_ERROR6      "Error: %s requires modules to be specified"
+#define ARG_ERROR7      "Error: %s can only be specified once"
 
 #define JVM_ERROR1      "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
 #define JVM_ERROR2      "Error: Could not detach main thread.\n" JNI_ERROR
diff --git a/jdk/src/java.base/share/native/libjli/java.c b/jdk/src/java.base/share/native/libjli/java.c
index 41e0e21..9fd3ffd 100644
--- a/jdk/src/java.base/share/native/libjli/java.c
+++ b/jdk/src/java.base/share/native/libjli/java.c
@@ -69,10 +69,12 @@
 static jboolean printUsage = JNI_FALSE;   /* print and exit*/
 static jboolean printXUsage = JNI_FALSE;  /* print and exit*/
 static char     *showSettings = NULL;      /* print but continue */
+static char     *listModules = NULL;
 
 static const char *_program_name;
 static const char *_launcher_name;
 static jboolean _is_java_args = JNI_FALSE;
+static jboolean _have_classpath = JNI_FALSE;
 static const char *_fVersion;
 static jboolean _wc_enabled = JNI_FALSE;
 static jint _ergo_policy = DEFAULT_POLICY;
@@ -96,6 +98,14 @@
  * Prototypes for functions internal to launcher.
  */
 static void SetClassPath(const char *s);
+static void SetModulePath(const char *s);
+static void SetUpgradeModulePath(const char *s);
+static void SetMainModule(const char *s);
+static void SetAddModulesProp(const char *mods);
+static void SetLimitModulesProp(const char *mods);
+static void SetAddReadsProp(const jint n, const char *s);
+static void SetAddExportsProp(const jint n, const char *s);
+static void SetPatchProp(const jint n, const char *s);
 static void SelectVersion(int argc, char **argv, char **main_class);
 static void SetJvmEnvironment(int argc, char **argv);
 static jboolean ParseArguments(int *pargc, char ***pargv,
@@ -114,6 +124,7 @@
 static void PrintJavaVersion(JNIEnv *env, jboolean extraLF);
 static void PrintUsage(JNIEnv* env, jboolean doXUsage);
 static void ShowSettings(JNIEnv* env, char *optString);
+static void ListModules(JNIEnv* env, char *optString);
 
 static void SetPaths(int argc, char **argv);
 
@@ -193,7 +204,6 @@
 {
     int mode = LM_UNKNOWN;
     char *what = NULL;
-    char *cpath = 0;
     char *main_class = NULL;
     int ret;
     InvocationFunctions ifn;
@@ -270,11 +280,10 @@
         }
     } else {
         /* Set default CLASSPATH */
-        cpath = getenv("CLASSPATH");
-        if (cpath == NULL) {
-            cpath = ".";
+        char* cpath = getenv("CLASSPATH");
+        if (cpath != NULL) {
+            SetClassPath(cpath);
         }
-        SetClassPath(cpath);
     }
 
     /* Parse command line options; if the return value of
@@ -382,6 +391,12 @@
         CHECK_EXCEPTION_LEAVE(1);
     }
 
+    if (listModules != NULL) {
+        ListModules(env, listModules);
+        CHECK_EXCEPTION_LEAVE(1);
+        LEAVE();
+    }
+
     if (printVersion || showVersion) {
         PrintJavaVersion(env, showVersion);
         CHECK_EXCEPTION_LEAVE(0);
@@ -520,7 +535,12 @@
             }
         } else {
             if (JLI_StrCmp(arg, "-classpath") == 0 ||
-                JLI_StrCmp(arg, "-cp") == 0) {
+                JLI_StrCmp(arg, "-cp") == 0 ||
+                JLI_StrCmp(arg, "-modulepath") == 0 ||
+                JLI_StrCmp(arg, "-mp") == 0 ||
+                JLI_StrCmp(arg, "-upgrademodulepath") == 0 ||
+                JLI_StrCmp(arg, "-addmods") == 0 ||
+                JLI_StrCmp(arg, "-limitmods") == 0) {
                 newArgv[newArgvIdx++] = arg;
                 argi++;
                 if (argi < argc) {
@@ -841,6 +861,105 @@
     AddOption(def, NULL);
     if (s != orig)
         JLI_MemFree((char *) s);
+    _have_classpath = JNI_TRUE;
+}
+
+static void
+SetModulePath(const char *s)
+{
+    char *def;
+    const char *orig = s;
+    static const char format[] = "-Djdk.module.path=%s";
+    if (s == NULL)
+        return;
+    s = JLI_WildcardExpandClasspath(s);
+    def = JLI_MemAlloc(sizeof(format)
+                       - 2 /* strlen("%s") */
+                       + JLI_StrLen(s));
+    sprintf(def, format, s);
+    AddOption(def, NULL);
+    if (s != orig)
+        JLI_MemFree((char *) s);
+}
+
+static void
+SetUpgradeModulePath(const char *s)
+{
+    char *def;
+    const char *orig = s;
+    static const char format[] = "-Djdk.upgrade.module.path=%s";
+    if (s == NULL)
+        return;
+    s = JLI_WildcardExpandClasspath(s);
+    def = JLI_MemAlloc(sizeof(format)
+                       - 2 /* strlen("%s") */
+                       + JLI_StrLen(s));
+    sprintf(def, format, s);
+    AddOption(def, NULL);
+    if (s != orig)
+        JLI_MemFree((char *) s);
+}
+
+static void
+SetMainModule(const char *s)
+{
+    static const char format[] = "-Djdk.module.main=%s";
+    char* slash = JLI_StrChr(s, '/');
+    size_t s_len, def_len;
+    char *def;
+
+    /* value may be <module> or <module>/<mainclass> */
+    if (slash == NULL) {
+        s_len = JLI_StrLen(s);
+    } else {
+        s_len = (size_t) (slash - s);
+    }
+    def_len = sizeof(format)
+               - 2 /* strlen("%s") */
+               + s_len;
+    def = JLI_MemAlloc(def_len);
+    JLI_Snprintf(def, def_len, format, s);
+    AddOption(def, NULL);
+}
+
+static void
+SetAddModulesProp(const char *mods) {
+    size_t buflen = JLI_StrLen(mods) + 40;
+    char *prop = (char *)JLI_MemAlloc(buflen);
+    JLI_Snprintf(prop, buflen, "-Djdk.launcher.addmods=%s", mods);
+    AddOption(prop, NULL);
+}
+
+static void
+SetLimitModulesProp(const char *mods) {
+    size_t buflen = JLI_StrLen(mods) + 40;
+    char *prop = (char *)JLI_MemAlloc(buflen);
+    JLI_Snprintf(prop, buflen, "-Djdk.launcher.limitmods=%s", mods);
+    AddOption(prop, NULL);
+}
+
+static void
+SetAddReadsProp(const jint n, const char *s) {
+    size_t buflen = JLI_StrLen(s) + 40;
+    char *prop = (char *)JLI_MemAlloc(buflen);
+    JLI_Snprintf(prop, buflen, "-Djdk.launcher.addreads.%d=%s", n, s);
+    AddOption(prop, NULL);
+}
+
+static void
+SetAddExportsProp(const jint n, const char *s) {
+    size_t buflen = JLI_StrLen(s) + 40;
+    char *prop = (char *)JLI_MemAlloc(buflen);
+    JLI_Snprintf(prop, buflen, "-Djdk.launcher.addexports.%d=%s", n, s);
+    AddOption(prop, NULL);
+}
+
+static void
+SetPatchProp(const jint n, const char *s) {
+    size_t buflen = JLI_StrLen(s) + 40;
+    char *prop = (char *)JLI_MemAlloc(buflen);
+    JLI_Snprintf(prop, buflen, "-Djdk.launcher.patch.%d=%s", n, s);
+    AddOption(prop, NULL);
 }
 
 /*
@@ -1030,9 +1149,45 @@
             SetClassPath(*argv);
             mode = LM_CLASS;
             argv++; --argc;
+        } else if (JLI_StrCmp(arg, "-modulepath") == 0 || JLI_StrCmp(arg, "-mp") == 0) {
+            ARG_CHECK (argc, ARG_ERROR4, arg);
+            SetModulePath(*argv);
+            argv++; --argc;
+        } else if (JLI_StrCmp(arg, "-upgrademodulepath") == 0) {
+            ARG_CHECK (argc, ARG_ERROR4, arg);
+            SetUpgradeModulePath(*argv);
+            argv++; --argc;
         } else if (JLI_StrCmp(arg, "-jar") == 0) {
             ARG_CHECK (argc, ARG_ERROR2, arg);
             mode = LM_JAR;
+        } else if (JLI_StrCmp(arg, "-m") == 0) {
+            ARG_CHECK (argc, ARG_ERROR5, arg);
+            SetMainModule(*argv);
+            mode = LM_MODULE;
+        } else if (JLI_StrCmp(arg, "-addmods") == 0) {
+            ARG_CHECK (argc, ARG_ERROR6, arg);
+            SetAddModulesProp(*argv);
+            argv++; --argc;
+        } else if (JLI_StrCmp(arg, "-limitmods") == 0) {
+            ARG_CHECK (argc, ARG_ERROR6, arg);
+            SetLimitModulesProp(*argv);
+            argv++; --argc;
+        } else if (JLI_StrCmp(arg, "-listmods") == 0 ||
+                   JLI_StrCCmp(arg, "-listmods:") == 0) {
+            listModules = arg;
+            return JNI_TRUE;
+        } else if (JLI_StrCCmp(arg, "-XaddReads:") == 0) {
+            static jint n;
+            char *value = arg + 11;
+            SetAddReadsProp(n++, value);
+        } else if (JLI_StrCCmp(arg, "-XaddExports:") == 0) {
+            static jint n;
+            char *value = arg + 13;
+            SetAddExportsProp(n++, value);
+        } else if (JLI_StrCCmp(arg, "-Xpatch:") == 0) {
+            static jint n;
+            char *value = arg + 8;
+            SetPatchProp(n++, value);
         } else if (JLI_StrCmp(arg, "-help") == 0 ||
                    JLI_StrCmp(arg, "-h") == 0 ||
                    JLI_StrCmp(arg, "-?") == 0) {
@@ -1051,10 +1206,13 @@
  * In the latter case, any SUBOPT value not recognized will default to "all"
  */
         } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 ||
-                JLI_StrCCmp(arg, "-XshowSettings:") == 0) {
+                   JLI_StrCCmp(arg, "-XshowSettings:") == 0) {
             showSettings = arg;
         } else if (JLI_StrCmp(arg, "-Xdiag") == 0) {
             AddOption("-Dsun.java.launcher.diag=true", NULL);
+            AddOption("-Djdk.launcher.traceResolver=true", NULL);
+        } else if (JLI_StrCmp(arg, "-Xdiag:resolver") == 0) {
+            AddOption("-Djdk.launcher.traceResolver=true", NULL);
 /*
  * The following case provide backward compatibility with old-style
  * command line options.
@@ -1099,6 +1257,10 @@
         } else if (RemovableOption(arg)) {
             ; /* Do not pass option to vm. */
         } else {
+            /* java.class.path set on the command line */
+            if (JLI_StrCCmp(arg, "-Djava.class.path=") == 0) {
+                _have_classpath = JNI_TRUE;
+            }
             AddOption(arg, NULL);
         }
     }
@@ -1110,8 +1272,11 @@
     if (*pwhat == NULL) {
         *pret = 1;
     } else if (mode == LM_UNKNOWN) {
-        /* default to LM_CLASS if -jar and -cp option are
+        /* default to LM_CLASS if -m, -jar and -cp options are
          * not specified */
+        if (!_have_classpath) {
+            SetClassPath(".");
+        }
         mode = LM_CLASS;
     }
 
@@ -1503,6 +1668,24 @@
                                  ServerClassMachine());
 }
 
+/**
+ * List modules supported by the runtime
+ */
+static void
+ListModules(JNIEnv *env, char *optString)
+{
+    jmethodID listModulesID;
+    jstring joptString;
+    jclass cls = GetLauncherHelperClass(env);
+    NULL_CHECK(cls);
+    NULL_CHECK(listModulesID = (*env)->GetStaticMethodID(env, cls,
+            "listModules", "(ZLjava/lang/String;)V"));
+    NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
+    (*env)->CallStaticVoidMethod(env, cls, listModulesID,
+                                 USE_STDERR,
+                                 joptString);
+}
+
 /*
  * Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
  */
diff --git a/jdk/src/java.base/share/native/libjli/java.h b/jdk/src/java.base/share/native/libjli/java.h
index f6156fb..cf9d37e 100644
--- a/jdk/src/java.base/share/native/libjli/java.h
+++ b/jdk/src/java.base/share/native/libjli/java.h
@@ -223,7 +223,8 @@
 enum LaunchMode {               // cf. sun.launcher.LauncherHelper
     LM_UNKNOWN = 0,
     LM_CLASS,
-    LM_JAR
+    LM_JAR,
+    LM_MODULE
 };
 
 static const char *launchModeNames[]
diff --git a/jdk/src/java.base/solaris/classes/module-info.java.extra b/jdk/src/java.base/solaris/classes/module-info.java.extra
new file mode 100644
index 0000000..1e46f7c
--- /dev/null
+++ b/jdk/src/java.base/solaris/classes/module-info.java.extra
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+exports sun.nio.ch to jdk.crypto.ucrypto;
+exports sun.security.action to jdk.crypto.ucrypto;
+exports sun.security.internal.spec to jdk.crypto.ucrypto;
+exports sun.security.jca to jdk.crypto.ucrypto;
+exports sun.security.rsa to jdk.crypto.ucrypto;
+exports sun.security.util to jdk.crypto.ucrypto;
diff --git a/jdk/src/java.base/windows/classes/module-info.java.extra b/jdk/src/java.base/windows/classes/module-info.java.extra
new file mode 100644
index 0000000..1e4a3a6
--- /dev/null
+++ b/jdk/src/java.base/windows/classes/module-info.java.extra
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+exports sun.security.rsa to jdk.crypto.mscapi;
+exports sun.security.internal.spec to jdk.crypto.mscapi;
+exports sun.security.util to jdk.crypto.mscapi;
diff --git a/jdk/src/java.compact1/share/classes/module-info.java b/jdk/src/java.compact1/share/classes/module-info.java
new file mode 100644
index 0000000..8c60468
--- /dev/null
+++ b/jdk/src/java.compact1/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.compact1 {
+    requires public java.logging;
+    requires public java.scripting;
+}
+
diff --git a/jdk/src/java.compact2/share/classes/module-info.java b/jdk/src/java.compact2/share/classes/module-info.java
new file mode 100644
index 0000000..31a738d
--- /dev/null
+++ b/jdk/src/java.compact2/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.compact2 {
+    requires public java.compact1;
+    requires public java.rmi;
+    requires public java.sql;
+    requires public java.xml;
+}
+
diff --git a/jdk/src/java.compact3/share/classes/module-info.java b/jdk/src/java.compact3/share/classes/module-info.java
new file mode 100644
index 0000000..aff5c52
--- /dev/null
+++ b/jdk/src/java.compact3/share/classes/module-info.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.compact3 {
+    requires public java.compact2;
+    requires public java.compiler;
+    requires public java.httpclient;
+    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;
+}
+
diff --git a/jdk/src/java.datatransfer/share/classes/module-info.java b/jdk/src/java.datatransfer/share/classes/module-info.java
new file mode 100644
index 0000000..6c5c3a1
--- /dev/null
+++ b/jdk/src/java.datatransfer/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+module java.datatransfer {
+    exports java.awt.datatransfer;
+    exports sun.datatransfer to java.desktop;
+    uses sun.datatransfer.DesktopDatatransferService;
+}
diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java
index faa6703..67520fc 100644
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtils.java
@@ -37,12 +37,13 @@
 import javax.swing.border.Border;
 import javax.swing.plaf.UIResource;
 
+import jdk.internal.loader.ClassLoaders;
+
 import sun.awt.AppContext;
 
 import sun.lwawt.macosx.CImage;
 import sun.lwawt.macosx.CImage.Creator;
 import sun.lwawt.macosx.CPlatformWindow;
-import sun.misc.Launcher;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.action.GetPropertyAction;
 import sun.swing.SwingUtilities2;
@@ -364,7 +365,8 @@
     // special casing naughty applications, like InstallAnywhere
     // <rdar://problem/4851533> REGR: JButton: Myst IV: the buttons of 1.0.3 updater have redraw issue
     static boolean shouldUseOpaqueButtons() {
-        final ClassLoader launcherClassLoader = Launcher.getLauncher().getClassLoader();
+        // can we use ClassLoader.getSystemClassLoader here?
+        final ClassLoader launcherClassLoader = ClassLoaders.appClassLoader();
         if (classExists(launcherClassLoader, "com.installshield.wizard.platform.macosx.MacOSXUtils")) return true;
         return false;
     }
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
index cc3d345..b4116a1 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
@@ -51,8 +51,6 @@
 import sun.lwawt.LWWindowPeer.PeerType;
 import sun.security.action.GetBooleanAction;
 
-import sun.util.CoreResourceBundleControl;
-
 @SuppressWarnings("serial") // JDK implementation class
 final class NamedCursor extends Cursor {
     NamedCursor(String name) {
@@ -84,9 +82,7 @@
             public ResourceBundle run() {
                 ResourceBundle platformResources = null;
                 try {
-                    platformResources =
-                            ResourceBundle.getBundle("sun.awt.resources.awtosx",
-                                    CoreResourceBundleControl.getRBControlInstance());
+                    platformResources = ResourceBundle.getBundle("sun.awt.resources.awtosx");
                 } catch (MissingResourceException e) {
                     // No resource file; defaults will be used.
                 }
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/java.net.ContentHandlerFactory b/jdk/src/java.desktop/share/classes/META-INF/services/java.net.ContentHandlerFactory
deleted file mode 100644
index 85fce1e..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/java.net.ContentHandlerFactory
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  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.
-#
-
-# Provider for content handlers
-sun.awt.www.content.MultimediaContentHandlers
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.PrintServiceLookup b/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.PrintServiceLookup
deleted file mode 100644
index bbeb657..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.PrintServiceLookup
+++ /dev/null
@@ -1,2 +0,0 @@
-# Provider for Java Print Service
-sun.print.PrintServiceLookupProvider
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.StreamPrintServiceFactory b/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.StreamPrintServiceFactory
deleted file mode 100644
index b1bf88d..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.print.StreamPrintServiceFactory
+++ /dev/null
@@ -1,2 +0,0 @@
-# Provider for Java 2D Stream print services.
-sun.print.PSStreamPrinterFactory
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiDeviceProvider b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiDeviceProvider
deleted file mode 100644
index bffb952..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiDeviceProvider
+++ /dev/null
@@ -1,5 +0,0 @@
-# Providers for midi devices
-com.sun.media.sound.RealTimeSequencerProvider
-com.sun.media.sound.MidiOutDeviceProvider
-com.sun.media.sound.MidiInDeviceProvider
-com.sun.media.sound.SoftProvider
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileReader b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileReader
deleted file mode 100644
index 1d643a0..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileReader
+++ /dev/null
@@ -1,2 +0,0 @@
-# Providers for midi sequences
-com.sun.media.sound.StandardMidiFileReader
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileWriter b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileWriter
deleted file mode 100644
index bb74df7..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.MidiFileWriter
+++ /dev/null
@@ -1,2 +0,0 @@
-# Providers for Midi file writing
-com.sun.media.sound.StandardMidiFileWriter
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.SoundbankReader b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.SoundbankReader
deleted file mode 100644
index 03c3df8..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.midi.spi.SoundbankReader
+++ /dev/null
@@ -1,5 +0,0 @@
-# Providers for Soundbanks
-com.sun.media.sound.SF2SoundbankReader
-com.sun.media.sound.DLSSoundbankReader
-com.sun.media.sound.AudioFileSoundbankReader
-com.sun.media.sound.JARSoundbankReader
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader
deleted file mode 100644
index f0536e7..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader
+++ /dev/null
@@ -1,7 +0,0 @@
-# Providers for audio file reading
-com.sun.media.sound.AuFileReader
-com.sun.media.sound.AiffFileReader
-com.sun.media.sound.WaveFileReader
-com.sun.media.sound.WaveFloatFileReader
-com.sun.media.sound.WaveExtensibleFileReader
-com.sun.media.sound.SoftMidiAudioFileReader
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter
deleted file mode 100644
index 83ac2b9..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter
+++ /dev/null
@@ -1,5 +0,0 @@
-# Providers for writing audio files
-com.sun.media.sound.AuFileWriter
-com.sun.media.sound.AiffFileWriter
-com.sun.media.sound.WaveFileWriter
-com.sun.media.sound.WaveFloatFileWriter
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.FormatConversionProvider b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.FormatConversionProvider
deleted file mode 100644
index a92a602..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.FormatConversionProvider
+++ /dev/null
@@ -1,5 +0,0 @@
-# Providers for FormatConversion
-com.sun.media.sound.AudioFloatFormatConverter
-com.sun.media.sound.UlawCodec
-com.sun.media.sound.AlawCodec
-com.sun.media.sound.PCMtoPCMCodec
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.MixerProvider b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.MixerProvider
deleted file mode 100644
index 5414bee..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.MixerProvider
+++ /dev/null
@@ -1,3 +0,0 @@
-# last mixer is default mixer
-com.sun.media.sound.PortMixerProvider
-com.sun.media.sound.DirectAudioDeviceProvider
diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/sun.datatransfer.DesktopDatatransferService b/jdk/src/java.desktop/share/classes/META-INF/services/sun.datatransfer.DesktopDatatransferService
deleted file mode 100644
index 7d763de..0000000
--- a/jdk/src/java.desktop/share/classes/META-INF/services/sun.datatransfer.DesktopDatatransferService
+++ /dev/null
@@ -1 +0,0 @@
-sun.awt.datatransfer.DesktopDatatransferServiceImpl
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
index bc2e752..984bf8a 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/ConstructorFinder.java
@@ -72,6 +72,9 @@
         if (type.isInterface()) {
             throw new NoSuchMethodException("Interface does not contain constructors");
         }
+        if (!FinderUtils.isExported(type)) {
+            throw new NoSuchMethodException("Class is not accessible");
+        }
         if (Modifier.isAbstract(type.getModifiers())) {
             throw new NoSuchMethodException("Abstract class cannot be instantiated");
         }
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FieldFinder.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FieldFinder.java
index eb8b5bb..5a4766d 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FieldFinder.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FieldFinder.java
@@ -54,6 +54,9 @@
         if (name == null) {
             throw new IllegalArgumentException("Field name is not set");
         }
+        if (!FinderUtils.isExported(type)) {
+            throw new NoSuchFieldException("Field '" + name + "' is not accessible");
+        }
         Field field = type.getField(name);
         if (!Modifier.isPublic(field.getModifiers())) {
             throw new NoSuchFieldException("Field '" + name + "' is not public");
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FinderUtils.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FinderUtils.java
new file mode 100644
index 0000000..27da02a
--- /dev/null
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/FinderUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.beans.finder;
+
+/**
+ * Defines utility methods for use by finders.
+ */
+
+final class FinderUtils {
+    private FinderUtils() { }
+
+    /**
+     * Returns true if the given class is an exported package.
+     */
+    public static boolean isExported(Class<?> c) {
+        String pn = packageName(c);
+        return c.getModule().isExported(pn);
+    }
+
+    private static String packageName(Class<?> c) {
+        if (c.isArray()) {
+            return packageName(c.getComponentType());
+        } else {
+            String name = c.getName();
+            int dot = name.lastIndexOf('.');
+            if (dot == -1) return "";
+            return name.substring(0, dot);
+        }
+    }
+}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java
index a10a1e7..eafc216c 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/finder/MethodFinder.java
@@ -134,6 +134,10 @@
      */
     public static Method findAccessibleMethod(Method method) throws NoSuchMethodException {
         Class<?> type = method.getDeclaringClass();
+
+        if (!FinderUtils.isExported(type)) {
+            throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
+        }
         if (Modifier.isPublic(type.getModifiers()) && isPackageAccessible(type)) {
             return method;
         }
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
index 30c4981..a5f024a 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
@@ -88,7 +88,8 @@
                     try {
                         Class<?> c = Class.forName(line.trim(), false, ucl);
                         if (Soundbank.class.isAssignableFrom(c)) {
-                            Object o = ReflectUtil.newInstance(c);
+                            ReflectUtil.checkPackageAccess(c);
+                            Object o = c.newInstance();
                             soundbanks.add((Soundbank) o);
                         }
                     } catch (ClassNotFoundException ignored) {
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java
index 663c5f9..a01b906 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java
@@ -8696,6 +8696,7 @@
      * the Swing package private method {@code compWriteObjectNotify}.
      */
     private void doSwingSerialization() {
+        @SuppressWarnings("deprecation")
         Package swingPackage = Package.getPackage("javax.swing");
         // For Swing serialization to correctly work Swing needs to
         // be notified before Component does it's serialization.  This
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
index 663a6c7..9e7646f 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
@@ -56,7 +56,6 @@
 import sun.awt.HeadlessToolkit;
 import sun.awt.PeerEvent;
 import sun.awt.SunToolkit;
-import sun.util.CoreResourceBundleControl;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -464,7 +463,8 @@
      */
     private static void fallbackToLoadClassForAT(String atName) {
         try {
-            Class.forName(atName, false, ClassLoader.getSystemClassLoader()).newInstance();
+            Class<?> c = Class.forName(atName, false, ClassLoader.getSystemClassLoader());
+            c.newInstance();
         } catch (ClassNotFoundException e) {
             newAWTError(e, "Assistive Technology not found: " + atName);
         } catch (InstantiationException e) {
@@ -1373,9 +1373,7 @@
                                  new java.security.PrivilegedAction<Void>() {
             public Void run() {
                 try {
-                    resources =
-                        ResourceBundle.getBundle("sun.awt.resources.awt",
-                                                 CoreResourceBundleControl.getRBControlInstance());
+                    resources = ResourceBundle.getBundle("sun.awt.resources.awt");
                 } catch (MissingResourceException e) {
                     // No resource file; defaults will be used.
                 }
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Window.java b/jdk/src/java.desktop/share/classes/java/awt/Window.java
index 7ac8023..5894ad3 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Window.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java
@@ -2797,7 +2797,12 @@
      */
     @Deprecated
     public void applyResourceBundle(String rbName) {
-        applyResourceBundle(ResourceBundle.getBundle(rbName));
+        // Use the unnamed module from the TCCL or system class loader.
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+        applyResourceBundle(ResourceBundle.getBundle(rbName, cl.getUnnamedModule()));
     }
 
    /*
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
index f9c29cd..5f39ea9 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java
@@ -2452,31 +2452,16 @@
                 locale = Locale.getDefault();
             }
 
-            /**
-             * If an applet supplies an implementation of ImageReader and
-             * resource bundles, then the resource bundle will need to be
-             * accessed via the applet class loader. So first try the context
-             * class loader to locate the resource bundle.
-             * If that throws MissingResourceException, then try the
-             * system class loader.
+            /*
+             * Only the plugin knows the messages that are provided, so we
+             * can always locate the resource bundles from the same loader
+             * as that for the plugin code itself.
              */
-            ClassLoader loader =
-                java.security.AccessController.doPrivileged(
-                   new java.security.PrivilegedAction<ClassLoader>() {
-                      public ClassLoader run() {
-                        return Thread.currentThread().getContextClassLoader();
-                      }
-                });
-
             ResourceBundle bundle = null;
             try {
-                bundle = ResourceBundle.getBundle(baseName, locale, loader);
+                bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
             } catch (MissingResourceException mre) {
-                try {
-                    bundle = ResourceBundle.getBundle(baseName, locale);
-                } catch (MissingResourceException mre1) {
-                    throw new IllegalArgumentException("Bundle not found!");
-                }
+                throw new IllegalArgumentException("Bundle not found!");
             }
 
             String warning = null;
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
index d9b0694..a9a681c 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageWriter.java
@@ -1954,31 +1954,16 @@
                 locale = Locale.getDefault();
             }
 
-            /**
-             * If an applet supplies an implementation of ImageWriter and
-             * resource bundles, then the resource bundle will need to be
-             * accessed via the applet class loader. So first try the context
-             * class loader to locate the resource bundle.
-             * If that throws MissingResourceException, then try the
-             * system class loader.
+            /*
+             * Only the plugin knows the messages that are provided, so we
+             * can always locate the resource bundles from the same loader
+             * as that for the plugin code itself.
              */
-            ClassLoader loader =
-                java.security.AccessController.doPrivileged(
-                   new java.security.PrivilegedAction<ClassLoader>() {
-                      public ClassLoader run() {
-                        return Thread.currentThread().getContextClassLoader();
-                      }
-                });
-
             ResourceBundle bundle = null;
             try {
-                bundle = ResourceBundle.getBundle(baseName, locale, loader);
+                bundle = ResourceBundle.getBundle(baseName, locale, this.getClass().getModule());
             } catch (MissingResourceException mre) {
-                try {
-                    bundle = ResourceBundle.getBundle(baseName, locale);
-                } catch (MissingResourceException mre1) {
-                    throw new IllegalArgumentException("Bundle not found!");
-                }
+                throw new IllegalArgumentException("Bundle not found!");
             }
 
             String warning = null;
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java
index 14646f1..76e28bc 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadata.java
@@ -26,7 +26,11 @@
 package javax.imageio.metadata;
 
 import org.w3c.dom.Node;
+
 import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
  * An abstract class to be extended by objects that represent metadata
@@ -395,45 +399,11 @@
             throw new IllegalArgumentException("Unsupported format name");
         }
         try {
-            Class<?> cls = null;
-            final Object o = this;
-
-            // firstly we try to use classloader used for loading
-            // the IIOMetadata implemantation for this plugin.
-            ClassLoader loader =
-                java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedAction<ClassLoader>() {
-                            public ClassLoader run() {
-                                return o.getClass().getClassLoader();
-                            }
-                        });
-
-            try {
-                cls = Class.forName(formatClassName, true,
-                                    loader);
-            } catch (ClassNotFoundException e) {
-                // we failed to load IIOMetadataFormat class by
-                // using IIOMetadata classloader.Next try is to
-                // use thread context classloader.
-                loader =
-                    java.security.AccessController.doPrivileged(
-                        new java.security.PrivilegedAction<ClassLoader>() {
-                                public ClassLoader run() {
-                                    return Thread.currentThread().getContextClassLoader();
-                                }
-                        });
-                try {
-                    cls = Class.forName(formatClassName, true,
-                                        loader);
-                } catch (ClassNotFoundException e1) {
-                    // finally we try to use system classloader in case
-                    // if we failed to load IIOMetadataFormat implementation
-                    // class above.
-                    cls = Class.forName(formatClassName, true,
-                                        ClassLoader.getSystemClassLoader());
-                }
-            }
-
+            final String className = formatClassName;
+            // Try to load from the module of the IIOMetadata implementation
+            // for this plugin since the IIOMetadataImpl is part of the plugin
+            PrivilegedAction<Class<?>> pa = () -> { return getMetadataFormatClass(className); };
+            Class<?> cls = AccessController.doPrivileged(pa);
             Method meth = cls.getMethod("getInstance");
             return (IIOMetadataFormat) meth.invoke(null);
         } catch (Exception e) {
@@ -442,7 +412,24 @@
             ex.initCause(e);
             throw ex;
         }
+    }
 
+    private Class<?> getMetadataFormatClass(String formatClassName) {
+        Module thisModule = IIOMetadata.class.getModule();
+        Module targetModule = this.getClass().getModule();
+        Class<?> c = Class.forName(targetModule, formatClassName);
+        if (thisModule.equals(targetModule) || c == null) {
+            return c;
+        }
+        if (thisModule.isNamed()) {
+            int i = formatClassName.lastIndexOf(".");
+            String pn = i > 0 ? formatClassName.substring(0, i) : "";
+            if (!targetModule.isExported(pn, thisModule)) {
+                throw new IllegalStateException("Class " + formatClassName +
+                   " in named module must be exported to java.desktop module.");
+            }
+        }
+        return c;
     }
 
     /**
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java
index 736decc..797ecc5 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormat.java
@@ -43,6 +43,12 @@
  * returns an instance of the class.  Commonly, an implementation will
  * construct only a single instance and cache it for future
  * invocations of {@code getInstance}.
+ * <p> In the event that the plugin is provided as part of a named module,
+ * that module must export the package containing the implementation class
+ * to the <pre>java.desktop</pre> module via a qualified export.
+ * An unqualified export is not recommended unless also needed for
+ * some other reason. Failing to export the package will result in
+ * access failure at runtime.
  *
  * <p> The structures that may be described by this class are a subset
  * of those expressible using XML document type definitions (DTDs),
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java
index bec11eb..82df590 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataFormatImpl.java
@@ -956,34 +956,17 @@
         }
 
         /**
-         * If an applet supplies an implementation of IIOMetadataFormat and
-         * resource bundles, then the resource bundle will need to be
-         * accessed via the applet class loader. So first try the context
-         * class loader to locate the resource bundle.
-         * If that throws MissingResourceException, then try the
-         * system class loader.
+         * Per the class documentation, resource bundles, including localized ones
+         * are intended to be delivered by the subclasser - ie supplier of the
+         * metadataformat. For the standard format and all standard plugins that
+         * is the JDK. For 3rd party plugins that they will supply their own.
+         * This includes plugins bundled with applets/applications.
+         * In all cases this means it is sufficient to search for those resource
+         * in the module that is providing the MetadataFormatImpl subclass.
          */
-        ClassLoader loader =
-            java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<ClassLoader>() {
-                   public ClassLoader run() {
-                       return Thread.currentThread().getContextClassLoader();
-                   }
-            });
-
-        ResourceBundle bundle = null;
         try {
-            bundle = ResourceBundle.getBundle(resourceBaseName,
-                                              locale, loader);
-        } catch (MissingResourceException mre) {
-            try {
-                bundle = ResourceBundle.getBundle(resourceBaseName, locale);
-            } catch (MissingResourceException mre1) {
-                return null;
-            }
-        }
-
-        try {
+            ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale,
+                                                            this.getClass().getModule());
             return bundle.getString(key);
         } catch (MissingResourceException e) {
             return null;
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java b/jdk/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java
index 7b433f9..d46711a 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/spi/ImageReaderWriterSpi.java
@@ -28,6 +28,9 @@
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Arrays;
 import java.util.Iterator;
 import javax.imageio.ImageReader;
@@ -587,8 +590,10 @@
             throw new IllegalArgumentException("Unsupported format name");
         }
         try {
-            Class<?> cls = Class.forName(formatClassName, true,
-                                      ClassLoader.getSystemClassLoader());
+            // Try to load from the same location as the module of the SPI
+            final String className = formatClassName;
+            PrivilegedAction<Class<?>> pa = () -> { return getMetadataFormatClass(className); };
+            Class<?> cls = AccessController.doPrivileged(pa);
             Method meth = cls.getMethod("getInstance");
             return (IIOMetadataFormat) meth.invoke(null);
         } catch (Exception e) {
@@ -598,4 +603,22 @@
             throw ex;
         }
     }
+
+    private Class<?> getMetadataFormatClass(String formatClassName) {
+        Module thisModule = ImageReaderWriterSpi.class.getModule();
+        Module targetModule = this.getClass().getModule();
+        Class<?> c = Class.forName(targetModule, formatClassName);
+        if (thisModule.equals(targetModule) || c == null) {
+            return c;
+        }
+        if (thisModule.isNamed()) {
+            int i = formatClassName.lastIndexOf(".");
+            String pn = i > 0 ? formatClassName.substring(0, i) : "";
+            if (!targetModule.isExported(pn, thisModule)) {
+                throw new IllegalStateException("Class " +  formatClassName +
+                  " in named module must be exported to java.desktop module.");
+            }
+        }
+        return c;
+    }
 }
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java
index d529f69..1955407 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java
@@ -30,13 +30,15 @@
 import javax.swing.border.*;
 import javax.swing.event.SwingPropertyChangeSupport;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.lang.reflect.*;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.ResourceBundle;
-import java.util.ResourceBundle.Control;
 import java.util.Locale;
 import java.util.Vector;
 import java.util.MissingResourceException;
@@ -52,7 +54,6 @@
 import sun.reflect.misc.MethodUtil;
 import sun.reflect.misc.ReflectUtil;
 import sun.swing.SwingUtilities2;
-import sun.util.CoreResourceBundleControl;
 
 /**
  * A table of defaults for Swing components.  Applications can set/get
@@ -302,12 +303,12 @@
             for (int i=resourceBundles.size()-1; i >= 0; i--) {
                 String bundleName = resourceBundles.get(i);
                 try {
-                    Control c = CoreResourceBundleControl.getRBControlInstance(bundleName);
                     ResourceBundle b;
-                    if (c != null) {
-                        b = ResourceBundle.getBundle(bundleName, l, c);
+                    if (isDesktopResourceBundle(bundleName)) {
+                        // load resource bundle from java.desktop module
+                        b = ResourceBundle.getBundle(bundleName, l, UIDefaults.class.getModule());
                     } else {
-                        b = ResourceBundle.getBundle(bundleName, l);
+                        b = ResourceBundle.getBundle(bundleName, l, ClassLoader.getSystemClassLoader());
                     }
                     Enumeration<String> keys = b.getKeys();
 
@@ -329,6 +330,30 @@
         return values;
     }
 
+    /*
+     * Test if the specified baseName of the ROOT locale is in java.desktop module.
+     * JDK always defines the resource bundle of the ROOT locale.
+     */
+    private static boolean isDesktopResourceBundle(String baseName) {
+        Module thisModule = UIDefaults.class.getModule();
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?> c = Class.forName(thisModule, baseName);
+                if (c != null) {
+                    return true;
+                } else {
+                    String resourceName = baseName.replace('.', '/') + ".properties";
+                    try (InputStream in = thisModule.getResourceAsStream(resourceName)) {
+                        return in != null;
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                }
+            }
+        });
+    }
+
     /**
      * Sets the value of <code>key</code> to <code>value</code> for all locales.
      * If <code>key</code> is a string and the new value isn't
@@ -767,7 +792,13 @@
                     m = uiClass.getMethod("createUI", new Class<?>[]{JComponent.class});
                     put(uiClass, m);
                 }
-                uiObject = MethodUtil.invoke(m, null, new Object[]{target});
+
+                if (uiClass.getModule() == ComponentUI.class.getModule()) {
+                    // uiClass is a system LAF if it's in java.desktop module
+                    uiObject = m.invoke(null, new Object[]{target});
+                } else {
+                    uiObject = MethodUtil.invoke(m, null, new Object[]{target});
+                }
             }
             catch (NoSuchMethodException e) {
                 getUIError("static createUI() method not found in " + uiClass);
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultFormatter.java b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultFormatter.java
index ee9cda6..12cc4b3 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultFormatter.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultFormatter.java
@@ -31,7 +31,6 @@
 import java.lang.reflect.*;
 import java.text.ParseException;
 import javax.swing.*;
-import javax.swing.text.*;
 
 /**
  * <code>DefaultFormatter</code> formats arbitrary objects. Formatting is done
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java
index 205fda2..c40bdfc 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/ObjectView.java
@@ -24,7 +24,6 @@
  */
 package javax.swing.text.html;
 
-import java.util.Enumeration;
 import java.awt.*;
 import javax.swing.*;
 import javax.swing.text.*;
diff --git a/jdk/src/java.desktop/share/classes/module-info.java b/jdk/src/java.desktop/share/classes/module-info.java
new file mode 100644
index 0000000..78af9bf
--- /dev/null
+++ b/jdk/src/java.desktop/share/classes/module-info.java
@@ -0,0 +1,135 @@
+/*
+ * 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
+ * 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.
+ */
+
+module java.desktop {
+    requires public java.datatransfer;
+    requires public java.xml;
+    requires java.prefs;
+
+    exports java.applet;
+    exports java.awt;
+    exports java.awt.color;
+    exports java.awt.dnd;
+    exports java.awt.event;
+    exports java.awt.font;
+    exports java.awt.geom;
+    exports java.awt.im;
+    exports java.awt.im.spi;
+    exports java.awt.image;
+    exports java.awt.image.renderable;
+    exports java.awt.print;
+    exports java.beans;
+    exports java.beans.beancontext;
+    exports javax.accessibility;
+    exports javax.imageio;
+    exports javax.imageio.event;
+    exports javax.imageio.metadata;
+    exports javax.imageio.plugins.bmp;
+    exports javax.imageio.plugins.jpeg;
+    exports javax.imageio.plugins.tiff;
+    exports javax.imageio.spi;
+    exports javax.imageio.stream;
+    exports javax.print;
+    exports javax.print.attribute;
+    exports javax.print.attribute.standard;
+    exports javax.print.event;
+    exports javax.sound.midi;
+    exports javax.sound.midi.spi;
+    exports javax.sound.sampled;
+    exports javax.sound.sampled.spi;
+    exports javax.swing;
+    exports javax.swing.border;
+    exports javax.swing.colorchooser;
+    exports javax.swing.event;
+    exports javax.swing.filechooser;
+    exports javax.swing.plaf;
+    exports javax.swing.plaf.basic;
+    exports javax.swing.plaf.metal;
+    exports javax.swing.plaf.multi;
+    exports javax.swing.plaf.nimbus;
+    exports javax.swing.plaf.synth;
+    exports javax.swing.table;
+    exports javax.swing.text;
+    exports javax.swing.text.html;
+    exports javax.swing.text.html.parser;
+    exports javax.swing.text.rtf;
+    exports javax.swing.tree;
+    exports javax.swing.undo;
+
+    // qualified exports may be inserted at build time
+    // see make/GensrcModuleInfo.gmk
+    exports sun.awt to
+        jdk.accessibility;
+
+    uses java.awt.im.spi.InputMethodDescriptor;
+    uses javax.accessibility.AccessibilityProvider;
+    uses javax.imageio.spi.ImageInputStreamSpi;
+    uses javax.imageio.spi.ImageOutputStreamSpi;
+    uses javax.imageio.spi.ImageReaderSpi;
+    uses javax.imageio.spi.ImageTranscoderSpi;
+    uses javax.imageio.spi.ImageWriterSpi;
+    uses javax.print.PrintServiceLookup;
+    uses javax.print.StreamPrintServiceFactory;
+    uses javax.sound.midi.spi.MidiDeviceProvider;
+    uses javax.sound.midi.spi.MidiFileReader;
+    uses javax.sound.midi.spi.MidiFileWriter;
+    uses javax.sound.midi.spi.SoundbankReader;
+    uses javax.sound.sampled.spi.AudioFileReader;
+    uses javax.sound.sampled.spi.AudioFileWriter;
+    uses javax.sound.sampled.spi.FormatConversionProvider;
+    uses javax.sound.sampled.spi.MixerProvider;
+
+    provides sun.datatransfer.DesktopDatatransferService with sun.awt.datatransfer.DesktopDatatransferServiceImpl;
+    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.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;
+}
+
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java
index 192c0c8..9faf3b3 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java
@@ -43,7 +43,6 @@
 import sun.awt.AWTSecurityManager;
 import sun.awt.AppContext;
 import sun.awt.AWTPermissions;
-import sun.security.provider.*;
 import sun.security.util.SecurityConstants;
 
 
diff --git a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java
index 39ba273..3aadaa6 100644
--- a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java
+++ b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/TransferableProxy.java
@@ -208,9 +208,11 @@
             classObjs[i] = cl;
         }
         try {
-            return Proxy.getProxyClass(hasNonPublicInterface ?
-                                       nonPublicLoader : classLoader,
-                                       classObjs);
+            @SuppressWarnings("deprecation")
+            Class<?> proxyClass = Proxy.getProxyClass(hasNonPublicInterface ?
+                                                          nonPublicLoader : classLoader,
+                                                      classObjs);
+            return proxyClass;
         } catch (IllegalArgumentException e) {
             throw new ClassNotFoundException(null, e);
         }
diff --git a/jdk/src/java.httpclient/share/classes/module-info.java b/jdk/src/java.httpclient/share/classes/module-info.java
new file mode 100644
index 0000000..eee3f32
--- /dev/null
+++ b/jdk/src/java.httpclient/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.httpclient {
+    requires java.base;
+    exports java.net.http;
+}
+
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java b/jdk/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java
index c3a5197..c0bb90b 100644
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.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
@@ -25,141 +25,155 @@
 
 package java.lang.instrument;
 
-import  java.security.ProtectionDomain;
+import java.lang.reflect.Module;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 
 /*
  * Copyright 2003 Wily Technology, Inc.
  */
 
 /**
- * An agent provides an implementation of this interface in order
- * to transform class files.
- * The transformation occurs before the class is defined by the JVM.
+ * A transformer of class files. An agent registers an implementation of this
+ * interface using the {@link Instrumentation#addTransformer addTransformer}
+ * method so that the transformer's {@link
+ * ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
+ * transform} method is invoked when classes are loaded,
+ * {@link Instrumentation#redefineClasses redefined}, or
+ * {@link Instrumentation#retransformClasses retransformed}. The implementation
+ * should override one of the {@code transform} methods defined here.
+ * Transformers are invoked before the class is defined by the Java virtual
+ * machine.
+ *
+ * <P>
+ * There are two kinds of transformers, determined by the <code>canRetransform</code>
+ * parameter of
+ * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)}:
+ *  <ul>
+ *    <li><i>retransformation capable</i> transformers that were added with
+ *        <code>canRetransform</code> as true
+ *    </li>
+ *    <li><i>retransformation incapable</i> transformers that were added with
+ *        <code>canRetransform</code> as false or where added with
+ *        {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer)}
+ *    </li>
+ *  </ul>
+ *
+ * <P>
+ * Once a transformer has been registered with
+ * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)
+ * addTransformer},
+ * the transformer will be called for every new class definition and every class redefinition.
+ * Retransformation capable transformers will also be called on every class retransformation.
+ * The request for a new class definition is made with
+ * {@link java.lang.ClassLoader#defineClass ClassLoader.defineClass}
+ * or its native equivalents.
+ * The request for a class redefinition is made with
+ * {@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses}
+ * or its native equivalents.
+ * The request for a class retransformation is made with
+ * {@link java.lang.instrument.Instrumentation#retransformClasses Instrumentation.retransformClasses}
+ * or its native equivalents.
+ * The transformer is called during the processing of the request, before the class file bytes
+ * have been verified or applied.
+ * When there are multiple transformers, transformations are composed by chaining the
+ * <code>transform</code> calls.
+ * That is, the byte array returned by one call to <code>transform</code> becomes the input
+ * (via the <code>classfileBuffer</code> parameter) to the next call.
+ *
+ * <P>
+ * Transformations are applied in the following order:
+ *  <ul>
+ *    <li>Retransformation incapable transformers
+ *    </li>
+ *    <li>Retransformation incapable native transformers
+ *    </li>
+ *    <li>Retransformation capable transformers
+ *    </li>
+ *    <li>Retransformation capable native transformers
+ *    </li>
+ *  </ul>
+ *
+ * <P>
+ * For retransformations, the retransformation incapable transformers are not
+ * called, instead the result of the previous transformation is reused.
+ * In all other cases, this method is called.
+ * Within each of these groupings, transformers are called in the order registered.
+ * Native transformers are provided by the <code>ClassFileLoadHook</code> event
+ * in the Java Virtual Machine Tool Interface).
+ *
+ * <P>
+ * The input (via the <code>classfileBuffer</code> parameter) to the first
+ * transformer is:
+ *  <ul>
+ *    <li>for new class definition,
+ *        the bytes passed to <code>ClassLoader.defineClass</code>
+ *    </li>
+ *    <li>for class redefinition,
+ *        <code>definitions.getDefinitionClassFile()</code> where
+ *        <code>definitions</code> is the parameter to
+ *        {@link java.lang.instrument.Instrumentation#redefineClasses
+ *         Instrumentation.redefineClasses}
+ *    </li>
+ *    <li>for class retransformation,
+ *         the bytes passed to the new class definition or, if redefined,
+ *         the last redefinition, with all transformations made by retransformation
+ *         incapable transformers reapplied automatically and unaltered;
+ *         for details see
+ *         {@link java.lang.instrument.Instrumentation#retransformClasses
+ *          Instrumentation.retransformClasses}
+ *    </li>
+ *  </ul>
+ *
+ * <P>
+ * If the implementing method determines that no transformations are needed,
+ * it should return <code>null</code>.
+ * Otherwise, it should create a new <code>byte[]</code> array,
+ * copy the input <code>classfileBuffer</code> into it,
+ * along with all desired transformations, and return the new array.
+ * The input <code>classfileBuffer</code> must not be modified.
+ *
+ * <P>
+ * In the retransform and redefine cases,
+ * the transformer must support the redefinition semantics:
+ * if a class that the transformer changed during initial definition is later
+ * retransformed or redefined, the
+ * transformer must insure that the second class output class file is a legal
+ * redefinition of the first output class file.
+ *
+ * <P>
+ * If the transformer throws an exception (which it doesn't catch),
+ * subsequent transformers will still be called and the load, redefine
+ * or retransform will still be attempted.
+ * Thus, throwing an exception has the same effect as returning <code>null</code>.
+ * To prevent unexpected behavior when unchecked exceptions are generated
+ * in transformer code, a transformer can catch <code>Throwable</code>.
+ * If the transformer believes the <code>classFileBuffer</code> does not
+ * represent a validly formatted class file, it should throw
+ * an <code>IllegalClassFormatException</code>;
+ * while this has the same effect as returning null. it facilitates the
+ * logging or debugging of format corruptions.
+ *
  * <P>
  * Note the term <i>class file</i> is used as defined in section 3.1 of
- * <cite>The Java&trade; Virtual Machine Specification</cite>,
- * to mean a sequence
- * of bytes in class file format, whether or not they reside in a file.
+ * <cite>The Java&trade; Virtual Machine Specification</cite>, to mean a
+ * sequence of bytes in class file format, whether or not they reside in a
+ * file.
  *
  * @see     java.lang.instrument.Instrumentation
- * @see     java.lang.instrument.Instrumentation#addTransformer
- * @see     java.lang.instrument.Instrumentation#removeTransformer
  * @since   1.5
  */
 
 public interface ClassFileTransformer {
+
     /**
-     * The implementation of this method may transform the supplied class file and
-     * return a new replacement class file.
+     * Transforms the given class file and returns a new replacement class file.
+     * This method is invoked when the {@link Module Module} bearing {@link
+     * ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
+     * transform} is not overridden.
      *
-     * <P>
-     * There are two kinds of transformers, determined by the <code>canRetransform</code>
-     * parameter of
-     * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)}:
-     *  <ul>
-     *    <li><i>retransformation capable</i> transformers that were added with
-     *        <code>canRetransform</code> as true
-     *    </li>
-     *    <li><i>retransformation incapable</i> transformers that were added with
-     *        <code>canRetransform</code> as false or where added with
-     *        {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer)}
-     *    </li>
-     *  </ul>
-     *
-     * <P>
-     * Once a transformer has been registered with
-     * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)
-     * addTransformer},
-     * the transformer will be called for every new class definition and every class redefinition.
-     * Retransformation capable transformers will also be called on every class retransformation.
-     * The request for a new class definition is made with
-     * {@link java.lang.ClassLoader#defineClass ClassLoader.defineClass}
-     * or its native equivalents.
-     * The request for a class redefinition is made with
-     * {@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses}
-     * or its native equivalents.
-     * The request for a class retransformation is made with
-     * {@link java.lang.instrument.Instrumentation#retransformClasses Instrumentation.retransformClasses}
-     * or its native equivalents.
-     * The transformer is called during the processing of the request, before the class file bytes
-     * have been verified or applied.
-     * When there are multiple transformers, transformations are composed by chaining the
-     * <code>transform</code> calls.
-     * That is, the byte array returned by one call to <code>transform</code> becomes the input
-     * (via the <code>classfileBuffer</code> parameter) to the next call.
-     *
-     * <P>
-     * Transformations are applied in the following order:
-     *  <ul>
-     *    <li>Retransformation incapable transformers
-     *    </li>
-     *    <li>Retransformation incapable native transformers
-     *    </li>
-     *    <li>Retransformation capable transformers
-     *    </li>
-     *    <li>Retransformation capable native transformers
-     *    </li>
-     *  </ul>
-     *
-     * <P>
-     * For retransformations, the retransformation incapable transformers are not
-     * called, instead the result of the previous transformation is reused.
-     * In all other cases, this method is called.
-     * Within each of these groupings, transformers are called in the order registered.
-     * Native transformers are provided by the <code>ClassFileLoadHook</code> event
-     * in the Java Virtual Machine Tool Interface).
-     *
-     * <P>
-     * The input (via the <code>classfileBuffer</code> parameter) to the first
-     * transformer is:
-     *  <ul>
-     *    <li>for new class definition,
-     *        the bytes passed to <code>ClassLoader.defineClass</code>
-     *    </li>
-     *    <li>for class redefinition,
-     *        <code>definitions.getDefinitionClassFile()</code> where
-     *        <code>definitions</code> is the parameter to
-     *        {@link java.lang.instrument.Instrumentation#redefineClasses
-     *         Instrumentation.redefineClasses}
-     *    </li>
-     *    <li>for class retransformation,
-     *         the bytes passed to the new class definition or, if redefined,
-     *         the last redefinition, with all transformations made by retransformation
-     *         incapable transformers reapplied automatically and unaltered;
-     *         for details see
-     *         {@link java.lang.instrument.Instrumentation#retransformClasses
-     *          Instrumentation.retransformClasses}
-     *    </li>
-     *  </ul>
-     *
-     * <P>
-     * If the implementing method determines that no transformations are needed,
-     * it should return <code>null</code>.
-     * Otherwise, it should create a new <code>byte[]</code> array,
-     * copy the input <code>classfileBuffer</code> into it,
-     * along with all desired transformations, and return the new array.
-     * The input <code>classfileBuffer</code> must not be modified.
-     *
-     * <P>
-     * In the retransform and redefine cases,
-     * the transformer must support the redefinition semantics:
-     * if a class that the transformer changed during initial definition is later
-     * retransformed or redefined, the
-     * transformer must insure that the second class output class file is a legal
-     * redefinition of the first output class file.
-     *
-     * <P>
-     * If the transformer throws an exception (which it doesn't catch),
-     * subsequent transformers will still be called and the load, redefine
-     * or retransform will still be attempted.
-     * Thus, throwing an exception has the same effect as returning <code>null</code>.
-     * To prevent unexpected behavior when unchecked exceptions are generated
-     * in transformer code, a transformer can catch <code>Throwable</code>.
-     * If the transformer believes the <code>classFileBuffer</code> does not
-     * represent a validly formatted class file, it should throw
-     * an <code>IllegalClassFormatException</code>;
-     * while this has the same effect as returning null. it facilitates the
-     * logging or debugging of format corruptions.
+     * @implSpec The default implementation returns null.
      *
      * @param loader                the defining loader of the class to be transformed,
      *                              may be <code>null</code> if the bootstrap loader
@@ -169,20 +183,67 @@
      *                              For example, <code>"java/util/List"</code>.
      * @param classBeingRedefined   if this is triggered by a redefine or retransform,
      *                              the class being redefined or retransformed;
-     *                              if this is a class load, <code>null</code>
+     *                              if this is a class load, {@code null}
      * @param protectionDomain      the protection domain of the class being defined or redefined
      * @param classfileBuffer       the input byte buffer in class file format - must not be modified
      *
-     * @throws IllegalClassFormatException if the input does not represent a well-formed class file
-     * @return  a well-formed class file buffer (the result of the transform),
-                or <code>null</code> if no transform is performed.
-     * @see Instrumentation#redefineClasses
+     * @throws IllegalClassFormatException
+     *         if the input does not represent a well-formed class file
+     * @return a well-formed class file buffer (the result of the transform),
+     *         or {@code null} if no transform is performed
      */
-    byte[]
+    default byte[]
     transform(  ClassLoader         loader,
                 String              className,
                 Class<?>            classBeingRedefined,
                 ProtectionDomain    protectionDomain,
                 byte[]              classfileBuffer)
-        throws IllegalClassFormatException;
+        throws IllegalClassFormatException {
+        return null;
+    }
+
+
+    /**
+     * Transforms the given class file and returns a new replacement class file.
+     *
+     * @implSpec The default implementation of this method invokes the
+     * {@link #transform(ClassLoader,String,Class,ProtectionDomain,byte[]) transform}
+     * method with the {@link Module#getClassLoader() ClassLoader} for the module.
+     *
+     * @param module                the module of the class to be transformed
+     * @param className             the name of the class in the internal form of fully
+     *                              qualified class and interface names as defined in
+     *                              <i>The Java Virtual Machine Specification</i>.
+     *                              For example, <code>"java/util/List"</code>.
+     * @param classBeingRedefined   if this is triggered by a redefine or retransform,
+     *                              the class being redefined or retransformed;
+     *                              if this is a class load, {@code null}
+     * @param protectionDomain      the protection domain of the class being defined or redefined
+     * @param classfileBuffer       the input byte buffer in class file format - must not be modified
+     *
+     * @throws IllegalClassFormatException
+     *         if the input does not represent a well-formed class file
+     * @return a well-formed class file buffer (the result of the transform),
+     *         or {@code null} if no transform is performed
+     *
+     * @since  9
+     */
+    default byte[]
+    transform(  Module              module,
+                String              className,
+                Class<?>            classBeingRedefined,
+                ProtectionDomain    protectionDomain,
+                byte[]              classfileBuffer)
+        throws IllegalClassFormatException {
+
+        PrivilegedAction<ClassLoader> pa = module::getClassLoader;
+        ClassLoader loader = AccessController.doPrivileged(pa);
+
+        // invoke the legacy transform method
+        return transform(loader,
+                         className,
+                         classBeingRedefined,
+                         protectionDomain,
+                         classfileBuffer);
+    }
 }
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 bedb780..44b0aa3 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -25,9 +25,9 @@
 
 package java.lang.instrument;
 
-import  java.io.File;
-import  java.io.IOException;
-import  java.util.jar.JarFile;
+import java.lang.reflect.Module;
+import java.security.ProtectionDomain;
+import java.util.jar.JarFile;
 
 /*
  * Copyright 2003 Wily Technology, Inc.
@@ -74,9 +74,8 @@
      * The transformer is called when classes are loaded, when they are
      * {@linkplain #redefineClasses redefined}. and if <code>canRetransform</code> is true,
      * when they are {@linkplain #retransformClasses retransformed}.
-     * See {@link java.lang.instrument.ClassFileTransformer#transform
-     * ClassFileTransformer.transform} for the order
-     * of transform calls.
+     * {@link ClassFileTransformer} defines the order of transform calls.
+     *
      * If a transformer throws
      * an exception during execution, the JVM will still call the other registered
      * transformers in order. The same transformer may be added more than once,
@@ -163,18 +162,16 @@
      *    </li>
      *    <li>for each transformer that was added with <code>canRetransform</code>
      *      false, the bytes returned by
-     *      {@link java.lang.instrument.ClassFileTransformer#transform transform}
-     *      during the last class load or redefine are
+     *      {@link ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
+     *      transform} during the last class load or redefine are
      *      reused as the output of the transformation; note that this is
      *      equivalent to reapplying the previous transformation, unaltered;
-     *      except that
-     *      {@link java.lang.instrument.ClassFileTransformer#transform transform}
-     *      is not called
+     *      except that {@code transform} method is not called.
      *    </li>
      *    <li>for each transformer that was added with <code>canRetransform</code>
      *      true, the
-     *      {@link java.lang.instrument.ClassFileTransformer#transform transform}
-     *      method is called in these transformers
+     *      {@link ClassFileTransformer#transform(Module,String,Class,ProtectionDomain,byte[])
+     *      transform} method is called in these transformers
      *    </li>
      *    <li>the transformed class file bytes are installed as the new
      *      definition of the class
@@ -182,10 +179,9 @@
      *  </ul>
      * <P>
      *
-     * The order of transformation is described in the
-     * {@link java.lang.instrument.ClassFileTransformer#transform transform} method.
-     * This same order is used in the automatic reapplication of retransformation
-     * incapable transforms.
+     * The order of transformation is described in {@link ClassFileTransformer}.
+     * This same order is used in the automatic reapplication of
+     * retransformation incapable transforms.
      * <P>
      *
      * The initial class file bytes represent the bytes passed to
@@ -662,4 +658,21 @@
      */
     void
     setNativeMethodPrefix(ClassFileTransformer transformer, String prefix);
+
+    /**
+     * Updates a module to read another module.
+     *
+     * 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}.
+     *
+     * @param module the module to update
+     * @param other the module to read
+     * @throws NullPointerException if either module is {@code null}
+     *
+     * @since 9
+     * @see Module#canRead(Module)
+     */
+    void addModuleReads(Module module, Module other);
 }
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 6c6e380..9b1b02e 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
@@ -1,5 +1,5 @@
 <!--
- Copyright (c) 2003, 2014, 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
@@ -267,6 +267,24 @@
 the <code>Agent-Class</code> attribute specifies the name of the agent class
 (the value of <code>Premain-Class</code> attribute is ignored).
 
+
+<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
+transformed classes to read the unnamed module of both class loaders.
+
+
 <h2>Related Documentation</h2>
 
 For tool documentation, please see:
diff --git a/jdk/src/java.instrument/share/classes/module-info.java b/jdk/src/java.instrument/share/classes/module-info.java
new file mode 100644
index 0000000..3eb704c
--- /dev/null
+++ b/jdk/src/java.instrument/share/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.instrument {
+    exports java.lang.instrument;
+}
+
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 3b36a87..e671fec 100644
--- a/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
+++ b/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 package sun.instrument;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Module;
 import java.lang.reflect.AccessibleObject;
 
 import java.lang.instrument.ClassFileTransformer;
@@ -37,6 +38,7 @@
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 
+import java.util.Objects;
 import java.util.jar.JarFile;
 
 /*
@@ -225,6 +227,14 @@
         setNativeMethodPrefixes(mNativeAgent, prefixes, mgr.isRetransformable());
     }
 
+    @Override
+    public void addModuleReads(Module module, Module other) {
+        Objects.requireNonNull(module);
+        Objects.requireNonNull(other);
+        jdk.internal.module.Modules.addReads(module, other);
+    }
+
+
     private TransformerManager
     findTransformerManager(ClassFileTransformer transformer) {
         if (mTransformerManager.includesTransformer(transformer)) {
@@ -387,9 +397,6 @@
         } else {
             m.invoke(null, new Object[] { optionsString });
         }
-
-        // don't let others access a non-public premain method
-        setAccessible(m, false);
     }
 
     // WARNING: the native code knows the name & signature of this method
@@ -414,6 +421,7 @@
     // WARNING: the native code knows the name & signature of this method
     private byte[]
     transform(  ClassLoader         loader,
+                Module              module,
                 String              classname,
                 Class<?>            classBeingRedefined,
                 ProtectionDomain    protectionDomain,
@@ -422,10 +430,19 @@
         TransformerManager mgr = isRetransformer?
                                         mRetransfomableTransformerManager :
                                         mTransformerManager;
+        // module is null when not a class load or when loading a class in an
+        // unnamed module and this is the first type to be loaded in the package.
+        if (module == null) {
+            if (classBeingRedefined != null) {
+                module = classBeingRedefined.getModule();
+            } else {
+                module = loader.getUnnamedModule();
+            }
+        }
         if (mgr == null) {
             return null; // no manager, no transform
         } else {
-            return mgr.transform(   loader,
+            return mgr.transform(   module,
                                     classname,
                                     classBeingRedefined,
                                     protectionDomain,
diff --git a/jdk/src/java.instrument/share/classes/sun/instrument/TransformerManager.java b/jdk/src/java.instrument/share/classes/sun/instrument/TransformerManager.java
index 570617c..310f036 100644
--- a/jdk/src/java.instrument/share/classes/sun/instrument/TransformerManager.java
+++ b/jdk/src/java.instrument/share/classes/sun/instrument/TransformerManager.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
@@ -28,6 +28,7 @@
 
 import java.lang.instrument.Instrumentation;
 import java.lang.instrument.ClassFileTransformer;
+import java.lang.reflect.Module;
 import java.security.ProtectionDomain;
 
 /*
@@ -167,7 +168,7 @@
     }
 
     public byte[]
-    transform(  ClassLoader         loader,
+    transform(  Module              module,
                 String              classname,
                 Class<?>            classBeingRedefined,
                 ProtectionDomain    protectionDomain,
@@ -185,7 +186,7 @@
             byte[]                  transformedBytes = null;
 
             try {
-                transformedBytes = transformer.transform(   loader,
+                transformedBytes = transformer.transform(   module,
                                                             classname,
                                                             classBeingRedefined,
                                                             protectionDomain,
diff --git a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c
index d7dfe26..b3936cb 100644
--- a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c
+++ b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.c
@@ -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
@@ -28,6 +28,7 @@
  */
 
 #include    <jni.h>
+#include    <jvm.h>
 #include    <jvmti.h>
 #include    <stdlib.h>
 #include    <string.h>
@@ -769,6 +770,36 @@
     }
 }
 
+static jobject
+getModuleObject(JNIEnv *                jnienv,
+                jobject                 loaderObject,
+                const char*             cname) {
+    jboolean errorOutstanding = JNI_FALSE;
+    jobject moduleObject = NULL;
+    jstring package = NULL;
+
+    /* find last slash in the class name */
+    char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/');
+    int len = (last_slash == NULL) ? 0 : (int)(last_slash - cname);
+    char* pkg_name_buf = (char*)malloc(len + 1);
+
+    jplis_assert_msg(pkg_name_buf != NULL, "OOM error in native tmp buffer allocation");
+    if (last_slash != NULL) {
+        strncpy(pkg_name_buf, cname, len);
+    }
+    pkg_name_buf[len] = '\0';
+
+    package = (*jnienv)->NewStringUTF(jnienv, pkg_name_buf);
+    jplis_assert_msg(package != NULL, "OOM error in NewStringUTF");
+
+    moduleObject = JVM_GetModuleByPackageName(jnienv, loaderObject, package);
+
+    errorOutstanding = checkForAndClearThrowable(jnienv);
+    jplis_assert_msg(!errorOutstanding,
+                     "error in lookup of a module of the class being instrumented");
+    free((void*)pkg_name_buf);
+    return moduleObject;
+}
 
 /*
  *  Support for the JVMTI callbacks
@@ -810,7 +841,7 @@
             classFileBufferObject = (*jnienv)->NewByteArray(jnienv,
                                                             class_data_len);
             errorOutstanding = checkForAndClearThrowable(jnienv);
-            jplis_assert_msg(!errorOutstanding, "can't create byte arrau");
+            jplis_assert_msg(!errorOutstanding, "can't create byte array");
         }
 
         if ( !errorOutstanding ) {
@@ -828,6 +859,14 @@
         /*  now call the JPL agents to do the transforming */
         /*  potential future optimization: may want to skip this if there are none */
         if ( !errorOutstanding ) {
+            jobject moduleObject = NULL;
+
+            if (classBeingRedefined == NULL) {
+                moduleObject = getModuleObject(jnienv, loaderObject, name);
+            } else {
+                // Redefine or retransform, InstrumentationImpl.transform() will use
+                // classBeingRedefined.getModule() to get the module.
+            }
             jplis_assert(agent->mInstrumentationImpl != NULL);
             jplis_assert(agent->mTransform != NULL);
             transformedBufferObject = (*jnienv)->CallObjectMethod(
@@ -835,6 +874,7 @@
                                                 agent->mInstrumentationImpl,
                                                 agent->mTransform,
                                                 loaderObject,
+                                                moduleObject,
                                                 classNameStringObject,
                                                 classBeingRedefined,
                                                 protectionDomain,
diff --git a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h
index 03abfe6..3c70554 100644
--- a/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h
+++ b/jdk/src/java.instrument/share/native/libinstrument/JPLISAgent.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, 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
@@ -66,7 +66,7 @@
 #define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V"
 #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME           "transform"
 #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE      \
-    "(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B"
+    "(Ljava/lang/ClassLoader;Ljava/lang/reflect/Module;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B"
 
 
 /*
diff --git a/jdk/src/java.logging/share/classes/META-INF/services/jdk.internal.logger.DefaultLoggerFinder b/jdk/src/java.logging/share/classes/META-INF/services/jdk.internal.logger.DefaultLoggerFinder
deleted file mode 100644
index d35467b..0000000
--- a/jdk/src/java.logging/share/classes/META-INF/services/jdk.internal.logger.DefaultLoggerFinder
+++ /dev/null
@@ -1 +0,0 @@
-sun.util.logging.internal.LoggingProviderImpl
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 8f2d3e7..fa0da4c 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
@@ -24,6 +24,7 @@
  */
 
 package java.util.logging;
+import java.lang.reflect.Module;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -262,9 +263,13 @@
     }
 
     private String computeLocalizedLevelName(Locale newLocale) {
-        ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName, newLocale);
-        final String localizedName = rb.getString(name);
+        // Resource bundle should be loaded from the defining module
+        // 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, newLocale, module);
 
+        final String localizedName = rb.getString(name);
         final boolean isDefaultBundle = defaultBundle.equals(resourceBundleName);
         if (!isDefaultBundle) return localizedName;
 
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 48210ef..07b06fd 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 package java.util.logging;
 
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Module;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -254,6 +255,9 @@
     private static final LoggerBundle NO_RESOURCE_BUNDLE =
             new LoggerBundle(null, null);
 
+    private static final RuntimePermission GET_CLASS_LOADER_PERMISSION =
+            new RuntimePermission("getClassLoader");
+
     private volatile LogManager manager;
     private String name;
     private final CopyOnWriteArrayList<Handler> handlers =
@@ -277,7 +281,7 @@
     private ArrayList<LogManager.LoggerWeakRef> kids;   // WeakReferences to loggers that have us as parent
     private volatile Level levelObject;
     private volatile int levelValue;  // current effective level value
-    private WeakReference<ClassLoader> callersClassLoaderRef;
+    private WeakReference<Module> callerModuleRef;
     private final boolean isSystemLogger;
 
     /**
@@ -383,18 +387,18 @@
         levelValue = Level.INFO.intValue();
     }
 
-    private void setCallersClassLoaderRef(Class<?> caller) {
-        ClassLoader callersClassLoader = ((caller != null)
-                                         ? caller.getClassLoader()
-                                         : null);
-        if (callersClassLoader != null) {
-            this.callersClassLoaderRef = new WeakReference<>(callersClassLoader);
+    private void setCallerModuleRef(Class<?> caller) {
+        Module callerModule = ((caller != null)
+                                        ? caller.getModule()
+                                        : null);
+        if (callerModule != null) {
+            this.callerModuleRef = new WeakReference<>(callerModule);
         }
     }
 
-    private ClassLoader getCallersClassLoader() {
-        return (callersClassLoaderRef != null)
-                ? callersClassLoaderRef.get()
+    private Module getCallerModule() {
+        return (callerModuleRef != null)
+                ? callerModuleRef.get()
                 : null;
     }
 
@@ -522,6 +526,7 @@
      * Find or create a logger for a named subsystem.  If a logger has
      * already been created with the given name it is returned.  Otherwise
      * a new logger is created.
+     *
      * <p>
      * If a new logger is created its log level will be configured
      * based on the LogManager and it will configured to also send logging
@@ -539,7 +544,7 @@
      * <p>
      * If the named Logger already exists and does not yet have a
      * localization resource bundle then the given resource bundle
-     * name is used.  If the named Logger already exists and has
+     * name is used. If the named Logger already exists and has
      * a different resource bundle name then an IllegalArgumentException
      * is thrown.
      *
@@ -1919,22 +1924,6 @@
         return useParentHandlers;
     }
 
-    private static ResourceBundle findSystemResourceBundle(final Locale locale) {
-        // the resource bundle is in a restricted package
-        return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
-            @Override
-            public ResourceBundle run() {
-                try {
-                    return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
-                                                    locale,
-                                                    ClassLoader.getSystemClassLoader());
-                } catch (MissingResourceException e) {
-                    throw new InternalError(e.toString());
-                }
-            }
-        });
-    }
-
     /**
      * Private utility method to map a resource bundle name to an
      * actual resource bundle, using a simple one-entry cache.
@@ -1943,17 +1932,29 @@
      * there is no suitable previous cached value.
      *
      * @param name the ResourceBundle to locate
-     * @param userCallersClassLoader if true search using the caller's ClassLoader
+     * @param useCallersModule if true search using the caller's module.
      * @return ResourceBundle specified by name or null if not found
      */
     private synchronized ResourceBundle findResourceBundle(String name,
-                                                           boolean useCallersClassLoader) {
-        // For all lookups, we first check the thread context class loader
-        // if it is set.  If not, we use the system classloader.  If we
-        // still haven't found it we use the callersClassLoaderRef if it
-        // is set and useCallersClassLoader is true.  We set
-        // callersClassLoaderRef initially upon creating the logger with a
-        // non-null resource bundle name.
+                                                           boolean useCallersModule) {
+        // When this method is called from logrb, useCallersModule==false, and
+        // the resource bundle 'name' is the argument provided to logrb.
+        // It may, or may not be, equal to lb.resourceBundleName.
+        // Otherwise, useCallersModule==true, and name is the resource bundle
+        // name that is set (or will be set) in this logger.
+        //
+        // When useCallersModule is false, or when the caller's module is
+        // null, or when the caller's module is an unnamed module, we look
+        // first in the TCCL (or the System ClassLoader if the TCCL is null)
+        // to locate the resource bundle.
+        //
+        // Otherwise, if useCallersModule is true, and the caller's module is not
+        // null, and the caller's module is named, we look in the caller's module
+        // to locate the resource bundle.
+        //
+        // Finally, if the caller's module is not null and is unnamed, and
+        // useCallersModule is true, we look in the caller's module class loader
+        // (unless we already looked there in step 1).
 
         // Return a null bundle for a null name.
         if (name == null) {
@@ -1972,59 +1973,87 @@
             return catalog;
         }
 
-        if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
-            catalog = findSystemResourceBundle(currentLocale);
-            catalogName = name;
-            catalogLocale = currentLocale;
-            return catalog;
-        }
-
         // Use the thread's context ClassLoader.  If there isn't one, use the
         // {@linkplain java.lang.ClassLoader#getSystemClassLoader() system ClassLoader}.
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         if (cl == null) {
             cl = ClassLoader.getSystemClassLoader();
         }
-        try {
-            catalog = ResourceBundle.getBundle(name, currentLocale, cl);
-            catalogName = name;
-            catalogLocale = currentLocale;
-            return catalog;
-        } catch (MissingResourceException ex) {
-            // We can't find the ResourceBundle in the default
-            // ClassLoader.  Drop through.
-        }
 
-        if (useCallersClassLoader) {
-            // Try with the caller's ClassLoader
-            ClassLoader callersClassLoader = getCallersClassLoader();
+        final Module callerModule = getCallerModule();
 
-            if (callersClassLoader == null || callersClassLoader == cl) {
-                return null;
-            }
-
+        // If useCallersModule is false, we are called by logrb, with a name
+        // that is provided by the user. In that case we will look in the TCCL.
+        // We also look in the TCCL if callerModule is null or unnamed.
+        if (!useCallersModule || callerModule == null || !callerModule.isNamed()) {
             try {
-                catalog = ResourceBundle.getBundle(name, currentLocale,
-                                                   callersClassLoader);
+                Module mod = cl.getUnnamedModule();
+                PrivilegedAction<ResourceBundle> pa = () ->
+                    ResourceBundle.getBundle(name, currentLocale, mod);
+                catalog = AccessController.doPrivileged(pa, null, GET_CLASS_LOADER_PERMISSION);
+                catalogName = name;
+                catalogLocale = currentLocale;
+                return catalog;
+            } catch (MissingResourceException ex) {
+                // We can't find the ResourceBundle in the default
+                // ClassLoader.  Drop through.
+                if (useCallersModule && callerModule != null) {
+                    try {
+                        // We are called by an unnamed module: try with the
+                        // unnamed module class loader:
+                        PrivilegedAction<ClassLoader> getModuleClassLoader =
+                                () -> callerModule.getClassLoader();
+                        ClassLoader moduleCL =
+                                AccessController.doPrivileged(getModuleClassLoader);
+                        // moduleCL can be null if the logger is created by a class
+                        // appended to the bootclasspath.
+                        // If moduleCL is null we would use cl, but we already tried
+                        // that above (we first looked in the TCCL for unnamed
+                        // caller modules) - so there no point in trying again: we
+                        // won't find anything more this second time.
+                        // In this case just return null.
+                        if (moduleCL == cl || moduleCL == null) return null;
+
+                        // we already tried the TCCL and found nothing - so try
+                        // with the module's loader this time.
+                        catalog = ResourceBundle.getBundle(name, currentLocale,
+                                                           moduleCL);
+                        catalogName = name;
+                        catalogLocale = currentLocale;
+                        return catalog;
+                    } catch (MissingResourceException x) {
+                        return null; // no luck
+                    }
+                } else {
+                    return null;
+                }
+            }
+        } else {
+            // we should have:
+            //  useCallersModule && callerModule != null && callerModule.isNamed();
+            // 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);
                 catalogName = name;
                 catalogLocale = currentLocale;
                 return catalog;
             } catch (MissingResourceException ex) {
                 return null; // no luck
             }
-        } else {
-            return null;
         }
     }
 
     // Private utility method to initialize our one entry
-    // resource bundle name cache and the callers ClassLoader
+    // resource bundle name cache and the callers Module
     // Note: for consistency reasons, we are careful to check
     // that a suitable ResourceBundle exists before setting the
     // resourceBundleName field.
     // Synchronized to prevent races in setting the fields.
     private synchronized void setupResourceInfo(String name,
-                                                Class<?> callersClass) {
+                                                Class<?> callerClass) {
         final LoggerBundle lb = loggerBundle;
         if (lb.resourceBundleName != null) {
             // this Logger already has a ResourceBundle
@@ -2043,22 +2072,26 @@
             return;
         }
 
-        setCallersClassLoaderRef(callersClass);
-        if (isSystemLogger && getCallersClassLoader() != null) {
+        setCallerModuleRef(callerClass);
+        if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) {
             checkPermission();
         }
-        if (findResourceBundle(name, true) == null) {
-            // We've failed to find an expected ResourceBundle.
-            // unset the caller's ClassLoader since we were unable to find the
-            // the bundle using it
-            this.callersClassLoaderRef = null;
-            throw new MissingResourceException("Can't find " + name + " bundle",
-                                                name, "");
-        }
 
-        // if lb.userBundle is not null we won't reach this line.
-        assert lb.userBundle == null;
-        loggerBundle = LoggerBundle.get(name, null);
+        if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
+            loggerBundle = SYSTEM_BUNDLE;
+        } else {
+            ResourceBundle bundle = findResourceBundle(name, true);
+            if (bundle == null) {
+                // We've failed to find an expected ResourceBundle.
+                // unset the caller's module since we were unable to find the
+                // the bundle using it
+                this.callerModuleRef = null;
+                throw new MissingResourceException("Can't find " + name + " bundle from ",
+                        name, "");
+            }
+
+            loggerBundle = LoggerBundle.get(name, null);
+        }
     }
 
     /**
diff --git a/jdk/src/java.logging/share/classes/module-info.java b/jdk/src/java.logging/share/classes/module-info.java
new file mode 100644
index 0000000..47456e5
--- /dev/null
+++ b/jdk/src/java.logging/share/classes/module-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.logging {
+    exports java.util.logging;
+    provides jdk.internal.logger.DefaultLoggerFinder with
+        sun.util.logging.internal.LoggingProviderImpl;
+}
+
diff --git a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java
index 5fdcd54..cbf32ee 100644
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java
+++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java
@@ -43,6 +43,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
 import java.lang.reflect.Proxy;
 import java.net.MalformedURLException;
 import java.rmi.MarshalledObject;
@@ -100,6 +101,7 @@
 import javax.naming.NamingException;
 import javax.rmi.ssl.SslRMIClientSocketFactory;
 import javax.security.auth.Subject;
+import jdk.internal.module.Modules;
 import sun.reflect.misc.ReflectUtil;
 import sun.rmi.server.UnicastRef2;
 import sun.rmi.transport.LiveRef;
@@ -1956,21 +1958,22 @@
             RMIConnection.class.getName() + "Impl_Stub";
     private static final Class<?> rmiConnectionImplStubClass;
     private static final String pRefClassName =
-        "com.sun.jmx.remote.internal.PRef";
+        "jdk.jmx.remote.internal.PRef";
     private static final Constructor<?> proxyRefConstructor;
     static {
         final String pRefByteCodeString =
-                "\312\376\272\276\0\0\0.\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17\0"+
-                "\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/RemoteRef;"+
-                ")V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/reflec"+
-                "t/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12Exception"+
-                "s\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1\0\40com/"+
-                "sun/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/internal/Pr"+
-                "oxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rmi/serve"+
-                "r/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5\0\0\0\0"+
-                "\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261"+
-                "\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0\6\0\0\0\17*\264\0"+
-                "\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0\4\0\1\0\14\0\0";
+                "\312\376\272\276\0\0\0\60\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
+                "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
+                "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
+                "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
+                "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
+                "\0\34jdk/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/inter"+
+                "nal/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rm"+
+                "i/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5"+
+                "\0\0\0\0\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0\6*+\267"+
+                "\0\1\261\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0\6\0\0\0"+
+                "\17*\264\0\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0\4\0\1\0"+
+                "\14\0\0";
         final byte[] pRefByteCode =
                 NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
         PrivilegedExceptionAction<Constructor<?>> action =
@@ -1980,13 +1983,34 @@
                 ClassLoader thisLoader = thisClass.getClassLoader();
                 ProtectionDomain thisProtectionDomain =
                         thisClass.getProtectionDomain();
-                String[] otherClassNames = {ProxyRef.class.getName()};
+
+                String proxyRefCName = ProxyRef.class.getName();
                 ClassLoader cl =
                         new NoCallStackClassLoader(pRefClassName,
                         pRefByteCode,
-                        otherClassNames,
+                        new String[] { proxyRefCName },
                         thisLoader,
                         thisProtectionDomain);
+
+                Module jmxModule = ProxyRef.class.getModule();
+                Module rmiModule = RemoteRef.class.getModule();
+
+                String pkg = packageOf(pRefClassName);
+                assert pkg != null && pkg.length() > 0 && !pkg.equals(packageOf(proxyRefCName));
+                Module m = Modules.defineModule(cl, "jdk.remoteref", Collections.singleton(pkg));
+
+                // jdk.remoteref needs to read to java.base and jmxModule
+                Modules.addReads(m, Object.class.getModule());
+                Modules.addReads(m, jmxModule);
+                Modules.addReads(m, rmiModule);
+
+                // jdk.remoteref needs access to ProxyRef class
+                Modules.addExports(jmxModule, packageOf(proxyRefCName), m);
+
+                // java.management needs to instantiate the fabricated RemoteRef class
+                Modules.addReads(jmxModule, m);
+                Modules.addExports(m, pkg, jmxModule);
+
                 Class<?> c = cl.loadClass(pRefClassName);
                 return c.getConstructor(RemoteRef.class);
             }
@@ -2021,6 +2045,11 @@
         proxyRefConstructor = constr;
     }
 
+    private static String packageOf(String cn) {
+        int i = cn.lastIndexOf('.');
+        return i > 0 ? cn.substring(0, i) : "";
+    }
+
     private static RMIConnection shadowJrmpStub(RemoteObject stub)
     throws InstantiationException, IllegalAccessException,
             InvocationTargetException, ClassNotFoundException,
diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java
new file mode 100644
index 0000000..8f7bd1b
--- /dev/null
+++ b/jdk/src/java.management/share/classes/module-info.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.management {
+    requires public java.rmi;
+    requires java.logging;
+    requires java.naming;
+
+    exports java.lang.management;
+    exports javax.management;
+    exports javax.management.loading;
+    exports javax.management.modelmbean;
+    exports javax.management.monitor;
+    exports javax.management.openmbean;
+    exports javax.management.relation;
+    exports javax.management.remote;
+    exports javax.management.remote.rmi;
+    exports javax.management.timer;
+    exports sun.management to jdk.jconsole, jdk.management;
+    exports sun.management.spi to jdk.management;
+
+    uses javax.management.remote.JMXConnectorProvider;
+    uses javax.management.remote.JMXConnectorServerProvider;
+    uses sun.management.spi.PlatformMBeanProvider;
+
+    provides javax.security.auth.spi.LoginModule
+        with com.sun.jmx.remote.security.FileLoginModule;
+}
+
diff --git a/jdk/src/java.management/share/classes/sun/management/RuntimeImpl.java b/jdk/src/java.management/share/classes/sun/management/RuntimeImpl.java
index f381bc1..c919c0e 100644
--- a/jdk/src/java.management/share/classes/sun/management/RuntimeImpl.java
+++ b/jdk/src/java.management/share/classes/sun/management/RuntimeImpl.java
@@ -96,12 +96,8 @@
     }
 
     public String getBootClassPath() {
-        if (!isBootClassPathSupported()) {
-            throw new UnsupportedOperationException(
-                "Boot class path mechanism is not supported");
-        }
-        Util.checkMonitorAccess();
-        return jvm.getBootClassPath();
+        throw new UnsupportedOperationException(
+            "Boot class path mechanism is not supported");
     }
 
     public List<String> getInputArguments() {
@@ -118,7 +114,7 @@
     }
 
     public boolean isBootClassPathSupported() {
-        return jvm.isBootClassPathSupported();
+        return false;
     }
 
     public Map<String,String> getSystemProperties() {
diff --git a/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java b/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java
index 812e2b6..5f8b1bd 100644
--- a/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java
+++ b/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java
@@ -25,6 +25,9 @@
 
 package sun.management;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Predicate;
 import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
@@ -49,10 +52,19 @@
     public static StackTraceElement from(CompositeData cd) {
         validateCompositeData(cd);
 
-        return new StackTraceElement(getString(cd, CLASS_NAME),
-                                     getString(cd, METHOD_NAME),
-                                     getString(cd, FILE_NAME),
-                                     getInt(cd, LINE_NUMBER));
+        if (stackTraceElementV6CompositeType.equals(cd.getCompositeType())) {
+            return new StackTraceElement(getString(cd, CLASS_NAME),
+                                         getString(cd, METHOD_NAME),
+                                         getString(cd, FILE_NAME),
+                                         getInt(cd, LINE_NUMBER));
+        } else {
+            return new StackTraceElement(getString(cd, MODULE_NAME),
+                                         getString(cd, MODULE_VERSION),
+                                         getString(cd, CLASS_NAME),
+                                         getString(cd, METHOD_NAME),
+                                         getString(cd, FILE_NAME),
+                                         getInt(cd, LINE_NUMBER));
+        }
     }
 
     public static CompositeData toCompositeData(StackTraceElement ste) {
@@ -69,6 +81,8 @@
             ste.getFileName(),
             ste.getLineNumber(),
             ste.isNativeMethod(),
+            ste.getModuleName(),
+            ste.getModuleVersion(),
         };
         try {
             return new CompositeDataSupport(stackTraceElementCompositeType,
@@ -80,23 +94,14 @@
         }
     }
 
-    private static final CompositeType stackTraceElementCompositeType;
-    static {
-        try {
-            stackTraceElementCompositeType = (CompositeType)
-                MappedMXBeanType.toOpenType(StackTraceElement.class);
-        } catch (OpenDataException e) {
-            // Should never reach here
-            throw new AssertionError(e);
-        }
-    }
-
     // Attribute names
     private static final String CLASS_NAME      = "className";
     private static final String METHOD_NAME     = "methodName";
     private static final String FILE_NAME       = "fileName";
     private static final String LINE_NUMBER     = "lineNumber";
     private static final String NATIVE_METHOD   = "nativeMethod";
+    private static final String MODULE_NAME     = "moduleName";
+    private static final String MODULE_VERSION  = "moduleVersion";
 
     private static final String[] stackTraceElementItemNames = {
         CLASS_NAME,
@@ -104,8 +109,32 @@
         FILE_NAME,
         LINE_NUMBER,
         NATIVE_METHOD,
+        MODULE_NAME,
+        MODULE_VERSION,
     };
 
+    private static final String[] stackTraceElementV9ItemNames = {
+        MODULE_NAME,
+        MODULE_VERSION,
+    };
+
+    private static final CompositeType stackTraceElementCompositeType;
+    private static final CompositeType stackTraceElementV6CompositeType;
+    static {
+        try {
+            stackTraceElementCompositeType = (CompositeType)
+                MappedMXBeanType.toOpenType(StackTraceElement.class);
+            stackTraceElementV6CompositeType =
+                TypeVersionMapper.getInstance().getVersionedCompositeType(
+                    stackTraceElementCompositeType,
+                    TypeVersionMapper.V6
+                );
+        } catch (OpenDataException e) {
+            // Should never reach here
+            throw new AssertionError(e);
+        }
+    }
+
     /** Validate if the input CompositeData has the expected
      * CompositeType (i.e. contain all attributes with expected
      * names and types).
@@ -115,11 +144,23 @@
             throw new NullPointerException("Null CompositeData");
         }
 
-        if (!isTypeMatched(stackTraceElementCompositeType, cd.getCompositeType())) {
-            throw new IllegalArgumentException(
-                "Unexpected composite type for StackTraceElement");
+        CompositeType ct = cd.getCompositeType();
+        if (!isTypeMatched(stackTraceElementCompositeType, ct)) {
+            if (!isTypeMatched(stackTraceElementV6CompositeType, ct)) {
+                throw new IllegalArgumentException(
+                    "Unexpected composite type for StackTraceElement");
+            }
         }
     }
 
+    static boolean isV6Attribute(String name) {
+        for(String attrName : stackTraceElementV9ItemNames) {
+            if (name.equals(attrName)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private static final long serialVersionUID = -2704607706598396827L;
 }
diff --git a/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java b/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java
index e2d0357..146e9ac 100644
--- a/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java
+++ b/jdk/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java
@@ -32,7 +32,6 @@
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
 import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
 
 /**
  * A CompositeData for ThreadInfo for the local management support.
@@ -210,54 +209,16 @@
             threadInfoCompositeType = (CompositeType)
                 MappedMXBeanType.toOpenType(ThreadInfo.class);
             // Form a CompositeType for JDK 5.0 ThreadInfo version
-            String[] itemNames =
-                threadInfoCompositeType.keySet().toArray(new String[0]);
-            int numV5Attributes = threadInfoItemNames.length -
-                threadInfoV6Attributes.length - threadInfoV9Attributes.length;
-            String[] v5ItemNames = new String[numV5Attributes];
-            String[] v5ItemDescs = new String[numV5Attributes];
-            OpenType<?>[] v5ItemTypes = new OpenType<?>[numV5Attributes];
-            int i = 0;
-            for (String n : itemNames) {
-                if (isV5Attribute(n)) {
-                    v5ItemNames[i] = n;
-                    v5ItemDescs[i] = threadInfoCompositeType.getDescription(n);
-                    v5ItemTypes[i] = threadInfoCompositeType.getType(n);
-                    i++;
-                }
-            }
 
             threadInfoV5CompositeType =
-                new CompositeType("java.lang.management.ThreadInfo",
-                                  "J2SE 5.0 java.lang.management.ThreadInfo",
-                                  v5ItemNames,
-                                  v5ItemDescs,
-                                  v5ItemTypes);
-
-
-            // Form a CompositeType for JDK 6.0 ThreadInfo version
-            int numV6Attributes = threadInfoItemNames.length -
-                                      threadInfoV9Attributes.length;
-            String[] v6ItemNames = new String[numV6Attributes];
-            String[] v6ItemDescs = new String[numV6Attributes];
-            OpenType<?>[] v6ItemTypes = new OpenType<?>[numV6Attributes];
-            i = 0;
-            for (String n : itemNames) {
-                if (isV5Attribute(n) || isV6Attribute(n)) {
-                    v6ItemNames[i] = n;
-                    v6ItemDescs[i] = threadInfoCompositeType.getDescription(n);
-                    v6ItemTypes[i] = threadInfoCompositeType.getType(n);
-                    i++;
-                }
-            }
+                TypeVersionMapper.getInstance().getVersionedCompositeType(
+                    threadInfoCompositeType, TypeVersionMapper.V5
+                );
 
             threadInfoV6CompositeType =
-                new CompositeType("java.lang.management.ThreadInfo",
-                                  "Java SE 6 java.lang.management.ThreadInfo",
-                                  v6ItemNames,
-                                  v6ItemDescs,
-                                  v6ItemTypes);
-
+                TypeVersionMapper.getInstance().getVersionedCompositeType(
+                    threadInfoCompositeType, TypeVersionMapper.V6
+                );
         } catch (OpenDataException e) {
             // Should never reach here
             throw new AssertionError(e);
@@ -275,7 +236,7 @@
         lockInfoCompositeType = cd.getCompositeType();
     }
 
-    private static boolean isV5Attribute(String itemName) {
+    static boolean isV5Attribute(String itemName) {
         for (String n : threadInfoV6Attributes) {
             if (itemName.equals(n)) {
                 return false;
@@ -289,7 +250,7 @@
         return true;
     }
 
-    private static boolean isV6Attribute(String itemName) {
+    static boolean isV6Attribute(String itemName) {
         for (String n : threadInfoV9Attributes) {
             if (itemName.equals(n)) {
                 return false;
@@ -446,8 +407,8 @@
             // check if cd is an older version
             if (!isTypeMatched(threadInfoV5CompositeType, type) &&
                 !isTypeMatched(threadInfoV6CompositeType, type)) {
-              throw new IllegalArgumentException(
-                  "Unexpected composite type for ThreadInfo");
+                throw new IllegalArgumentException(
+                    "Unexpected composite type for ThreadInfo");
             }
         }
 
diff --git a/jdk/src/java.management/share/classes/sun/management/TypeVersionMapper.java b/jdk/src/java.management/share/classes/sun/management/TypeVersionMapper.java
new file mode 100644
index 0000000..4119599
--- /dev/null
+++ b/jdk/src/java.management/share/classes/sun/management/TypeVersionMapper.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.management;
+
+import java.lang.management.ThreadInfo;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularType;
+import static sun.management.Util.toStringArray;
+
+/**
+ * Provides simplistic support for versioning of {@linkplain CompositeType} instances
+ * based on the latest version and filtering out certain items.
+ */
+final class TypeVersionMapper {
+    private static final class Singleton {
+        private final static TypeVersionMapper INSTANCE = new TypeVersionMapper();
+    }
+
+    final static String V5 = "J2SE 5.0";
+    final static String V6 = "Java SE 6";
+
+    private final Map<String, Map<String, Predicate<String>>> filterMap;
+
+    private TypeVersionMapper() {
+        filterMap = new HashMap<>();
+        setupStackTraceElement();
+        setupThreadInfo();
+    }
+
+    public static TypeVersionMapper getInstance() {
+        return Singleton.INSTANCE;
+    }
+
+    private void setupStackTraceElement() {
+        Map<String, Predicate<String>> filter = new HashMap<>();
+        filterMap.put(StackTraceElement.class.getName(), filter);
+        filter.put(V5, StackTraceElementCompositeData::isV6Attribute);
+        filter.put(V6, StackTraceElementCompositeData::isV6Attribute);
+    }
+
+    private void setupThreadInfo() {
+        Map<String, Predicate<String>> filter = new HashMap<>();
+        filterMap.put(ThreadInfo.class.getName(), filter);
+        filter.put(V5, ThreadInfoCompositeData::isV5Attribute);
+        filter.put(V6, ThreadInfoCompositeData::isV6Attribute);
+    }
+
+    /**
+     * Retrieves the specified version of a {@linkplain CompositeType} instance.
+     * @param type The current (latest) version of {@linkplain CompositeType}
+     * @param version The version identifier (eg. {@linkplain TypeVersionMapper#V5})
+     * @return Returns the {@linkplain CompositeType} corresponding to the requested
+     *         version.
+     * @throws OpenDataException
+     */
+    CompositeType getVersionedCompositeType(CompositeType type, String version)
+        throws OpenDataException
+    {
+        Predicate<String> filter = getFilter(type.getTypeName(), version);
+        if (filter == null) {
+            return type;
+        }
+
+        List<String> itemNames = new ArrayList<>();
+        List<String> itemDesc = new ArrayList<>();
+        List<OpenType<?>> itemTypes = new ArrayList<>();
+
+        for(String item : type.keySet()) {
+            if (filter.test(item)) {
+                itemNames.add(item);
+                itemDesc.add(type.getDescription(item));
+                itemTypes.add(getVersionedType(
+                    type.getType(item),
+                    version
+                ));
+            }
+        }
+        return new CompositeType(
+            type.getTypeName(),
+            version != null ? version + " " + type.getDescription() : type.getDescription(),
+            itemNames.toArray(new String[itemNames.size()]),
+            itemDesc.toArray(new String[itemDesc.size()]),
+            itemTypes.toArray(new OpenType<?>[itemTypes.size()])
+        );
+    }
+
+    private OpenType<?> getVersionedType(OpenType<?> type, String version)
+        throws OpenDataException
+    {
+        if (type instanceof ArrayType) {
+            return getVersionedArrayType((ArrayType)type, version);
+        }
+        if (type instanceof CompositeType) {
+            return getVersionedCompositeType((CompositeType)type, version);
+        }
+        if (type instanceof TabularType) {
+            return getVersionedTabularType((TabularType)type, version);
+        }
+        return type;
+    }
+
+    private ArrayType<?> getVersionedArrayType(ArrayType<?> type, String version)
+        throws OpenDataException
+    {
+        if (type.isPrimitiveArray()) {
+            return type;
+        }
+        OpenType<?> ot = getVersionedType(
+            type.getElementOpenType(),
+            version
+        );
+        if (ot instanceof SimpleType) {
+            return new ArrayType<>((SimpleType<?>)ot, type.isPrimitiveArray());
+        } else {
+            return new ArrayType<>(type.getDimension(), ot);
+        }
+    }
+
+    private TabularType getVersionedTabularType(TabularType type, String version)
+        throws OpenDataException
+    {
+        CompositeType ct = getVersionedCompositeType(
+            type.getRowType(),
+            version
+        );
+
+        if (ct != null) {
+            return new TabularType(
+                type.getTypeName(), type.getDescription(), ct,
+                toStringArray(type.getIndexNames()));
+        }
+        return null;
+    }
+
+    private Predicate<String> getFilter(String type, String version) {
+        Map<String, Predicate<String>> versionMap = filterMap.get(type);
+        if (versionMap == null) {
+            return null;
+        }
+
+        return versionMap.get(version);
+    }
+}
diff --git a/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java b/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java
index 0600a7a..b0e4d44 100644
--- a/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java
+++ b/jdk/src/java.management/share/classes/sun/management/VMManagementImpl.java
@@ -51,7 +51,6 @@
     private static boolean threadContentionMonitoringSupport;
     private static boolean currentThreadCpuTimeSupport;
     private static boolean otherThreadCpuTimeSupport;
-    private static boolean bootClassPathSupport;
     private static boolean objectMonitorUsageSupport;
     private static boolean synchronizerUsageSupport;
     private static boolean threadAllocatedMemorySupport;
@@ -87,7 +86,7 @@
     }
 
     public boolean isBootClassPathSupported() {
-        return bootClassPathSupport;
+        return false;
     }
 
     public boolean isObjectMonitorUsageSupported() {
@@ -172,8 +171,8 @@
     }
 
     public String   getBootClassPath( ) {
-        return AccessController.doPrivileged(
-            (PrivilegedAction<String>) () -> System.getProperty("sun.boot.class.path"));
+        throw new UnsupportedOperationException(
+            "Boot class path mechanism is not supported");
     }
 
     public long getUptime() {
diff --git a/jdk/src/java.management/share/native/include/jmm.h b/jdk/src/java.management/share/native/include/jmm.h
index 6c3894a..9e21296 100644
--- a/jdk/src/java.management/share/native/include/jmm.h
+++ b/jdk/src/java.management/share/native/include/jmm.h
@@ -59,7 +59,6 @@
   unsigned int isThreadContentionMonitoringSupported : 1;
   unsigned int isCurrentThreadCpuTimeSupported : 1;
   unsigned int isOtherThreadCpuTimeSupported : 1;
-  unsigned int isBootClassPathSupported : 1;
   unsigned int isObjectMonitorUsageSupported : 1;
   unsigned int isSynchronizerUsageSupported : 1;
   unsigned int isThreadAllocatedMemorySupported : 1;
diff --git a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c
index 7743c35..5113685 100644
--- a/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c
+++ b/jdk/src/java.management/share/native/libmanagement/VMManagementImpl.c
@@ -80,9 +80,6 @@
     value = mos.isOtherThreadCpuTimeSupported;
     setStaticBooleanField(env, cls, "otherThreadCpuTimeSupport", value);
 
-    value = mos.isBootClassPathSupported;
-    setStaticBooleanField(env, cls, "bootClassPathSupport", value);
-
     if (jmm_version >= JMM_VERSION_1_1) {
         value = mos.isObjectMonitorUsageSupported;
         setStaticBooleanField(env, cls, "objectMonitorUsageSupport", value);
diff --git a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
index e1be611..728ea0d 100644
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
@@ -643,8 +643,10 @@
                  classObjs[i] = cl;
              }
              try {
-                 return Proxy.getProxyClass(hasNonPublicInterface ?
+                 @SuppressWarnings("deprecation")
+                 Class<?> proxyClass = Proxy.getProxyClass(hasNonPublicInterface ?
                         nonPublicLoader : classLoader, classObjs);
+                 return proxyClass;
              } catch (IllegalArgumentException e) {
                  throw new ClassNotFoundException(null, e);
              }
diff --git a/jdk/src/java.naming/share/classes/com/sun/naming/internal/VersionHelper.java b/jdk/src/java.naming/share/classes/com/sun/naming/internal/VersionHelper.java
index 6220e1e..c29a88d 100644
--- a/jdk/src/java.naming/share/classes/com/sun/naming/internal/VersionHelper.java
+++ b/jdk/src/java.naming/share/classes/com/sun/naming/internal/VersionHelper.java
@@ -149,12 +149,39 @@
         return jProps;
     }
 
+    private static String resolveName(Class<?> c, String name) {
+        if (name == null) {
+            return name;
+        }
+        if (!name.startsWith("/")) {
+            while (c.isArray()) {
+                c = c.getComponentType();
+            }
+            String baseName = c.getName();
+            int index = baseName.lastIndexOf('.');
+            if (index != -1) {
+                name = baseName.substring(0, index).replace('.', '/')
+                    +"/"+name;
+            }
+        } else {
+            name = name.substring(1);
+        }
+        return name;
+    }
+
     /*
      * Returns the resource of a given name associated with a particular
      * class (never null), or null if none can be found.
      */
     InputStream getResourceAsStream(Class<?> c, String name) {
-        PrivilegedAction<InputStream> act = () -> c.getResourceAsStream(name);
+        PrivilegedAction<InputStream> act = () -> {
+            try {
+                java.lang.reflect.Module m = c.getModule();
+                return c.getModule().getResourceAsStream(resolveName(c,name));
+             } catch (IOException x) {
+                 return null;
+             }
+        };
         return AccessController.doPrivileged(act);
     }
 
diff --git a/jdk/src/java.naming/share/classes/javax/naming/ldap/ControlFactory.java b/jdk/src/java.naming/share/classes/javax/naming/ldap/ControlFactory.java
index afb28ad..49b63e6 100644
--- a/jdk/src/java.naming/share/classes/javax/naming/ldap/ControlFactory.java
+++ b/jdk/src/java.naming/share/classes/javax/naming/ldap/ControlFactory.java
@@ -112,8 +112,11 @@
       *    exception is passed up to the caller.
       *</ul>
       * <p>
-      * Note that a control factory
-      * must be public and must have a public constructor that accepts no arguments.
+      * Note that a control factory must be public and must have a public
+      * constructor that accepts no arguments.
+      * In cases where the factory is in a named module then it must be in a
+      * package which is exported by that module to the {@code java.naming}
+      * module.
       *
       * @param ctl The non-null control object containing the OID and BER data.
       * @param ctx The possibly null context in which the control is being created.
diff --git a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java
index 7031e64..6a13625 100644
--- a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java
+++ b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,8 +25,9 @@
 
 package javax.naming.spi;
 
-import java.util.*;
 import java.net.MalformedURLException;
+import java.util.*;
+
 
 import javax.naming.*;
 import com.sun.naming.internal.VersionHelper;
@@ -243,6 +244,9 @@
      * Note that an object factory (an object that implements the ObjectFactory
      * interface) must be public and must have a public constructor that
      * accepts no arguments.
+     * In cases where the factory is in a named module then it must be in a
+     * package which is exported by that module to the {@code java.naming}
+     * module.
      * <p>
      * The {@code name} and {@code nameCtx} parameters may
      * optionally be used to specify the name of the object being created.
@@ -525,6 +529,9 @@
      * Note that an object factory (an object that implements the ObjectFactory
      * interface) must be public and must have a public constructor that
      * accepts no arguments.
+     * In cases where the factory is in a named module then it must be in a
+     * package which is exported by that module to the {@code java.naming}
+     * module.
      *
      * @param scheme    The non-null scheme-id of the URLs supported by the context.
      * @param environment The possibly null environment properties to be
@@ -641,7 +648,10 @@
      *         <br>
      *         (Note that an initial context factory (an object that implements
      *         the InitialContextFactory interface) must be public and must have
-     *         a public constructor that accepts no arguments)</li>
+     *         a public constructor that accepts no arguments.
+     *         In cases where the factory is in a named module then it must
+     *         be in a package which is exported by that module to the
+     *         {@code java.naming} module.)</li>
      *     </ul>
      * </li>
      * </ul>
@@ -847,6 +857,9 @@
      * (an object that implements the StateFactory
      * interface) must be public and must have a public constructor that
      * accepts no arguments.
+     * In cases where the factory is in a named module then it must be in a
+     * package which is exported by that module to the {@code java.naming}
+     * module.
      * <p>
      * The {@code name} and {@code nameCtx} parameters may
      * optionally be used to specify the name of the object being created.
diff --git a/jdk/src/java.naming/share/classes/javax/naming/spi/ObjectFactory.java b/jdk/src/java.naming/share/classes/javax/naming/spi/ObjectFactory.java
index 9059022..c78f5d3 100644
--- a/jdk/src/java.naming/share/classes/javax/naming/spi/ObjectFactory.java
+++ b/jdk/src/java.naming/share/classes/javax/naming/spi/ObjectFactory.java
@@ -46,6 +46,9 @@
   * An object factory must implement the {@code ObjectFactory} interface.
   * In addition, the factory class must be public and must have a
   * public constructor that accepts no parameters.
+  * Note that in cases where the factory is in a named module then it must be
+  * in a package which is exported by that module to the {@code java.naming}
+  * module.
   *<p>
   * The {@code getObjectInstance()} method of an object factory may
   * be invoked multiple times, possibly using different parameters.
diff --git a/jdk/src/java.naming/share/classes/javax/naming/spi/StateFactory.java b/jdk/src/java.naming/share/classes/javax/naming/spi/StateFactory.java
index 9ef15b8..bf8273e 100644
--- a/jdk/src/java.naming/share/classes/javax/naming/spi/StateFactory.java
+++ b/jdk/src/java.naming/share/classes/javax/naming/spi/StateFactory.java
@@ -58,6 +58,9 @@
   * A state factory must implement the {@code StateFactory} interface.
   * In addition, the factory class must be public and must have a
   * public constructor that accepts no parameters.
+  * Note that in cases where the factory is in a named module then it must be
+  * in a package which is exported by that module to the {@code java.naming}
+  * module.
   *<p>
   * The {@code getStateToBind()} method of a state factory may
   * be invoked multiple times, possibly using different parameters.
diff --git a/jdk/src/java.naming/share/classes/module-info.java b/jdk/src/java.naming/share/classes/module-info.java
new file mode 100644
index 0000000..fb2e101
--- /dev/null
+++ b/jdk/src/java.naming/share/classes/module-info.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.naming {
+    requires java.security.sasl;
+
+    exports javax.naming;
+    exports javax.naming.directory;
+    exports javax.naming.event;
+    exports javax.naming.ldap;
+    exports javax.naming.spi;
+    exports com.sun.jndi.toolkit.ctx to
+        jdk.naming.dns;
+    exports com.sun.jndi.toolkit.url to
+        java.corba,
+        jdk.naming.dns,
+        jdk.naming.rmi;
+    uses javax.naming.ldap.StartTlsResponse;
+    uses javax.naming.spi.InitialContextFactory;
+    provides java.security.Provider with sun.security.provider.certpath.ldap.JdkLDAP;
+}
+
diff --git a/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java b/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
index 5d69324..1b9a2b0 100644
--- a/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
+++ b/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java
@@ -48,7 +48,6 @@
 import sun.security.provider.certpath.X509CertificatePair;
 import sun.security.util.Cache;
 import sun.security.util.Debug;
-import sun.security.x509.X500Name;
 
 /**
  * Core implementation of a LDAP Cert Store.
diff --git a/jdk/src/java.prefs/share/classes/module-info.java b/jdk/src/java.prefs/share/classes/module-info.java
new file mode 100644
index 0000000..3556b8e
--- /dev/null
+++ b/jdk/src/java.prefs/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.prefs {
+    requires java.xml;
+
+    exports java.util.prefs;
+    uses java.util.prefs.PreferencesFactory;
+}
+
diff --git a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java
index 02511b8..120a15a 100644
--- a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java
+++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java
@@ -275,10 +275,9 @@
             RemoteRef ref = refClass.newInstance();
             ref.readExternal(in);
             activator = (Activator)
-                Proxy.newProxyInstance(null,
+                Proxy.newProxyInstance(Activator.class.getClassLoader(),
                                        new Class<?>[] { Activator.class },
                                        new RemoteObjectInvocationHandler(ref));
-
         } catch (InstantiationException e) {
             throw (IOException)
                 new InvalidObjectException(
diff --git a/jdk/src/java.rmi/share/classes/module-info.java b/jdk/src/java.rmi/share/classes/module-info.java
new file mode 100644
index 0000000..44bd728
--- /dev/null
+++ b/jdk/src/java.rmi/share/classes/module-info.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.rmi {
+    requires java.logging;
+
+    exports java.rmi;
+    exports java.rmi.activation;
+    exports java.rmi.dgc;
+    exports java.rmi.registry;
+    exports java.rmi.server;
+    exports javax.rmi.ssl;
+    // com.sun.rmi.rmid contains permissions classes that must be
+    // accessible to the security manager at initialization time
+    exports com.sun.rmi.rmid to java.base;
+    exports sun.rmi.registry to
+        java.management;
+    exports sun.rmi.server to
+        java.management,
+        jdk.jconsole;
+    exports sun.rmi.transport to
+        java.management,
+        jdk.jconsole;
+    uses java.rmi.server.RMIClassLoaderSpi;
+}
+
diff --git a/jdk/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java b/jdk/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java
index 9e7a0ca..cc8127d 100644
--- a/jdk/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java
+++ b/jdk/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java
@@ -433,8 +433,11 @@
         InputStream sysIn = null;
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         for (String ext : exts) {
-            sysIn = cl.getResourceAsStream("com/sun/tools/script/shell/init." +
-                    ext);
+            try {
+                sysIn = Main.class.getModule().getResourceAsStream("com/sun/tools/script/shell/init." + ext);
+            } catch (IOException ioe) {
+                throw new RuntimeException(ioe);
+            }
             if (sysIn != null) break;
         }
         if (sysIn != null) {
diff --git a/jdk/src/java.scripting/share/classes/module-info.java b/jdk/src/java.scripting/share/classes/module-info.java
new file mode 100644
index 0000000..b713ad0
--- /dev/null
+++ b/jdk/src/java.scripting/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.scripting {
+    exports javax.script;
+    uses javax.script.ScriptEngineFactory;
+}
+
diff --git a/jdk/src/java.se.ee/share/classes/module-info.java b/jdk/src/java.se.ee/share/classes/module-info.java
new file mode 100644
index 0000000..6d4a11f
--- /dev/null
+++ b/jdk/src/java.se.ee/share/classes/module-info.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+module java.se.ee {
+
+    requires public 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;
+
+}
diff --git a/jdk/src/java.se/share/classes/module-info.java b/jdk/src/java.se/share/classes/module-info.java
new file mode 100644
index 0000000..af159f4
--- /dev/null
+++ b/jdk/src/java.se/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.se {
+    requires public java.compact3;
+    requires public java.datatransfer;
+    requires public java.desktop;
+}
diff --git a/jdk/src/java.security.jgss/share/classes/META-INF/services/sun.security.ssl.ClientKeyExchangeService b/jdk/src/java.security.jgss/share/classes/META-INF/services/sun.security.ssl.ClientKeyExchangeService
deleted file mode 100644
index 883cba3..0000000
--- a/jdk/src/java.security.jgss/share/classes/META-INF/services/sun.security.ssl.ClientKeyExchangeService
+++ /dev/null
@@ -1,2 +0,0 @@
-sun.security.krb5.internal.ssl.Krb5KeyExchangeService
-
diff --git a/jdk/src/java.security.jgss/share/classes/module-info.java b/jdk/src/java.security.jgss/share/classes/module-info.java
new file mode 100644
index 0000000..0a1e6c0
--- /dev/null
+++ b/jdk/src/java.security.jgss/share/classes/module-info.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.security.jgss {
+    requires java.naming;
+    exports javax.security.auth.kerberos;
+    exports org.ietf.jgss;
+    exports sun.security.jgss to
+        jdk.security.jgss;
+    exports sun.security.jgss.krb5 to
+        jdk.security.auth;
+    exports sun.security.krb5 to
+        jdk.security.auth;
+    exports sun.security.krb5.internal to
+        jdk.security.jgss;
+    exports sun.security.krb5.internal.ktab to
+        jdk.security.auth;
+    provides java.security.Provider with sun.security.jgss.SunProvider;
+    provides sun.security.ssl.ClientKeyExchangeService
+        with sun.security.krb5.internal.ssl.Krb5KeyExchangeService;
+}
+
diff --git a/jdk/src/java.security.sasl/share/classes/module-info.java b/jdk/src/java.security.sasl/share/classes/module-info.java
new file mode 100644
index 0000000..ca06592
--- /dev/null
+++ b/jdk/src/java.security.sasl/share/classes/module-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.security.sasl {
+    requires java.logging;
+
+    exports javax.security.sasl;
+    exports com.sun.security.sasl.util to
+        jdk.security.jgss;
+    provides java.security.Provider with com.sun.security.sasl.Provider;
+}
+
diff --git a/jdk/src/java.smartcardio/share/classes/module-info.java b/jdk/src/java.smartcardio/share/classes/module-info.java
new file mode 100644
index 0000000..18f3998
--- /dev/null
+++ b/jdk/src/java.smartcardio/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.smartcardio {
+    exports javax.smartcardio;
+    provides java.security.Provider with sun.security.smartcardio.SunPCSC;
+}
+
diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java
index a97a272..b17cd50 100644
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java
@@ -2961,7 +2961,8 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData) ReflectUtil.newInstance(c);
+                    ReflectUtil.checkPackageAccess(c);
+                    obj = (SQLData) c.newInstance();
                 } catch(Exception ex) {
                     throw new SQLException("Unable to Instantiate: ", ex);
                 }
@@ -5708,7 +5709,8 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData) ReflectUtil.newInstance(c);
+                    ReflectUtil.checkPackageAccess(c);
+                    obj = (SQLData) c.newInstance();
                 } catch(Exception ex) {
                     throw new SQLException("Unable to Instantiate: ", ex);
                 }
diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
index a2eca12..aaf3a5b 100644
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
@@ -102,8 +102,8 @@
         Locale locale = Locale.getDefault();
 
         // Load appropriate bundle according to locale
-         propResBundle = (PropertyResourceBundle) ResourceBundle.getBundle(PATH,
-                           locale, Thread.currentThread().getContextClassLoader());
+        propResBundle = (PropertyResourceBundle) ResourceBundle.getBundle(PATH,
+                           locale, JdbcRowSetResourceBundle.class.getModule());
 
    }
 
diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java
index 2b596f3..07865ac 100644
--- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java
@@ -573,7 +573,8 @@
                         // create new instance of the class
                         SQLData obj = null;
                         try {
-                            obj = (SQLData)ReflectUtil.newInstance(c);
+                            ReflectUtil.checkPackageAccess(c);
+                            obj = (SQLData)c.newInstance();
                         } catch (Exception ex) {
                             throw new SQLException("Unable to Instantiate: ", ex);
                         }
@@ -1467,4 +1468,5 @@
 
         return isValid;
     }
+
 }
diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java
index 20aacfd..02863b2 100644
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java
@@ -31,7 +31,6 @@
 import java.util.PropertyPermission;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
-import javax.sql.rowset.spi.SyncFactoryException;
 import sun.reflect.misc.ReflectUtil;
 
 /**
@@ -132,9 +131,15 @@
             factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
             if (factoryClassName != null) {
                 trace("Found system property, value=" + factoryClassName);
-                factory = (RowSetFactory) ReflectUtil.newInstance(getFactoryClass(factoryClassName, null, true));
+                if (factoryClassName.equals(ROWSET_FACTORY_IMPL)) {
+                    return defaultRowSetFactory();
+                }
+                // getFactoryClass takes care of adding the read edge if
+                // necessary
+                Class<?> c = getFactoryClass(factoryClassName, null, false);
+                factory = (RowSetFactory) c.newInstance();
             }
-        }  catch (Exception e) {
+        } catch (Exception e) {
             throw new SQLException( "RowSetFactory: " + factoryClassName +
                     " could not be instantiated: ", e);
         }
@@ -145,10 +150,12 @@
             // look it up via the ServiceLoader API and if not found, use the
             // Java SE default.
             factory = loadViaServiceLoader();
-            factory =
-                    factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory;
         }
-        return (factory);
+        return  factory == null ? defaultRowSetFactory() : factory;
+    }
+
+    private static RowSetFactory defaultRowSetFactory() {
+        return new com.sun.rowset.RowSetFactoryImpl();
     }
 
     /**
@@ -192,6 +199,8 @@
         }
 
         try {
+            // getFactoryClass takes care of adding the read edge if
+            // necessary
             Class<?> providerClass = getFactoryClass(factoryClassName, cl, false);
             RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
             if (debug) {
@@ -242,25 +251,30 @@
      */
     static private Class<?> getFactoryClass(String factoryClassName, ClassLoader cl,
             boolean doFallback) throws ClassNotFoundException {
+        Class<?> factoryClass = null;
+
         try {
             if (cl == null) {
                 cl = getContextClassLoader();
                 if (cl == null) {
                     throw new ClassNotFoundException();
                 } else {
-                    return cl.loadClass(factoryClassName);
+                    factoryClass = cl.loadClass(factoryClassName);
                 }
             } else {
-                return cl.loadClass(factoryClassName);
+                factoryClass = cl.loadClass(factoryClassName);
             }
         } catch (ClassNotFoundException e) {
             if (doFallback) {
                 // Use current class loader
-                return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
+                factoryClass = Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
             } else {
                 throw e;
             }
         }
+
+        ReflectUtil.checkPackageAccess(factoryClass);
+        return factoryClass;
     }
 
     /**
diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java
index 2bde738..41332f5 100644
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java
@@ -477,7 +477,8 @@
                 // create new instance of the class
                 SQLData obj = null;
                 try {
-                    obj = (SQLData)ReflectUtil.newInstance(c);
+                    ReflectUtil.checkPackageAccess(c);
+                    obj = (SQLData)c.newInstance();
                 } catch (Exception ex) {
                     throw new SQLException("Unable to Instantiate: ", ex);
                 }
diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java
index 686479f..8aeccdf 100644
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java
@@ -383,17 +383,14 @@
                         strFileSep + "rowset" + strFileSep +
                         "rowset.properties";
 
-                ClassLoader cl = Thread.currentThread().getContextClassLoader();
-
                 try {
                     AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
-                        try (InputStream stream = (cl == null) ?
-                                ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES)
-                                : cl.getResourceAsStream(ROWSET_PROPERTIES)) {
-                            if (stream == null) {
-                                throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
-                            }
-                            properties.load(stream);
+                        InputStream in = SyncFactory.class.getModule().getResourceAsStream(ROWSET_PROPERTIES);
+                        if (in == null) {
+                            throw new SyncFactoryException("Resource " + ROWSET_PROPERTIES + " not found");
+                        }
+                        try (in) {
+                            properties.load(in);
                         }
                         return null;
                     });
@@ -585,12 +582,7 @@
              * there.
              **/
             c = Class.forName(providerID, true, cl);
-
-            if (c != null) {
-                return (SyncProvider) c.newInstance();
-            } else {
-                return new com.sun.rowset.providers.RIOptimisticProvider();
-            }
+            return (SyncProvider) c.newInstance();
 
         } catch (IllegalAccessException e) {
             throw new SyncFactoryException("IllegalAccessException: " + e.getMessage());
diff --git a/jdk/src/java.sql.rowset/share/classes/module-info.java b/jdk/src/java.sql.rowset/share/classes/module-info.java
new file mode 100644
index 0000000..a1cd9ce
--- /dev/null
+++ b/jdk/src/java.sql.rowset/share/classes/module-info.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.sql.rowset {
+    requires public java.logging;
+    requires public java.naming;
+    requires public java.sql;
+
+    exports javax.sql.rowset;
+    exports javax.sql.rowset.serial;
+    exports javax.sql.rowset.spi;
+    uses javax.sql.rowset.RowSetFactory;
+}
+
diff --git a/jdk/src/java.sql/share/classes/module-info.java b/jdk/src/java.sql/share/classes/module-info.java
new file mode 100644
index 0000000..30683d9
--- /dev/null
+++ b/jdk/src/java.sql/share/classes/module-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.sql {
+    requires public java.logging;
+    requires public java.xml;
+
+    exports java.sql;
+    exports javax.sql;
+    exports javax.transaction.xa;
+    uses java.sql.Driver;
+}
+
diff --git a/jdk/src/java.transaction/share/classes/module-info.java b/jdk/src/java.transaction/share/classes/module-info.java
new file mode 100644
index 0000000..de572d9
--- /dev/null
+++ b/jdk/src/java.transaction/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+module java.transaction {
+    requires public 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
new file mode 100644
index 0000000..1c92d07
--- /dev/null
+++ b/jdk/src/java.xml.crypto/share/classes/module-info.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.xml.crypto {
+    requires public java.xml;
+    requires java.logging;
+
+    exports javax.xml.crypto;
+    exports javax.xml.crypto.dom;
+    exports javax.xml.crypto.dsig;
+    exports javax.xml.crypto.dsig.dom;
+    exports javax.xml.crypto.dsig.keyinfo;
+    exports javax.xml.crypto.dsig.spec;
+    provides java.security.Provider with org.jcp.xml.dsig.internal.dom.XMLDSigRI;
+}
+
diff --git a/jdk/src/jdk.accessibility/share/classes/module-info.java b/jdk/src/jdk.accessibility/share/classes/module-info.java
new file mode 100644
index 0000000..e72b5b7
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+module jdk.accessibility {
+    requires public java.desktop;
+    exports com.sun.java.accessibility.util;
+}
+
diff --git a/jdk/src/jdk.accessibility/windows/classes/META-INF/services/javax.accessibility.AccessibilityProvider b/jdk/src/jdk.accessibility/windows/classes/META-INF/services/javax.accessibility.AccessibilityProvider
deleted file mode 100644
index 0c0e2ac..0000000
--- a/jdk/src/jdk.accessibility/windows/classes/META-INF/services/javax.accessibility.AccessibilityProvider
+++ /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.  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.

-

-

-com.sun.java.accessibility.internal.ProviderImpl

-

diff --git a/jdk/src/jdk.accessibility/windows/classes/module-info.java.extra b/jdk/src/jdk.accessibility/windows/classes/module-info.java.extra
new file mode 100644
index 0000000..f0ee5e4
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/classes/module-info.java.extra
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+provides javax.accessibility.AccessibilityProvider with com.sun.java.accessibility.internal.ProviderImpl;
diff --git a/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider b/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider
deleted file mode 100644
index 7ab9b79..0000000
--- a/jdk/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-sun.tools.attach.AttachProviderImpl
diff --git a/jdk/src/jdk.attach/share/classes/module-info.java b/jdk/src/jdk.attach/share/classes/module-info.java
new file mode 100644
index 0000000..a6f7a7e
--- /dev/null
+++ b/jdk/src/jdk.attach/share/classes/module-info.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.attach {
+    requires jdk.jvmstat;
+
+    exports com.sun.tools.attach;
+    exports com.sun.tools.attach.spi;
+    exports sun.tools.attach to
+        jdk.jcmd;
+    uses com.sun.tools.attach.spi.AttachProvider;
+    provides com.sun.tools.attach.spi.AttachProvider with sun.tools.attach.AttachProviderImpl;
+}
+
diff --git a/jdk/src/jdk.charsets/share/classes/META-INF/services/java.nio.charset.spi.CharsetProvider b/jdk/src/jdk.charsets/share/classes/META-INF/services/java.nio.charset.spi.CharsetProvider
deleted file mode 100644
index cf0949e..0000000
--- a/jdk/src/jdk.charsets/share/classes/META-INF/services/java.nio.charset.spi.CharsetProvider
+++ /dev/null
@@ -1,2 +0,0 @@
-# NIO charset SPI extended charset provider
-sun.nio.cs.ext.ExtendedCharsets
diff --git a/jdk/src/jdk.charsets/share/classes/module-info.java b/jdk/src/jdk.charsets/share/classes/module-info.java
new file mode 100644
index 0000000..6e8cfc3
--- /dev/null
+++ b/jdk/src/jdk.charsets/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.charsets {
+    provides java.nio.charset.spi.CharsetProvider
+        with sun.nio.cs.ext.ExtendedCharsets;
+}
+
diff --git a/jdk/src/jdk.compiler/share/classes/sun/tools/serialver/SerialVer.java b/jdk/src/jdk.compiler/share/classes/sun/tools/serialver/SerialVer.java
index 268ed51..e0426fe 100644
--- a/jdk/src/jdk.compiler/share/classes/sun/tools/serialver/SerialVer.java
+++ b/jdk/src/jdk.compiler/share/classes/sun/tools/serialver/SerialVer.java
@@ -27,15 +27,13 @@
 
 import java.io.*;
 import java.io.ObjectStreamClass;
-import java.util.Properties;
+import java.nio.file.Paths;
 import java.text.MessageFormat;
 import java.util.ResourceBundle;
 import java.util.MissingResourceException;
 import java.net.URLClassLoader;
 import java.net.URL;
 import java.net.MalformedURLException;
-import java.util.StringTokenizer;
-import sun.net.www.ParseUtil;
 
 /**
  * Supporting class for the serialver tool.
@@ -52,15 +50,12 @@
      * Create a URL class loader that will load classes from the
      * specified classpath.
      */
-    static void initializeLoader(String cp)
-                                throws MalformedURLException, IOException {
-        URL[] urls;
-        StringTokenizer st = new StringTokenizer(cp, File.pathSeparator);
-        int count = st.countTokens();
-        urls = new URL[count];
+    static void initializeLoader(String cp) throws IOException {
+        String[] paths = cp.split(File.pathSeparator);
+        int count = paths.length;
+        URL[] urls = new URL[count];
         for (int i = 0; i < count; i++) {
-            urls[i] = ParseUtil.fileToEncodedURL(
-                new File(new File(st.nextToken()).getCanonicalPath()));
+            urls[i] = Paths.get(paths[i]).toUri().toURL();
         }
         loader = new URLClassLoader(urls);
     }
diff --git a/jdk/src/jdk.crypto.ec/share/classes/module-info.java b/jdk/src/jdk.crypto.ec/share/classes/module-info.java
new file mode 100644
index 0000000..227882d
--- /dev/null
+++ b/jdk/src/jdk.crypto.ec/share/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.crypto.ec {
+    provides java.security.Provider with sun.security.ec.SunEC;
+}
+
diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java b/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java
new file mode 100644
index 0000000..9a2801e
--- /dev/null
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.crypto.mscapi {
+    provides java.security.Provider with sun.security.mscapi.SunMSCAPI;
+}
+
diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
index f9ffd5f..f28e5cb 100644
--- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java
@@ -30,7 +30,6 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.RSAKeyGenParameterSpec;
 
-import sun.security.jca.JCAUtil;
 import sun.security.rsa.RSAKeyFactory;
 
 /**
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java
new file mode 100644
index 0000000..e74bfdb
--- /dev/null
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.crypto.pkcs11 {
+    // Depends on SunEC provider for EC related functionality
+    requires jdk.crypto.ec;
+    provides java.security.Provider with sun.security.pkcs11.SunPKCS11;
+}
+
diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java
index beed130..de0bef5 100644
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -1439,10 +1439,17 @@
                                    (defaultHandler,
                                    true,
                                    Thread.currentThread().getContextClassLoader());
+                        if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) {
+                            // not the right subtype
+                            if (debug != null) {
+                                debug.println("default handler " + defaultHandler +
+                                              " is not a CallbackHandler");
+                            }
+                            return null;
+                        }
                         return (CallbackHandler)c.newInstance();
                     }
                 });
-
                 // save it
                 pHandler = myHandler;
                 return myHandler;
diff --git a/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java b/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java
new file mode 100644
index 0000000..161c6fe
--- /dev/null
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.crypto.ucrypto {
+    provides java.security.Provider with com.oracle.security.ucrypto.UcryptoProvider;
+}
+
diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/module-info.java b/jdk/src/jdk.deploy.osx/macosx/classes/module-info.java
new file mode 100644
index 0000000..0242735
--- /dev/null
+++ b/jdk/src/jdk.deploy.osx/macosx/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.deploy.osx {
+    requires java.desktop;
+    requires java.scripting;
+}
+
diff --git a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/ExtractedImage.java b/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/ExtractedImage.java
deleted file mode 100644
index 5bfdb0a..0000000
--- a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/ExtractedImage.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jimage;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import jdk.internal.jimage.Archive;
-import jdk.internal.jimage.ImageFileCreator;
-import jdk.internal.jimage.ImageModuleData;
-import jdk.internal.jimage.ImageModuleDataWriter;
-
-/**
- *
- * Support for extracted image.
- */
-public final class ExtractedImage {
-
-    /**
-     * An Archive backed by a directory.
-     */
-    public class DirArchive implements Archive {
-
-        /**
-         * A File located in a Directory.
-         */
-        private class FileEntry extends Archive.Entry {
-
-            private final long size;
-            private final Path path;
-
-            FileEntry(Path path, String name) {
-                super(DirArchive.this, getPathName(path), name,
-                        Archive.Entry.EntryType.CLASS_OR_RESOURCE);
-                this.path = path;
-                try {
-                    size = Files.size(path);
-                } catch (IOException ex) {
-                    throw new RuntimeException(ex);
-                }
-            }
-
-            /**
-             * Returns the number of bytes of this file.
-             */
-            @Override
-            public long size() {
-                return size;
-            }
-
-            @Override
-            public InputStream stream() throws IOException {
-                InputStream stream = Files.newInputStream(path);
-                open.add(stream);
-                return stream;
-            }
-        }
-
-        private final Path dirPath;
-        private final String moduleName;
-        private final List<InputStream> open = new ArrayList<>();
-        private final int chop;
-
-        protected DirArchive(Path dirPath) throws IOException {
-            if (!Files.isDirectory(dirPath)) {
-                throw new IOException("Not a directory");
-            }
-            chop = dirPath.toString().length() + 1;
-            this.moduleName = dirPath.getFileName().toString();
-            this.dirPath = dirPath;
-        }
-
-        @Override
-        public String moduleName() {
-            return moduleName;
-        }
-
-        @Override
-        public Stream<Entry> entries() {
-            try {
-                return Files.walk(dirPath).map(this::toEntry).filter(n -> n != null);
-            } catch(IOException ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-
-        private Archive.Entry toEntry(Path p) {
-            if (Files.isDirectory(p)) {
-                return null;
-            }
-            String name = getPathName(p).substring(chop);
-            if (name.startsWith("_")) {
-                return null;
-            }
-            if (verbose) {
-                String verboseName = moduleName + "/" + name;
-                log.println(verboseName);
-            }
-
-            return new FileEntry(p, name);
-        }
-
-        @Override
-        public void close() throws IOException {
-            IOException e = null;
-            for (InputStream stream : open) {
-                try {
-                    stream.close();
-                } catch (IOException ex) {
-                    if (e == null) {
-                        e = ex;
-                    } else {
-                        e.addSuppressed(ex);
-                    }
-                }
-            }
-            if (e != null) {
-                throw e;
-            }
-        }
-
-        @Override
-        public void open() throws IOException {
-            // NOOP
-        }
-    }
-    private Map<String, Set<String>> modulePackages = new LinkedHashMap<>();
-    private Set<Archive> archives = new HashSet<>();
-    private final PrintWriter log;
-    private final boolean verbose;
-    private final String jdataName;
-    ExtractedImage(Path dirPath, PrintWriter log,
-            boolean verbose) throws IOException {
-        if (!Files.isDirectory(dirPath)) {
-            throw new IOException("Not a directory");
-        }
-        List<String> jdataNameHolder = new ArrayList<>();
-        Files.walk(dirPath, 1).forEach((p) -> {
-            try {
-                if (!dirPath.equals(p)) {
-                    String name = getPathName(p);
-                    if (name.endsWith(ImageModuleData.META_DATA_EXTENSION)) {
-                        jdataNameHolder.add(p.getFileName().toString());
-                        List<String> lines = Files.readAllLines(p);
-                        for (Entry<String, List<String>> entry
-                                : ImageModuleDataWriter.toModulePackages(lines).entrySet()) {
-                            Set<String> pkgs = new HashSet<>();
-                            pkgs.addAll(entry.getValue());
-                            modulePackages.put(entry.getKey(), pkgs);
-                        }
-                        modulePackages = Collections.unmodifiableMap(modulePackages);
-                    } else {
-                        if (Files.isDirectory(p)) {
-                            Archive a = new DirArchive(p);
-                            archives.add(a);
-                        }
-                    }
-                }
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            }
-        });
-        archives = Collections.unmodifiableSet(archives);
-        this.log = log;
-        this.verbose = verbose;
-        if (jdataNameHolder.size() != 1) {
-            throw new IOException("Wrong module information");
-        }
-        // The name of the metadata resource must be reused in the recreated jimage
-        String name = jdataNameHolder.get(0);
-        // Extension will be added when recreating the jimage
-        if (name.endsWith(ImageModuleData.META_DATA_EXTENSION)) {
-            name = name.substring(0, name.length()
-                    - ImageModuleData.META_DATA_EXTENSION.length());
-        }
-        jdataName = name;
-    }
-
-    void recreateJImage(Path path) throws IOException {
-
-        ImageFileCreator.recreateJimage(path, jdataName, archives, modulePackages);
-    }
-
-    private static String getPathName(Path path) {
-        return path.toString().replace(File.separatorChar, '/');
-    }
-}
diff --git a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java
deleted file mode 100644
index 077100f..0000000
--- a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jimage;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.FileChannel;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import static java.nio.file.StandardOpenOption.READ;
-import static java.nio.file.StandardOpenOption.WRITE;
-import java.util.LinkedList;
-import java.util.List;
-import jdk.internal.jimage.BasicImageReader;
-import jdk.internal.jimage.ImageHeader;
-import static jdk.internal.jimage.ImageHeader.MAGIC;
-import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION;
-import static jdk.internal.jimage.ImageHeader.MINOR_VERSION;
-import jdk.internal.jimage.ImageLocation;
-import jdk.internal.jimage.ImageModuleData;
-import jdk.internal.jimage.ImageResourcesTree;
-import jdk.tools.jimage.TaskHelper.BadArgs;
-import jdk.tools.jimage.TaskHelper.HiddenOption;
-import jdk.tools.jimage.TaskHelper.Option;
-import jdk.tools.jimage.TaskHelper.OptionsHelper;
-
-class JImageTask {
-
-    static final Option<?>[] recognizedOptions = {
-        new Option<JImageTask>(true, "--dir") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) throws BadArgs {
-                 task.options.directory = arg;
-            }
-        },
-        new HiddenOption<JImageTask>(false, "--fullversion") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) {
-                task.options.fullVersion = true;
-            }
-        },
-        new Option<JImageTask>(false, "--help") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) {
-                task.options.help = true;
-            }
-        },
-
-        new Option<JImageTask>(true, "--flags") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) {
-                task.options.flags = arg;
-            }
-        },
-
-        new Option<JImageTask>(false, "--verbose") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) throws BadArgs {
-                 task.options.verbose = true;
-            }
-        },
-        new Option<JImageTask>(false, "--version") {
-            @Override
-            protected void process(JImageTask task, String opt, String arg) {
-                task.options.version = true;
-            }
-        },
-    };
-    private static final TaskHelper taskHelper
-            = new TaskHelper("jdk.tools.jimage.resources.jimage");
-    private static final OptionsHelper<JImageTask> optionsHelper
-            = taskHelper.newOptionsHelper(JImageTask.class, recognizedOptions);
-
-    static class OptionsValues {
-        Task task = Task.LIST;
-        String directory = ".";
-        boolean fullVersion;
-        boolean help;
-        String flags;
-        boolean verbose;
-        boolean version;
-        List<File> jimages = new LinkedList<>();
-    }
-
-    private static final String PROGNAME = "jimage";
-    private final OptionsValues options = new OptionsValues();
-
-    enum Task {
-        EXTRACT,
-        INFO,
-        LIST,
-        RECREATE,
-        SET,
-        VERIFY
-    };
-
-    private String pad(String string, int width, boolean justifyRight) {
-        int length = string.length();
-
-        if (length == width) {
-            return string;
-        }
-
-        if (length > width) {
-            return string.substring(0, width);
-        }
-
-        int padding = width - length;
-
-        StringBuilder sb = new StringBuilder(width);
-        if (justifyRight) {
-            for (int i = 0; i < padding; i++) {
-                sb.append(' ');
-            }
-        }
-
-        sb.append(string);
-
-        if (!justifyRight) {
-            for (int i = 0; i < padding; i++) {
-                sb.append(' ');
-            }
-        }
-
-        return sb.toString();
-    }
-
-    private String pad(String string, int width) {
-        return pad(string, width, false);
-    }
-
-    private String pad(long value, int width) {
-        return pad(Long.toString(value), width, true);
-    }
-
-    private static final int EXIT_OK = 0;        // No errors.
-    private static final int EXIT_ERROR = 1;     // Completed but reported errors.
-    private static final int EXIT_CMDERR = 2;    // Bad command-line arguments and/or switches.
-    private static final int EXIT_SYSERR = 3;    // System error or resource exhaustion.
-    private static final int EXIT_ABNORMAL = 4;  // Terminated abnormally.
-
-    int run(String[] args) {
-        if (log == null) {
-            setLog(new PrintWriter(System.out));
-        }
-
-        try {
-            List<String> unhandled = optionsHelper.handleOptions(this, args);
-            if(!unhandled.isEmpty()) {
-                options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase());
-                for(int i = 1; i < unhandled.size(); i++) {
-                    options.jimages.add(new File(unhandled.get(i)));
-                }
-            }
-            if (options.help) {
-                optionsHelper.showHelp(PROGNAME, "recreate only options:");
-            }
-            if (options.version || options.fullVersion) {
-                taskHelper.showVersion(options.fullVersion);
-            }
-            boolean ok = run();
-            return ok ? EXIT_OK : EXIT_ERROR;
-        } catch (BadArgs e) {
-            taskHelper.reportError(e.key, e.args);
-            if (e.showUsage) {
-                log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
-            }
-            return EXIT_CMDERR;
-        } catch (Exception x) {
-            x.printStackTrace();
-            return EXIT_ABNORMAL;
-        } finally {
-            log.flush();
-        }
-    }
-
-    private void recreate() throws IOException, BadArgs {
-        File directory = new File(options.directory);
-        if (!directory.isDirectory()) {
-            throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath());
-        }
-        Path dirPath = directory.toPath();
-        if (options.jimages.isEmpty()) {
-            throw taskHelper.newBadArgs("err.jimage.not.specified");
-        } else if (options.jimages.size() != 1) {
-            throw taskHelper.newBadArgs("err.only.one.jimage");
-        }
-
-        Path jimage = options.jimages.get(0).toPath();
-
-        if (jimage.toFile().createNewFile()) {
-            ExtractedImage img = new ExtractedImage(dirPath, log, options.verbose);
-            img.recreateJImage(jimage);
-        } else {
-            throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName());
-        }
-    }
-
-    private void title(File file, BasicImageReader reader) {
-        log.println("jimage: " + file.getName());
-    }
-
-    private void listTitle(File file, BasicImageReader reader) {
-        title(file, reader);
-
-        if (options.verbose) {
-            log.print(pad("Offset", OFFSET_WIDTH + 1));
-            log.print(pad("Size", SIZE_WIDTH + 1));
-            log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1));
-            log.println(" Entry");
-        }
-    }
-
-    private interface JImageAction {
-        public void apply(File file, BasicImageReader reader) throws IOException, BadArgs;
-    }
-
-    private interface ResourceAction {
-        public void apply(BasicImageReader reader, String name,
-                ImageLocation location) throws IOException, BadArgs;
-    }
-
-    private void extract(BasicImageReader reader, String name,
-            ImageLocation location) throws IOException, BadArgs {
-        File directory = new File(options.directory);
-        byte[] bytes = reader.getResource(location);
-        File resource =  new File(directory, name);
-        File parent = resource.getParentFile();
-
-        if (parent.exists()) {
-            if (!parent.isDirectory()) {
-                throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath());
-            }
-        } else if (!parent.mkdirs()) {
-            throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath());
-        }
-
-        if (name.endsWith(ImageModuleData.META_DATA_EXTENSION)) {
-            ImageModuleData imageModuleData = new ImageModuleData(reader, bytes);
-            List<String> lines = imageModuleData.fromModulePackages();
-            Files.write(resource.toPath(), lines);
-        } else {
-            if (!ImageResourcesTree.isTreeInfoResource(name)) {
-                Files.write(resource.toPath(), bytes);
-            }
-        }
-    }
-
-    private static final int NUMBER_WIDTH = 12;
-    private static final int OFFSET_WIDTH = NUMBER_WIDTH;
-    private static final int SIZE_WIDTH = NUMBER_WIDTH;
-    private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH;
-
-    private void print(String entry, ImageLocation location) {
-        log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " ");
-        log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " ");
-        log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " ");
-        log.println(entry);
-    }
-
-    private void print(BasicImageReader reader, String entry) {
-        if (options.verbose) {
-            print(entry, reader.findLocation(entry));
-        } else {
-            log.println(entry);
-        }
-    }
-
-    private void info(File file, BasicImageReader reader) throws IOException {
-        ImageHeader header = reader.getHeader();
-
-        log.println(" Major Version:  " + header.getMajorVersion());
-        log.println(" Minor Version:  " + header.getMinorVersion());
-        log.println(" Flags:          " + Integer.toHexString(header.getMinorVersion()));
-        log.println(" Resource Count: " + header.getResourceCount());
-        log.println(" Table Length:   " + header.getTableLength());
-        log.println(" Offsets Size:   " + header.getOffsetsSize());
-        log.println(" Redirects Size: " + header.getRedirectSize());
-        log.println(" Locations Size: " + header.getLocationsSize());
-        log.println(" Strings Size:   " + header.getStringsSize());
-        log.println(" Index Size:     " + header.getIndexSize());
-    }
-
-    private void list(BasicImageReader reader, String name, ImageLocation location) {
-        print(reader, name);
-    }
-
-    void set(File file, BasicImageReader reader) throws BadArgs {
-        try {
-            ImageHeader oldHeader = reader.getHeader();
-
-            int value = 0;
-            try {
-                value = Integer.valueOf(options.flags);
-            } catch (NumberFormatException ex) {
-                throw taskHelper.newBadArgs("err.flags.not.int", options.flags);
-            }
-
-            ImageHeader newHeader = new ImageHeader(MAGIC, MAJOR_VERSION, MINOR_VERSION,
-                    value,
-                    oldHeader.getResourceCount(), oldHeader.getTableLength(),
-                    oldHeader.getLocationsSize(), oldHeader.getStringsSize());
-
-            ByteBuffer buffer = ByteBuffer.allocate(ImageHeader.getHeaderSize());
-            buffer.order(ByteOrder.nativeOrder());
-            newHeader.writeTo(buffer);
-            buffer.rewind();
-
-            try (FileChannel channel = FileChannel.open(file.toPath(), READ, WRITE)) {
-                channel.write(buffer, 0);
-            }
-        } catch (IOException ex) {
-            throw taskHelper.newBadArgs("err.cannot.update.file", file.getName());
-        }
-    }
-
-     void verify(BasicImageReader reader, String name, ImageLocation location) {
-        if (name.endsWith(".class")) {
-            byte[] bytes = reader.getResource(location);
-
-            if (bytes == null || bytes.length <= 4 ||
-                (bytes[0] & 0xFF) != 0xCA ||
-                (bytes[1] & 0xFF) != 0xFE ||
-                (bytes[2] & 0xFF) != 0xBA ||
-                (bytes[3] & 0xFF) != 0xBE) {
-                log.print(" NOT A CLASS: ");
-                print(reader, name);
-            }
-        }
-    }
-
-    private void iterate(JImageAction jimageAction,
-            ResourceAction resourceAction) throws IOException, BadArgs {
-        for (File file : options.jimages) {
-            if (!file.exists() || !file.isFile()) {
-                throw taskHelper.newBadArgs("err.not.a.jimage", file.getName());
-            }
-
-            String path = file.getCanonicalPath();
-            BasicImageReader reader = BasicImageReader.open(path);
-
-            if (jimageAction != null) {
-                jimageAction.apply(file, reader);
-            }
-
-            if (resourceAction != null) {
-                String[] entryNames = reader.getEntryNames();
-
-                for (String name : entryNames) {
-                    if (!ImageResourcesTree.isTreeInfoResource(name)) {
-                        ImageLocation location = reader.findLocation(name);
-                        resourceAction.apply(reader, name, location);
-                    }
-                }
-            }
-       }
-    }
-
-    private boolean run() throws IOException, BadArgs {
-        switch (options.task) {
-            case EXTRACT:
-                iterate(null, this::extract);
-                break;
-            case INFO:
-                iterate(this::info, null);
-                break;
-            case LIST:
-                iterate(this::listTitle, this::list);
-                break;
-            case RECREATE:
-                recreate();
-                break;
-            case SET:
-                iterate(this::set, null);
-                break;
-            case VERIFY:
-                iterate(this::title, this::verify);
-                break;
-            default:
-                throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true);
-        }
-        return true;
-    }
-
-    private PrintWriter log;
-    void setLog(PrintWriter out) {
-        log = out;
-        taskHelper.setLog(log);
-    }
-}
diff --git a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/TaskHelper.java b/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/TaskHelper.java
deleted file mode 100644
index db4f4e1..0000000
--- a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/TaskHelper.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.tools.jimage;
-
-import java.io.PrintWriter;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-
-/**
- *
- * JImage tools shared helper.
- */
-public final class TaskHelper {
-
-    public class BadArgs extends Exception {
-
-        static final long serialVersionUID = 8765093759964640721L;
-
-        private BadArgs(String key, Object... args) {
-            super(bundleHelper.getMessage(key, args));
-            this.key = key;
-            this.args = args;
-        }
-
-        public BadArgs showUsage(boolean b) {
-            showUsage = b;
-            return this;
-        }
-        public final String key;
-        public final Object[] args;
-        public boolean showUsage;
-    }
-
-    public static abstract class Option<T> {
-
-        final boolean hasArg;
-        final String[] aliases;
-
-        public Option(boolean hasArg, String... aliases) {
-            this.hasArg = hasArg;
-            this.aliases = aliases;
-        }
-
-        public boolean isHidden() {
-            return false;
-        }
-
-        public boolean matches(String opt) {
-            for (String a : aliases) {
-                if (a.equals(opt)) {
-                    return true;
-                } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public boolean ignoreRest() {
-            return false;
-        }
-
-        protected abstract void process(T task, String opt, String arg) throws BadArgs;
-    }
-
-    public static abstract class HiddenOption<T> extends Option<T> {
-
-        public HiddenOption(boolean hasArg, String... aliases) {
-            super(hasArg, aliases);
-        }
-
-        @Override
-        public boolean isHidden() {
-            return true;
-        }
-    }
-
-    private class ResourceBundleHelper {
-
-        private final ResourceBundle bundle;
-
-        ResourceBundleHelper(String path) {
-            Locale locale = Locale.getDefault();
-            try {
-                bundle = ResourceBundle.getBundle(path, locale);
-            } catch (MissingResourceException e) {
-                throw new InternalError("Cannot find resource bundle for locale " + locale);
-            }
-        }
-
-        String getMessage(String key, Object... args) {
-            String val = bundle.getString(key);
-            return MessageFormat.format(val, args);
-        }
-
-    }
-
-    public class OptionsHelper<T> {
-
-        private final List<Option<T>> options;
-
-        OptionsHelper(List<Option<T>> options) {
-            this.options = options;
-        }
-
-        public List<String> handleOptions(T task, String[] args) throws BadArgs {
-            List<String> rest = new ArrayList<>();
-            // process options
-            for (int i = 0; i < args.length; i++) {
-                if (args[i].charAt(0) == '-') {
-                    String name = args[i];
-                    Option<T> option = getOption(name);
-                    if (option == null) {
-                        throw new BadArgs("err.unknown.option", name).showUsage(true);
-                    }
-                    String param = null;
-                    if (option.hasArg) {
-                        if (name.startsWith("--") && name.indexOf('=') > 0) {
-                            param = name.substring(name.indexOf('=') + 1, name.length());
-                        } else if (i + 1 < args.length) {
-                            param = args[++i];
-                        }
-                        if (param == null || param.isEmpty() || param.charAt(0) == '-') {
-                            throw new BadArgs("err.missing.arg", name).showUsage(true);
-                        }
-                    }
-                    option.process(task, name, param);
-                    if (option.ignoreRest()) {
-                        i = args.length;
-                    }
-                } else {
-                    rest.add(args[i]);
-                }
-            }
-            return rest;
-        }
-
-        private Option<T> getOption(String name) throws BadArgs {
-            for (Option<T> o : options) {
-                if (o.matches(name)) {
-                    return o;
-                }
-            }
-            return null;
-        }
-
-        public void showHelp(String progName, String pluginsHeader) {
-            log.println(bundleHelper.getMessage("main.usage", progName));
-            for (Option<?> o : options) {
-                String name = o.aliases[0].substring(1); // there must always be at least one name
-                name = name.charAt(0) == '-' ? name.substring(1) : name;
-                if (o.isHidden() || name.equals("h")) {
-                    continue;
-                }
-                log.println(bundleHelper.getMessage("main.opt." + name));
-            }
-        }
-    }
-
-    private PrintWriter log;
-    private final ResourceBundleHelper bundleHelper;
-
-    public TaskHelper(String path) {
-        this.bundleHelper = new ResourceBundleHelper(path);
-    }
-
-    public <T> OptionsHelper<T> newOptionsHelper(Class<T> clazz, Option<?>[] options) {
-        List<Option<T>> optionsList = new ArrayList<>();
-        for (Option<?> o : options) {
-            @SuppressWarnings("unchecked")
-            Option<T> opt = (Option<T>) o;
-            optionsList.add(opt);
-        }
-        return new OptionsHelper<>(optionsList);
-    }
-
-    public BadArgs newBadArgs(String key, Object... args) {
-        return new BadArgs(key, args);
-    }
-
-    public String getMessage(String key, Object... args) {
-        return bundleHelper.getMessage(key, args);
-    }
-
-    public void setLog(PrintWriter log) {
-        this.log = log;
-    }
-
-    public void reportError(String key, Object... args) {
-        log.println(bundleHelper.getMessage("error.prefix") + " " + bundleHelper.getMessage(key, args));
-    }
-
-    public void warning(String key, Object... args) {
-        log.println(bundleHelper.getMessage("warn.prefix") + " " + bundleHelper.getMessage(key, args));
-    }
-
-    public void showVersion(boolean full) {
-        log.println(version(full ? "full" : "release"));
-    }
-
-    public String version(String key) {
-        return System.getProperty("java.version");
-    }
-
-}
diff --git a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/resources/jimage.properties
deleted file mode 100644
index 27ba361..0000000
--- a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/resources/jimage.properties
+++ /dev/null
@@ -1,51 +0,0 @@
-main.usage.summary=\
-Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\
-use --help for a list of possible options
-
-main.usage=\
-Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\
-\n\
-\  extract  - Extract all jimage entries into separate files into the directory\n\
-\             specified by --dir=<directory> (default='.')\n\
-\  info     - Prints information specified in the jimage header.\n\
-\  list     - Prints the names of all the entries in the jimage.  When used with\n\
-\             --verbose will also print entry attributes ex. size and offset.\n\
-\  recreate - Reconstructs a jimage from an extracted directory (--dir)\n\
-\  set      - sets the value of specific jimage header entries\n\
-\  verify   - Reports errors on any .class entries that don't verify as classes.\n\
-\n\
-Possible options include:
-
-error.prefix=Error:
-warn.prefix=Warning:
-
-main.opt.dir=\
-\  --dir                                Target directory for extract/recreate
-
-main.opt.flags=\
-\  --flags=value                        Set the jimage flags to value
-
-main.opt.help=\
-\  --help                               Print this usage message
-
-main.opt.verbose=\
-\  --verbose                            Verbose listing
-
-main.opt.version=\
-\  --version                            Version information
-
-err.cannot.create.dir=cannot create directory: {0}
-err.cannot.read.file=cannot read file: {0}
-err.cannot.update.file=cannot update file: {0}
-err.flags.not.int=--flags value not integer: {0}
-err.internal.error=internal error: {0} {1} {2}
-err.invalid.arg.for.option=invalid argument for option: {0}
-err.invalid.task=task must be extract|recreate|info|list|verify: {0}
-err.jimage.already.exists=jimage already exists: {0}
-err.jimage.not.specified=no jimage specified
-err.missing.arg=no value given for {0}
-err.not.a.dir=not a directory: {0}
-err.not.a.jimage=not a jimage file: {0}
-err.only.one.jimage=only one jimage should be specified
-err.option.unsupported={0} not supported: {1}
-err.unknown.option=unknown option: {0}
diff --git a/jdk/src/jdk.httpserver/share/classes/module-info.java b/jdk/src/jdk.httpserver/share/classes/module-info.java
new file mode 100644
index 0000000..3956628
--- /dev/null
+++ b/jdk/src/jdk.httpserver/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.httpserver {
+    requires java.logging;
+    exports com.sun.net.httpserver;
+    exports com.sun.net.httpserver.spi;
+    uses com.sun.net.httpserver.spi.HttpServerProvider;
+}
+
diff --git a/jdk/src/jdk.internal.le/share/classes/module-info.java b/jdk/src/jdk.internal.le/share/classes/module-info.java
new file mode 100644
index 0000000..b4ae508
--- /dev/null
+++ b/jdk/src/jdk.internal.le/share/classes/module-info.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.internal.le {
+    exports jdk.internal.jline to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.jline.console to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.jline.console.completer to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.jline.console.history to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+    exports jdk.internal.jline.internal to
+        jdk.scripting.nashorn.shell,
+        jdk.jshell;
+}
+
diff --git a/jdk/src/jdk.internal.opt/share/classes/module-info.java b/jdk/src/jdk.internal.opt/share/classes/module-info.java
new file mode 100644
index 0000000..9c8f889
--- /dev/null
+++ b/jdk/src/jdk.internal.opt/share/classes/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.internal.opt {
+    exports jdk.internal.joptsimple to jdk.jlink;
+}
diff --git a/jdk/src/jdk.jartool/share/classes/module-info.java b/jdk/src/jdk.jartool/share/classes/module-info.java
new file mode 100644
index 0000000..cbf7032
--- /dev/null
+++ b/jdk/src/jdk.jartool/share/classes/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jartool {
+    exports com.sun.jarsigner;
+    exports jdk.security.jarsigner;
+}
+
diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java
new file mode 100644
index 0000000..6c97d25
--- /dev/null
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleDescriptor.Version;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Parser for GNU Style Options.
+ */
+class GNUStyleOptions {
+
+    static class BadArgs extends Exception {
+        static final long serialVersionUID = 0L;
+
+        boolean showUsage;
+
+        BadArgs(String key, String arg) { super(Main.formatMsg(key, arg)); }
+        BadArgs(String key) { super(Main.getMsg(key)); }
+
+        BadArgs showUsage(boolean b) {
+            showUsage = b;
+            return this;
+        }
+    }
+
+    static Option[] recognizedOptions = {
+            // Main operations
+            new Option(false, OptionType.MAIN_OPERATION, "--create", "-c") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.iflag || tool.tflag || tool.uflag || tool.xflag || tool.printModuleDescriptor)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.cflag = true;
+                }
+            },
+            new Option(true, OptionType.MAIN_OPERATION, "--generate-index", "-i") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.cflag || tool.tflag || tool.uflag || tool.xflag || tool.printModuleDescriptor)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.iflag = true;
+                    tool.rootjar = arg;
+                }
+            },
+            new Option(false, OptionType.MAIN_OPERATION, "--list", "-t") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.cflag || tool.iflag || tool.uflag || tool.xflag || tool.printModuleDescriptor)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.tflag = true;
+                }
+            },
+            new Option(false, OptionType.MAIN_OPERATION, "--update", "-u") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.cflag || tool.iflag || tool.tflag || tool.xflag || tool.printModuleDescriptor)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.uflag = true;
+                }
+            },
+            new Option(false, OptionType.MAIN_OPERATION, "--extract", "-x") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.cflag || tool.iflag  || tool.tflag || tool.uflag || tool.printModuleDescriptor)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.xflag = true;
+                }
+            },
+            new Option(false, OptionType.MAIN_OPERATION, "--print-module-descriptor", "-p") {
+                void process(Main tool, String opt, String arg) throws BadArgs {
+                    if (tool.cflag || tool.iflag  || tool.tflag || tool.uflag || tool.xflag)
+                        throw new BadArgs("error.multiple.main.operations").showUsage(true);
+                    tool.printModuleDescriptor = true;
+                }
+            },
+
+            // Additional options
+            new Option(true, OptionType.ANY, "--file", "-f") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.fname = arg;
+                }
+            },
+            new Option(false, OptionType.ANY, "--verbose", "-v") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.vflag = true;
+                }
+            },
+            new Option(false, OptionType.CREATE, "--normalize", "-n") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.nflag = true;
+                }
+                boolean isHidden() { return true; }
+            },
+            new Option(true, OptionType.CREATE_UPDATE, "--main-class", "-e") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.ename = arg;
+                }
+            },
+            new Option(true, OptionType.CREATE_UPDATE, "--manifest", "-m") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.mname = arg;
+                }
+            },
+            new Option(false, OptionType.CREATE_UPDATE, "--no-manifest", "-M") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.Mflag = true;
+                }
+            },
+            new Option(true, OptionType.CREATE_UPDATE, "--module-version") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.moduleVersion = Version.parse(arg);
+                }
+            },
+            new Option(true, OptionType.CREATE_UPDATE, "--hash-dependencies") {
+                void process(Main jartool, String opt, String arg) throws BadArgs {
+                    try {
+                        jartool.dependenciesToHash = Pattern.compile(arg);
+                    } catch (PatternSyntaxException e) {
+                        throw new BadArgs("err.badpattern", arg).showUsage(true);
+                    }
+                }
+            },
+            new Option(true, OptionType.CREATE_UPDATE, "--modulepath", "--mp") {
+                void process(Main jartool, String opt, String arg) {
+                    String[] dirs = arg.split(File.pathSeparator);
+                    Path[] paths = new Path[dirs.length];
+                    int i = 0;
+                    for (String dir : dirs) {
+                        paths[i++] = Paths.get(dir);
+                    }
+                    jartool.moduleFinder = ModuleFinder.compose(jartool.moduleFinder,
+                                                                ModuleFinder.of(paths));
+                }
+            },
+            new Option(false, OptionType.CREATE_UPDATE_INDEX, "--no-compress", "-0") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.flag0 = true;
+                }
+            },
+
+            // Hidden options
+            new Option(false, OptionType.OTHER, "-P") {
+                void process(Main jartool, String opt, String arg) {
+                    jartool.pflag = true;
+                }
+                boolean isHidden() { return true; }
+            },
+
+            // Other options
+            new Option(true, true, OptionType.OTHER, "--help", "-h") {
+                void process(Main jartool, String opt, String arg) throws BadArgs {
+                    if (jartool.info == null) {
+                        if (arg == null) {
+                            jartool.info = Main.Info.HELP;
+                            return;
+                        }
+
+                        if (!arg.equals("compat"))
+                            throw new BadArgs("error.illegal.option", arg).showUsage(true);
+
+                        jartool.info = Main.Info.COMPAT_HELP;
+                    }
+                }
+            },
+            new Option(false, OptionType.OTHER, "--version") {
+                void process(Main jartool, String opt, String arg) {
+                    if (jartool.info == null)
+                        jartool.info = Main.Info.VERSION;
+                }
+            }
+    };
+
+    enum OptionType {
+        MAIN_OPERATION("main"),
+        ANY("any"),
+        CREATE("create"),
+        CREATE_UPDATE("create.update"),
+        CREATE_UPDATE_INDEX("create.update.index"),
+        OTHER("other");
+
+        /** Resource lookup section prefix. */
+        final String name;
+
+        OptionType(String name) { this.name = name; }
+    }
+
+    static abstract class Option {
+        final boolean hasArg;
+        final boolean argIsOptional;
+        final String[] aliases;
+        final OptionType type;
+
+        Option(boolean hasArg, OptionType type, String... aliases) {
+            this(hasArg, false, type, aliases);
+        }
+
+        Option(boolean hasArg, boolean argIsOptional, OptionType type, String... aliases) {
+            this.hasArg = hasArg;
+            this.argIsOptional = argIsOptional;
+            this.type = type;
+            this.aliases = aliases;
+        }
+
+        boolean isHidden() { return false; }
+
+        boolean matches(String opt) {
+            for (String a : aliases) {
+                if (a.equals(opt)) {
+                    return true;
+                } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
+                    return true;
+                } else if (opt.startsWith("--help") && opt.startsWith(a + ":")) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        abstract void process(Main jartool, String opt, String arg) throws BadArgs;
+    }
+
+    static int parseOptions(Main jartool, String[] args) throws BadArgs {
+        int count = 0;
+        if (args.length == 0) {
+            jartool.info = Main.Info.USAGE_SUMMARY;
+            return 0;
+        }
+
+        // process options
+        for (; count < args.length; count++) {
+            if (args[count].charAt(0) != '-' || args[count].equals("-C"))
+                break;
+
+            String name = args[count];
+            Option option = getOption(name);
+            String param = null;
+            if (option.hasArg) {
+                if (name.startsWith("--help")) {  // "special" optional separator
+                    if (name.indexOf(':') > 0) {
+                        param = name.substring(name.indexOf(':') + 1, name.length());
+                    }
+                } else if (name.startsWith("--") && name.indexOf('=') > 0) {
+                    param = name.substring(name.indexOf('=') + 1, name.length());
+                } else if (count + 1 < args.length) {
+                    param = args[++count];
+                }
+                if (!option.argIsOptional &&
+                    (param == null || param.isEmpty() || param.charAt(0) == '-')) {
+                    throw new BadArgs("error.missing.arg", name).showUsage(true);
+                }
+            }
+            option.process(jartool, name, param);
+        }
+
+        return count;
+    }
+
+    private static Option getOption(String name) throws BadArgs {
+        for (Option o : recognizedOptions) {
+            if (o.matches(name)) {
+                return o;
+            }
+        }
+        throw new BadArgs("error.unrecognized.option", name).showUsage(true);
+    }
+
+    static void printHelp(PrintStream out) {
+        out.format("%s%n", Main.getMsg("main.help.preopt"));
+        for (OptionType type : OptionType.values()) {
+            boolean typeHeadingWritten = false;
+
+            for (Option o : recognizedOptions) {
+                if (!o.type.equals(type))
+                    continue;
+                String name = o.aliases[0].substring(1); // there must always be at least one name
+                name = name.charAt(0) == '-' ? name.substring(1) : name;
+                if (o.isHidden() || name.equals("h")) {
+                    continue;
+                }
+                if (!typeHeadingWritten) {
+                    out.format("%n%s%n", Main.getMsg("main.help.opt." + type.name));
+                    typeHeadingWritten = true;
+                }
+                out.format("%s%n", Main.getMsg("main.help.opt." + type.name + "." + name));
+            }
+        }
+        out.format("%n%s%n%n", Main.getMsg("main.help.postopt"));
+    }
+
+    static void printCompatHelp(PrintStream out) {
+        out.format("%s%n", Main.getMsg("usage.compat"));
+    }
+
+    static void printUsageSummary(PrintStream out) {
+        out.format("%s%n", Main.getMsg("main.usage.summary"));
+        out.format("%s%n", Main.getMsg("main.usage.summary.try"));
+    }
+
+    static void printVersion(PrintStream out) {
+        out.format("%s %s%n", "jar", System.getProperty("java.version"));
+    }
+}
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 32bffba..be2882d 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,17 +26,35 @@
 package sun.tools.jar;
 
 import java.io.*;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Method;
+import java.net.URI;
 import java.nio.file.Path;
 import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.*;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.zip.*;
 import java.util.jar.*;
 import java.util.jar.Pack200.*;
 import java.util.jar.Manifest;
 import java.text.MessageFormat;
+
+import jdk.internal.module.Hasher;
+import jdk.internal.module.ModuleInfoExtender;
 import sun.misc.JarIndex;
 import static sun.misc.JarIndex.INDEX_NAME;
 import static java.util.jar.JarFile.MANIFEST_NAME;
+import static java.util.stream.Collectors.joining;
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 
 /**
@@ -60,6 +78,11 @@
 
     // All files need to be added/updated.
     Set<File> entries = new LinkedHashSet<File>();
+    // All packages.
+    Set<String> packages = new HashSet<>();
+    // All actual entries added, or existing, in the jar file ( excl manifest
+    // and module-info.class ). Populated during create or update.
+    Set<String> jarEntries = new HashSet<>();
 
     // Directories specified by "-C" operation.
     Set<String> paths = new HashSet<String>();
@@ -78,6 +101,30 @@
      */
     boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag;
 
+    /* To support additional GNU Style informational options */
+    enum Info {
+        HELP(GNUStyleOptions::printHelp),
+        COMPAT_HELP(GNUStyleOptions::printCompatHelp),
+        USAGE_SUMMARY(GNUStyleOptions::printUsageSummary),
+        VERSION(GNUStyleOptions::printVersion);
+
+        private Consumer<PrintStream> printFunction;
+        Info(Consumer<PrintStream> f) { this.printFunction = f; }
+        void print(PrintStream out) { printFunction.accept(out); }
+    };
+    Info info;
+
+    /* Modular jar related options */
+    boolean printModuleDescriptor;
+    Version moduleVersion;
+    Pattern dependenciesToHash;
+    ModuleFinder moduleFinder = ModuleFinder.empty();
+
+    private static final String MODULE_INFO = "module-info.class";
+
+    Path moduleInfo;
+    private boolean isModularJar() { return moduleInfo != null; }
+
     static final String MANIFEST_DIR = "META-INF/";
     static final String VERSION = "1.0";
 
@@ -102,7 +149,7 @@
         }
     }
 
-    private String getMsg(String key) {
+    static String getMsg(String key) {
         try {
             return (rsrc.getString(key));
         } catch (MissingResourceException e) {
@@ -110,14 +157,14 @@
         }
     }
 
-    private String formatMsg(String key, String arg) {
+    static String formatMsg(String key, String arg) {
         String msg = getMsg(key);
         String[] args = new String[1];
         args[0] = arg;
         return MessageFormat.format(msg, (Object[]) args);
     }
 
-    private String formatMsg2(String key, String arg, String arg1) {
+    static String formatMsg2(String key, String arg, String arg1) {
         String msg = getMsg(key);
         String[] args = new String[2];
         args[0] = arg;
@@ -189,6 +236,16 @@
                     }
                 }
                 expand(null, files, false);
+
+                byte[] moduleInfoBytes = null;
+                if (isModularJar()) {
+                    moduleInfoBytes = addExtendedModuleAttributes(
+                            readModuleInfo(moduleInfo));
+                } else if (moduleVersion != null || dependenciesToHash != null) {
+                    error(getMsg("error.module.options.without.info"));
+                    return false;
+                }
+
                 OutputStream out;
                 if (fname != null) {
                     out = new FileOutputStream(fname);
@@ -210,7 +267,14 @@
                     tmpfile = createTemporaryFile(tmpbase, ".jar");
                     out = new FileOutputStream(tmpfile);
                 }
-                create(new BufferedOutputStream(out, 4096), manifest);
+                create(new BufferedOutputStream(out, 4096), manifest, moduleInfoBytes);
+
+                // Consistency checks for modular jars.
+                if (isModularJar()) {
+                    if (!checkServices(moduleInfoBytes))
+                        return false;
+                }
+
                 if (in != null) {
                     in.close();
                 }
@@ -267,8 +331,21 @@
                 InputStream manifest = (!Mflag && (mname != null)) ?
                     (new FileInputStream(mname)) : null;
                 expand(null, files, true);
+
+                byte[] moduleInfoBytes = null;
+                if (isModularJar()) {
+                    moduleInfoBytes = readModuleInfo(moduleInfo);
+                }
+
                 boolean updateOk = update(in, new BufferedOutputStream(out),
-                                          manifest, null);
+                                          manifest, moduleInfoBytes, null);
+
+                // Consistency checks for modular jars.
+                if (isModularJar()) {
+                    if(!checkServices(moduleInfoBytes))
+                        return false;
+                }
+
                 if (ok) {
                     ok = updateOk;
                 }
@@ -328,6 +405,17 @@
                 }
             } else if (iflag) {
                 genIndex(rootjar, files);
+            } else if (printModuleDescriptor) {
+                boolean found;
+                if (fname != null) {
+                    found = printModuleDescriptor(new ZipFile(fname));
+                } else {
+                    try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
+                        found = printModuleDescriptor(fin);
+                    }
+                }
+                if (!found)
+                    error(getMsg("error.module.descriptor.not.found"));
             }
         } catch (IOException e) {
             fatalError(e);
@@ -362,84 +450,111 @@
         int count = 1;
         try {
             String flags = args[0];
-            if (flags.startsWith("-")) {
-                flags = flags.substring(1);
-            }
-            for (int i = 0; i < flags.length(); i++) {
-                switch (flags.charAt(i)) {
-                case 'c':
-                    if (xflag || tflag || uflag || iflag) {
-                        usageError();
-                        return false;
+
+            // Note: flags.length == 2 can be treated as the short version of
+            // the GNU option since the there cannot be any other options,
+            // excluding -C, as per the old way.
+            if (flags.startsWith("--")
+                || (flags.startsWith("-") && flags.length() == 2)) {
+                try {
+                    count = GNUStyleOptions.parseOptions(this, args);
+                } catch (GNUStyleOptions.BadArgs x) {
+                    if (info != null) {
+                        info.print(out);
+                        return true;
                     }
-                    cflag = true;
-                    break;
-                case 'u':
-                    if (cflag || xflag || tflag || iflag) {
-                        usageError();
-                        return false;
-                    }
-                    uflag = true;
-                    break;
-                case 'x':
-                    if (cflag || uflag || tflag || iflag) {
-                        usageError();
-                        return false;
-                    }
-                    xflag = true;
-                    break;
-                case 't':
-                    if (cflag || uflag || xflag || iflag) {
-                        usageError();
-                        return false;
-                    }
-                    tflag = true;
-                    break;
-                case 'M':
-                    Mflag = true;
-                    break;
-                case 'v':
-                    vflag = true;
-                    break;
-                case 'f':
-                    fname = args[count++];
-                    break;
-                case 'm':
-                    mname = args[count++];
-                    break;
-                case '0':
-                    flag0 = true;
-                    break;
-                case 'i':
-                    if (cflag || uflag || xflag || tflag) {
-                        usageError();
-                        return false;
-                    }
-                    // do not increase the counter, files will contain rootjar
-                    rootjar = args[count++];
-                    iflag = true;
-                    break;
-                case 'n':
-                    nflag = true;
-                    break;
-                case 'e':
-                     ename = args[count++];
-                     break;
-                case 'P':
-                     pflag = true;
-                     break;
-                default:
-                    error(formatMsg("error.illegal.option",
-                                String.valueOf(flags.charAt(i))));
-                    usageError();
+                    error(x.getMessage());
+                    if (x.showUsage)
+                        Info.USAGE_SUMMARY.print(err);
                     return false;
                 }
+            } else {
+                // Legacy/compatibility options
+                if (flags.startsWith("-")) {
+                    flags = flags.substring(1);
+                }
+                for (int i = 0; i < flags.length(); i++) {
+                    switch (flags.charAt(i)) {
+                        case 'c':
+                            if (xflag || tflag || uflag || iflag) {
+                                usageError();
+                                return false;
+                            }
+                            cflag = true;
+                            break;
+                        case 'u':
+                            if (cflag || xflag || tflag || iflag) {
+                                usageError();
+                                return false;
+                            }
+                            uflag = true;
+                            break;
+                        case 'x':
+                            if (cflag || uflag || tflag || iflag) {
+                                usageError();
+                                return false;
+                            }
+                            xflag = true;
+                            break;
+                        case 't':
+                            if (cflag || uflag || xflag || iflag) {
+                                usageError();
+                                return false;
+                            }
+                            tflag = true;
+                            break;
+                        case 'M':
+                            Mflag = true;
+                            break;
+                        case 'v':
+                            vflag = true;
+                            break;
+                        case 'f':
+                            fname = args[count++];
+                            break;
+                        case 'm':
+                            mname = args[count++];
+                            break;
+                        case '0':
+                            flag0 = true;
+                            break;
+                        case 'i':
+                            if (cflag || uflag || xflag || tflag) {
+                                usageError();
+                                return false;
+                            }
+                            // do not increase the counter, files will contain rootjar
+                            rootjar = args[count++];
+                            iflag = true;
+                            break;
+                        case 'n':
+                            nflag = true;
+                            break;
+                        case 'e':
+                            ename = args[count++];
+                            break;
+                        case 'P':
+                            pflag = true;
+                            break;
+                        default:
+                            error(formatMsg("error.illegal.option",
+                                    String.valueOf(flags.charAt(i))));
+                            usageError();
+                            return false;
+                    }
+                }
             }
         } catch (ArrayIndexOutOfBoundsException e) {
             usageError();
             return false;
         }
-        if (!cflag && !tflag && !xflag && !uflag && !iflag) {
+
+        if (info != null) {
+            info.print(out);
+            return true;
+        }
+
+        if (!cflag && !tflag && !xflag && !uflag && !iflag && !printModuleDescriptor) {
             error(getMsg("error.bad.option"));
             usageError();
             return false;
@@ -489,23 +604,56 @@
         return true;
     }
 
+    private static Set<String> findPackages(ZipFile zf) {
+        return zf.stream()
+                 .filter(e -> e.getName().endsWith(".class"))
+                 .map(e -> toPackageName(e))
+                 .filter(pkg -> pkg.length() > 0)
+                 .distinct()
+                 .collect(Collectors.toSet());
+    }
+
+    private static String toPackageName(ZipEntry entry) {
+        return toPackageName(entry.getName());
+    }
+
+    private static String toPackageName(String path) {
+        assert path.endsWith(".class");
+        int index = path.lastIndexOf('/');
+        if (index != -1) {
+            return path.substring(0, index).replace('/', '.');
+        } else {
+            return "";
+        }
+    }
+
     /**
      * Expands list of files to process into full list of all files that
      * can be found by recursively descending directories.
      */
-    void expand(File dir, String[] files, boolean isUpdate) {
-        if (files == null) {
+    void expand(File dir, String[] files, boolean isUpdate) throws IOException {
+        if (files == null)
             return;
-        }
+
         for (int i = 0; i < files.length; i++) {
             File f;
-            if (dir == null) {
+            if (dir == null)
                 f = new File(files[i]);
-            } else {
+            else
                 f = new File(dir, files[i]);
-            }
+
             if (f.isFile()) {
-                if (entries.add(f)) {
+                String path = f.getPath();
+                if (entryName(path).equals(MODULE_INFO)) {
+                    if (moduleInfo != null && vflag)
+                        output(formatMsg("error.unexpected.module-info", path));
+                    moduleInfo = f.toPath();
+                    if (isUpdate)
+                        entryMap.put(entryName(path), f);
+                } else if (entries.add(f)) {
+                    jarEntries.add(entryName(path));
+                    if (path.endsWith(".class"))
+                        packages.add(toPackageName(entryName(path)));
                     if (isUpdate)
                         entryMap.put(entryName(f.getPath()), f);
                 }
@@ -529,13 +677,14 @@
     /**
      * Creates a new JAR file.
      */
-    void create(OutputStream out, Manifest manifest)
+    void create(OutputStream out, Manifest manifest, byte[] moduleInfoBytes)
         throws IOException
     {
         ZipOutputStream zos = new JarOutputStream(out);
         if (flag0) {
             zos.setMethod(ZipOutputStream.STORED);
         }
+        // TODO: check module-info attributes against manifest ??
         if (manifest != null) {
             if (vflag) {
                 output(getMsg("out.added.manifest"));
@@ -554,6 +703,20 @@
             manifest.write(zos);
             zos.closeEntry();
         }
+        if (moduleInfoBytes != null) {
+            if (vflag) {
+                output(getMsg("out.added.module-info"));
+            }
+            ZipEntry e = new ZipEntry(MODULE_INFO);
+            e.setTime(System.currentTimeMillis());
+            if (flag0) {
+                crc32ModuleInfo(e, moduleInfoBytes);
+            }
+            zos.putNextEntry(e);
+            ByteArrayInputStream in = new ByteArrayInputStream(moduleInfoBytes);
+            in.transferTo(zos);
+            zos.closeEntry();
+        }
         for (File file: entries) {
             addFile(zos, file);
         }
@@ -589,12 +752,14 @@
      */
     boolean update(InputStream in, OutputStream out,
                    InputStream newManifest,
+                   byte[] newModuleInfoBytes,
                    JarIndex jarIndex) throws IOException
     {
         ZipInputStream zis = new ZipInputStream(in);
         ZipOutputStream zos = new JarOutputStream(out);
         ZipEntry e = null;
         boolean foundManifest = false;
+        boolean foundModuleInfo = false;
         boolean updateOk = true;
 
         if (jarIndex != null) {
@@ -606,6 +771,7 @@
             String name = e.getName();
 
             boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
+            boolean isModuleInfoEntry = name.equals(MODULE_INFO);
 
             if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
                 || (Mflag && isManifestEntry)) {
@@ -633,6 +799,13 @@
                 if (!updateManifest(old, zos)) {
                     return false;
                 }
+            } else if (isModuleInfoEntry
+                       && ((newModuleInfoBytes != null) || (ename != null)
+                           || moduleVersion != null || dependenciesToHash != null)) {
+                if (newModuleInfoBytes == null) {
+                    // Update existing module-info.class
+                    newModuleInfoBytes = readModuleInfo(zis);
+                }
             } else {
                 if (!entryMap.containsKey(name)) { // copy the old stuff
                     // do our own compression
@@ -653,6 +826,10 @@
                     entryMap.remove(name);
                     entries.remove(f);
                 }
+
+                jarEntries.add(name);
+                if (name.endsWith(".class"))
+                    packages.add(toPackageName(name));
             }
         }
 
@@ -675,6 +852,20 @@
                 }
             }
         }
+
+        // write the module-info.class
+        if (newModuleInfoBytes != null) {
+            newModuleInfoBytes = addExtendedModuleAttributes(newModuleInfoBytes);
+
+            // TODO: check manifest main classes, etc
+            if (!updateModuleInfo(newModuleInfoBytes, zos)) {
+                updateOk = false;
+            }
+        } else if (moduleVersion != null || dependenciesToHash != null) {
+            error(getMsg("error.module.options.without.info"));
+            updateOk = false;
+        }
+
         zis.close();
         zos.close();
         return updateOk;
@@ -696,6 +887,22 @@
         zos.closeEntry();
     }
 
+    private boolean updateModuleInfo(byte[] moduleInfoBytes, ZipOutputStream zos)
+        throws IOException
+    {
+        ZipEntry e = new ZipEntry(MODULE_INFO);
+        e.setTime(System.currentTimeMillis());
+        if (flag0) {
+            crc32ModuleInfo(e, moduleInfoBytes);
+        }
+        zos.putNextEntry(e);
+        zos.write(moduleInfoBytes);
+        if (vflag) {
+            output(getMsg("out.update.module-info"));
+        }
+        return true;
+    }
+
     private boolean updateManifest(Manifest m, ZipOutputStream zos)
         throws IOException
     {
@@ -833,6 +1040,8 @@
                 output(formatMsg("out.ignore.entry", name));
             }
             return;
+        } else if (name.equals(MODULE_INFO)) {
+            throw new Error("Unexpected module info: " + name);
         }
 
         long size = isDir ? 0 : file.length();
@@ -928,6 +1137,17 @@
     }
 
     /**
+     * Computes the crc32 of a module-info.class.  This is necessary when the
+     * ZipOutputStream is in STORED mode.
+     */
+    private void crc32ModuleInfo(ZipEntry e, byte[] bytes) throws IOException {
+        CRC32OutputStream os = new CRC32OutputStream();
+        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+        in.transferTo(os);
+        os.updateEntry(e);
+    }
+
+    /**
      * Computes the crc32 of a Manifest.  This is necessary when the
      * ZipOutputStream is in STORED mode.
      */
@@ -1151,7 +1371,7 @@
         try {
             if (update(Files.newInputStream(jarPath),
                        Files.newOutputStream(tmpPath),
-                       null, index)) {
+                       null, null, index)) {
                 try {
                     Files.move(tmpPath, jarPath, REPLACE_EXISTING);
                 } catch (IOException e) {
@@ -1268,7 +1488,7 @@
      * Prints usage message.
      */
     void usageError() {
-        error(getMsg("usage"));
+        Info.USAGE_SUMMARY.print(err);
     }
 
     /**
@@ -1369,4 +1589,235 @@
         }
         return tmpfile;
     }
+
+    private static byte[] readModuleInfo(InputStream zis) throws IOException {
+        return zis.readAllBytes();
+    }
+
+    private static byte[] readModuleInfo(Path path) throws IOException {
+        try (InputStream is = Files.newInputStream(path)) {
+            return is.readAllBytes();
+        }
+    }
+
+    // Modular jar support
+
+    static <T> String toString(Set<T> set,
+                               CharSequence prefix,
+                               CharSequence suffix ) {
+        if (set.isEmpty())
+            return "";
+
+        return set.stream().map(e -> e.toString())
+                           .collect(joining(", ", prefix, suffix));
+    }
+
+    private boolean printModuleDescriptor(ZipFile zipFile)
+        throws IOException
+    {
+        ZipEntry entry = zipFile.getEntry(MODULE_INFO);
+        if (entry ==  null)
+            return false;
+
+        try (InputStream is = zipFile.getInputStream(entry)) {
+            printModuleDescriptor(is);
+        }
+        return true;
+    }
+
+    private boolean printModuleDescriptor(FileInputStream fis)
+        throws IOException
+    {
+        try (BufferedInputStream bis = new BufferedInputStream(fis);
+             ZipInputStream zis = new ZipInputStream(bis)) {
+
+            ZipEntry e;
+            while ((e = zis.getNextEntry()) != null) {
+                if (e.getName().equals(MODULE_INFO)) {
+                    printModuleDescriptor(zis);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void printModuleDescriptor(InputStream entryInputStream)
+        throws IOException
+    {
+        ModuleDescriptor md = ModuleDescriptor.read(entryInputStream);
+        StringBuilder sb = new StringBuilder();
+        sb.append("\nName:\n  " + md.toNameAndVersion());
+
+        Set<Requires> requires = md.requires();
+        if (!requires.isEmpty()) {
+            sb.append("\nRequires:");
+            requires.forEach(r ->
+                    sb.append("\n  ").append(r.name())
+                            .append(toString(r.modifiers(), " [ ", " ]")));
+        }
+
+        Set<String> s = md.uses();
+        if (!s.isEmpty()) {
+            sb.append("\nUses: ");
+            s.forEach(sv -> sb.append("\n  ").append(sv));
+        }
+
+        Set<Exports> exports = md.exports();
+        if (!exports.isEmpty()) {
+            sb.append("\nExports:");
+            exports.forEach(sv -> sb.append("\n  ").append(sv));
+        }
+
+        Map<String,Provides> provides = md.provides();
+        if (!provides.isEmpty()) {
+            sb.append("\nProvides: ");
+            provides.values().forEach(p ->
+                    sb.append("\n  ").append(p.service())
+                      .append(" with ")
+                      .append(toString(p.providers(), "", "")));
+        }
+
+        Optional<String> mc = md.mainClass();
+        if (mc.isPresent())
+            sb.append("\nMain class:\n  " + mc.get());
+
+        s = md.conceals();
+        if (!s.isEmpty()) {
+            sb.append("\nConceals:");
+            s.forEach(p -> sb.append("\n  ").append(p));
+        }
+
+        try {
+            Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
+            m.setAccessible(true);
+            Optional<Hasher.DependencyHashes> optHashes =
+                    (Optional<Hasher.DependencyHashes>) m.invoke(md);
+
+            if (optHashes.isPresent()) {
+                Hasher.DependencyHashes hashes = optHashes.get();
+                sb.append("\nHashes:");
+                sb.append("\n  Algorithm: " + hashes.algorithm());
+                hashes.names().stream().forEach(mod ->
+                        sb.append("\n  ").append(mod)
+                          .append(": ").append(hashes.hashFor(mod)));
+            }
+        } catch (ReflectiveOperationException x) {
+            throw new InternalError(x);
+        }
+        output(sb.toString());
+    }
+
+    private static String toBinaryName(String classname) {
+        return (classname.replace('.', '/')) + ".class";
+    }
+
+    private boolean checkServices(byte[] moduleInfoBytes)
+        throws IOException
+    {
+        ModuleDescriptor md;
+        try (InputStream in = new ByteArrayInputStream(moduleInfoBytes)) {
+            md = ModuleDescriptor.read(in);
+        }
+        Set<String> missing = md.provides()
+                                .values()
+                                .stream()
+                                .map(Provides::providers)
+                                .flatMap(Set::stream)
+                                .filter(p -> !jarEntries.contains(toBinaryName(p)))
+                                .collect(Collectors.toSet());
+        if (missing.size() > 0) {
+            missing.stream().forEach(s -> fatalError(formatMsg("error.missing.provider", s)));
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a byte array containing the module-info.class.
+     *
+     * If --module-version, --main-class, or other options were provided
+     * then the corresponding class file attributes are added to the
+     * module-info here.
+     */
+    private byte[] addExtendedModuleAttributes(byte[] moduleInfoBytes)
+        throws IOException
+    {
+        assert isModularJar();
+
+        ModuleDescriptor md;
+        try (InputStream in = new ByteArrayInputStream(moduleInfoBytes)) {
+            md = ModuleDescriptor.read(in);
+        }
+        String name = md.name();
+        Set<ModuleDescriptor.Requires> dependences = md.requires();
+        Set<String> exported = md.exports()
+                                 .stream()
+                                 .map(ModuleDescriptor.Exports::source)
+                                 .collect(Collectors.toSet());
+
+        // copy the module-info.class into the jmod with the additional
+        // attributes for the version, main class and other meta data
+        try (InputStream in = new ByteArrayInputStream(moduleInfoBytes);
+             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
+
+            // Add (or replace) the ConcealedPackages attribute
+            Set<String> conceals = packages.stream()
+                                            .filter(p -> !exported.contains(p))
+                                            .collect(Collectors.toSet());
+
+            extender.conceals(conceals);
+
+            // --main-class
+            if (ename != null)
+                extender.mainClass(ename);
+
+            // --module-version
+            if (moduleVersion != null)
+                extender.version(moduleVersion);
+
+            // --hash-dependencies
+            if (dependenciesToHash != null)
+                extender.hashes(hashDependences(name, dependences));
+
+            extender.write(baos);
+            return baos.toByteArray();
+        }
+    }
+
+    /**
+     * Examines the module dependences of the given module and computes the
+     * hash of any module that matches the pattern {@code dependenciesToHash}.
+     */
+    private Hasher.DependencyHashes
+    hashDependences(String name,
+                    Set<ModuleDescriptor.Requires> moduleDependences)
+        throws IOException
+    {
+        Map<String, Path> map = new HashMap<>();
+        Matcher matcher = dependenciesToHash.matcher("");
+        for (ModuleDescriptor.Requires md: moduleDependences) {
+            String dn = md.name();
+            if (matcher.reset(dn).find()) {
+                Optional<ModuleReference> omref = moduleFinder.find(dn);
+                if (!omref.isPresent()) {
+                    throw new IOException(formatMsg2("error.hash.dep", name , dn));
+                }
+                map.put(dn, modRefToPath(omref.get()));
+            }
+        }
+
+        if (map.size() == 0) {
+            return null;
+        } else {
+            return Hasher.generate(map, "SHA-256");
+        }
+    }
+
+    private static Path modRefToPath(ModuleReference mref) {
+        URI location = mref.location().get();
+        return Paths.get(location);
+    }
 }
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 3b87385..a880d9f 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
@@ -23,10 +23,18 @@
 # questions.
 #
 
+error.multiple.main.operations=\
+     You may not specify more than one '-cuxti' options
 error.cant.open=\
-     can''t open: {0} 
+     can''t open: {0}
 error.illegal.option=\
         Illegal option: {0}
+error.unrecognized.option=\
+    unrecognized option : {0}
+error.missing.arg=\
+     option {0} requires an argument
+error.bad.file.arg=\
+     Error parsing file arguments
 error.bad.option=\
         One of options -{ctxu} must be specified.
 error.bad.cflag=\
@@ -46,10 +54,24 @@
         incorrect length while processing: {0}
 error.create.tempfile=\
         Could not create a temporary file
+error.hash.dep=\
+        Hashing module {0} dependences, unable to find module {1} on module path
+error.module.options.without.info=\
+        One of --module-version or --hash-dependencies without module-info.class
+error.unexpected.module-info=\
+        Unexpected module descriptor {0}
+error.module.descriptor.not.found=\
+        Module descriptor not found
+error.missing.provider=\
+        Service provider not found: {0}
 out.added.manifest=\
         added manifest
+out.added.module-info=\
+        added module-info.class
 out.update.manifest=\
         updated manifest
+out.update.module-info=\
+        updated module-info.class
 out.ignore.entry=\
         ignoring entry {0}
 out.adding=\
@@ -67,7 +89,9 @@
 out.size=\
         (in = {0}) (out= {1})
 
-usage=\
+usage.compat=\
+\Compatibility Interface:\
+\n\
 Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
 Options:\n\
 \ \   -c  create new archive\n\
@@ -93,3 +117,91 @@
 Example 2: use an existing manifest file 'mymanifest' and archive all the\n\
 \ \          files in the foo/ directory into 'classes.jar': \n\
 \ \      jar cvfm classes.jar mymanifest -C foo/ .\n
+
+main.usage.summary=\
+jar: You must specify one of -ctxui options.
+main.usage.summary.try=\
+Try `jar --help' for more information.
+
+main.help.preopt=\
+Usage: jar [OPTION...] [-C dir] files ...\n\
+jar creates an archive for classes and resources, and can manipulate or\n\
+restore individual classes or resources from an archive.\n\
+\n\
+\ Examples:\n\
+\ # Create an archive called classes.jar with two class files:\n\
+\ jar --create --file classes.jar Foo.class Bar.class\n\
+\ # Create an archive using an existing manifest, with all the files in foo/:\n\
+\ jar --create --file classes.jar --manifest mymanifest -C foo/ .\n\
+\ # Create a modular jar archive, where the module descriptor is located in\n\
+\ # classes/module-info.class:\n\
+\ jar --create --file foo.jar --main-class com.foo.Main --module-version 1.0\n\
+\     -C foo/ classes resources\n\
+\ # Update an existing non-modular jar to a modular jar:\n\
+\ jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0\n\
+\     -C foo/ module-info.class
+main.help.opt.main=\
+\ Main operation mode:\n
+main.help.opt.main.create=\
+\  -c, --create               Create the archive
+main.help.opt.main.generate-index=\
+\  -i, --generate-index=FILE  Generate index information for the specified jar\n\
+\                             archives
+main.help.opt.main.list=\
+\  -t, --list                 List the table of contents for the archive
+main.help.opt.main.update=\
+\  -u, --update               Update an existing jar archive
+main.help.opt.main.extract=\
+\  -x, --extract              Extract named (or all) files from the archive
+main.help.opt.main.print-module-descriptor=\
+\  -p, --print-module-descriptor  Print the module descriptor
+main.help.opt.any=\
+\ Operation modifiers valid in any mode:\n\
+\n\
+\  -C DIR                     Change to the specified directory and include the\n\
+\                             following file
+main.help.opt.any.file=\
+\  -f, --file=FILE            The archive file name
+main.help.opt.any.verbose=\
+\  -v, --verbose              Generate verbose output on standard output
+main.help.opt.create.update=\
+\ Operation modifiers valid only in create and update mode:\n
+main.help.opt.create.update.main-class=\
+\  -e, --main-class=CLASSNAME The application entry point for stand-alone\n\
+\                             applications bundled into a modular, or executable,\n\
+\                             jar archive
+main.help.opt.create.update.manifest=\
+\  -m, --manifest=FILE        Include the manifest information from the given\n\
+\                             manifest file
+main.help.opt.create.update.no-manifest=\
+\  -M, --no-manifest          Do not create a manifest file for the entries
+main.help.opt.create.update.module-version=\
+\      --module-version=VERSION    The module version, when creating a modular\n\
+\                             jar, or updating a non-modular jar
+main.help.opt.create.update.hash-dependencies=\
+\      --hash-dependencies=PATTERN  Compute and record the hashes of module\n\
+\                             dependencies matched by the given pattern, when\n\
+\                             creating a modular jar, or updating a non-modular\n\
+\                             jar
+main.help.opt.create.update.modulepath=\
+\      --modulepath           Location of module dependence for generating
+\                             the hash
+main.help.opt.create.update.index=\
+\ Operation modifiers valid only in create, update, and generate-index mode:\n
+main.help.opt.create.update.index.no-compress=\
+\  -0, --no-compress          Store only; use no ZIP compression
+main.help.opt.other=\
+\ Other options:\n
+main.help.opt.other.help=\
+\  -?, --help[:compat]        Give this, or optionally the compatibility, help
+main.help.opt.other.version=\
+\      --version              Print program version
+main.help.postopt=\
+\ An archive is a modular jar if a module descriptor, 'module-info.class', is\n\
+\ located in the root of the given directories, or the root of the jar archive\n\
+\ itself. The following operations are only valid when creating a modular jar,\n\
+\ or updating an existing non-modular jar: '--module-version',\n\
+\ '--hash-dependencies', and '--modulepath'.\n\
+\n\
+\ Mandatory or optional arguments to long options are also mandatory or optional\n\
+\ for any corresponding short options.
\ No newline at end of file
diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java
new file mode 100644
index 0000000..55be308
--- /dev/null
+++ b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.vm.agent.spi;
+
+/**
+ * Service interface for jdk.hotspot.agent to provide the tools that
+ * jstack, jmap, jinfo will invoke, if present.
+ */
+public interface ToolProvider {
+    /**
+     * Returns the name of the tool provider
+     */
+    String getName();
+
+    /**
+     * Invoke the tool provider with the given arguments
+     */
+    void run(String... arguments);
+}
diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java
new file mode 100644
index 0000000..b96e6ae
--- /dev/null
+++ b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.vm.agent.spi;
+
+import java.lang.reflect.Layer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+public final class ToolProviderFinder {
+    private static final Map<String, ToolProvider> providers = init();
+
+    public static ToolProvider find(String name) {
+        return providers.get(name);
+    }
+
+    private static Map<String, ToolProvider> init() {
+        Map<String, ToolProvider> providers = new HashMap<>();
+        ServiceLoader.load(Layer.boot(), ToolProvider.class)
+                     .forEach(p -> providers.putIfAbsent(p.getName(), p));
+        return providers;
+    }
+}
diff --git a/jdk/src/jdk.jcmd/share/classes/module-info.java b/jdk/src/jdk.jcmd/share/classes/module-info.java
new file mode 100644
index 0000000..4b8dbce
--- /dev/null
+++ b/jdk/src/jdk.jcmd/share/classes/module-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jcmd {
+    requires jdk.attach;
+    requires jdk.jvmstat;
+
+    exports jdk.internal.vm.agent.spi to jdk.hotspot.agent;
+
+    uses jdk.internal.vm.agent.spi.ToolProvider;
+}
+
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
index ce44637..f19b6d1 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java
@@ -25,7 +25,6 @@
 
 package sun.tools.jinfo;
 
-import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,6 +32,8 @@
 import com.sun.tools.attach.VirtualMachine;
 
 import sun.tools.attach.HotSpotVirtualMachine;
+import jdk.internal.vm.agent.spi.ToolProvider;
+import jdk.internal.vm.agent.spi.ToolProviderFinder;
 
 /*
  * This class is the main class for the JInfo utility. It parses its arguments
@@ -40,6 +41,7 @@
  * or an SA tool.
  */
 final public class JInfo {
+    private static final String SA_JINFO_TOOL_NAME = "jinfo";
     private boolean useSA = false;
     private String[] args = null;
 
@@ -183,34 +185,11 @@
 
     // Invoke SA tool with the given arguments
     private void runTool() throws Exception {
-        String tool = "sun.jvm.hotspot.tools.JInfo";
-        // Tool not available on this platform.
-        Class<?> c = loadClass(tool);
-        if (c == null) {
+        ToolProvider tool = ToolProviderFinder.find(SA_JINFO_TOOL_NAME);
+        if (tool == null) {
             usage(1);
         }
-
-        // invoke the main method with the arguments
-        Class<?>[] argTypes = { String[].class } ;
-        Method m = c.getDeclaredMethod("main", argTypes);
-
-        Object[] invokeArgs = { args };
-        m.invoke(null, invokeArgs);
-    }
-
-    // loads the given class using the system class loader
-    private static Class<?> loadClass(String name) {
-        //
-        // We specify the system class loader so as to cater for development
-        // environments where this class is on the boot class path but sa-jdi.jar
-        // is on the system class path. Once the JDK is deployed then both
-        // tools.jar and sa-jdi.jar are on the system class path.
-        //
-        try {
-            return Class.forName(name, true,
-                                 ClassLoader.getSystemClassLoader());
-        } catch (Exception x)  { }
-        return null;
+        tool.run(args);
     }
 
     private static void flag(String pid, String option) throws IOException {
@@ -298,9 +277,7 @@
 
     // print usage message
     private static void usage(int exit) {
-
-        Class<?> c = loadClass("sun.jvm.hotspot.tools.JInfo");
-        boolean usageSA = (c != null);
+        boolean usageSA = ToolProviderFinder.find(SA_JINFO_TOOL_NAME) != null;
 
         System.err.println("Usage:");
         if (usageSA) {
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
index f6dd404..cb7651e 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
@@ -25,7 +25,6 @@
 
 package sun.tools.jmap;
 
-import java.lang.reflect.Method;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,6 +32,8 @@
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
+import jdk.internal.vm.agent.spi.ToolProvider;
+import jdk.internal.vm.agent.spi.ToolProviderFinder;
 
 /*
  * This class is the main class for the JMap utility. It parses its arguments
@@ -149,15 +150,15 @@
     // Invoke SA tool  with the given arguments
     private static void runTool(String option, String args[]) throws Exception {
         String[][] tools = {
-            { "-pmap",          "sun.jvm.hotspot.tools.PMap"             },
-            { "-heap",          "sun.jvm.hotspot.tools.HeapSummary"      },
-            { "-heap:format=b", "sun.jvm.hotspot.tools.HeapDumper"       },
-            { "-histo",         "sun.jvm.hotspot.tools.ObjectHistogram"  },
-            { "-clstats",       "sun.jvm.hotspot.tools.ClassLoaderStats" },
-            { "-finalizerinfo", "sun.jvm.hotspot.tools.FinalizerInfo"    },
+            { "-pmap",          "pmap"             },
+            { "-heap",          "heapSummary"      },
+            { "-heap:format=b", "heapDumper"       },
+            { "-histo",         "objectHistogram"  },
+            { "-clstats",       "classLoaderStats" },
+            { "-finalizerinfo", "finalizerInfo"    },
         };
 
-        String tool = null;
+        String name = null;
 
         // -dump option needs to be handled in a special way
         if (option.startsWith(DUMP_OPTION_PREFIX)) {
@@ -168,7 +169,7 @@
             }
 
             // tool for heap dumping
-            tool = "sun.jvm.hotspot.tools.HeapDumper";
+            name = "heapDumper";
 
             // HeapDumper -f <file>
             args = prepend(fn, args);
@@ -177,43 +178,24 @@
             int i=0;
             while (i < tools.length) {
                 if (option.equals(tools[i][0])) {
-                    tool = tools[i][1];
+                    name = tools[i][1];
                     break;
                 }
                 i++;
             }
         }
-        if (tool == null) {
+        if (name == null) {
             usage(1);   // no mapping to tool
         }
 
-        // Tool not available on this  platform.
-        Class<?> c = loadClass(tool);
-        if (c == null) {
+        // Tool not available on this platform.
+        ToolProvider tool = ToolProviderFinder.find(name);
+        if (tool == null) {
             usage(1);
         }
 
         // invoke the main method with the arguments
-        Class<?>[] argTypes = { String[].class } ;
-        Method m = c.getDeclaredMethod("main", argTypes);
-
-        Object[] invokeArgs = { args };
-        m.invoke(null, invokeArgs);
-    }
-
-    // loads the given class using the system class loader
-    private static Class<?> loadClass(String name) {
-        //
-        // We specify the system clas loader so as to cater for development
-        // environments where this class is on the boot class path but sa-jdi.jar
-        // is on the system class path. Once the JDK is deployed then both
-        // tools.jar and sa-jdi.jar are on the system class path.
-        //
-        try {
-            return Class.forName(name, true,
-                                 ClassLoader.getSystemClassLoader());
-        } catch (Exception x)  { }
-        return null;
+        tool.run(args);
     }
 
     private static final String LIVE_OBJECTS_OPTION = "-live";
@@ -340,8 +322,7 @@
 
     // returns true if SA is available
     private static boolean haveSA() {
-        Class<?> c = loadClass("sun.jvm.hotspot.tools.HeapSummary");
-        return (c != null);
+        return ToolProviderFinder.find("heapSummary") != null;
     }
 
     // print usage message
diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
index 2b0f59c..3553284 100644
--- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
+++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstack/JStack.java
@@ -25,14 +25,13 @@
 
 package sun.tools.jstack;
 
-import java.lang.reflect.Method;
-import java.lang.reflect.Constructor;
-import java.io.IOException;
 import java.io.InputStream;
 
 import com.sun.tools.attach.VirtualMachine;
 import com.sun.tools.attach.AttachNotSupportedException;
 import sun.tools.attach.HotSpotVirtualMachine;
+import jdk.internal.vm.agent.spi.ToolProvider;
+import jdk.internal.vm.agent.spi.ToolProviderFinder;
 
 /*
  * This class is the main class for the JStack utility. It parses its arguments
@@ -40,6 +39,8 @@
  * obtained the thread dump from a target process using the VM attach mechanism
  */
 public class JStack {
+    private static final String SA_JSTACK_TOOL_NAME = "jstack";
+
     public static void main(String[] args) throws Exception {
         if (args.length == 0) {
             usage(1); // no arguments
@@ -117,11 +118,14 @@
         }
     }
 
-
     // SA JStack tool
+    private static boolean isAgentToolPresent() {
+        return ToolProviderFinder.find(SA_JSTACK_TOOL_NAME) != null;
+    }
+
     private static void runJStackTool(boolean mixed, boolean locks, String args[]) throws Exception {
-        Class<?> cl = loadSAClass();
-        if (cl == null) {
+        ToolProvider tool = ToolProviderFinder.find(SA_JSTACK_TOOL_NAME);
+        if (tool == null) {
             usage(1);            // SA not available
         }
 
@@ -133,28 +137,9 @@
             args = prepend("-l", args);
         }
 
-        Class<?>[] argTypes = { String[].class };
-        Method m = cl.getDeclaredMethod("main", argTypes);
-
-        Object[] invokeArgs = { args };
-        m.invoke(null, invokeArgs);
+        tool.run(args);
     }
 
-    // Returns sun.jvm.hotspot.tools.JStack if available, otherwise null.
-    private static Class<?> loadSAClass() {
-        //
-        // Attempt to load JStack class - we specify the system class
-        // loader so as to cater for development environments where
-        // this class is on the boot class path but sa-jdi.jar is on
-        // the system class path. Once the JDK is deployed then both
-        // tools.jar and sa-jdi.jar are on the system class path.
-        //
-        try {
-            return Class.forName("sun.jvm.hotspot.tools.JStack", true,
-                                 ClassLoader.getSystemClassLoader());
-        } catch (Exception x)  { }
-        return null;
-    }
 
     // Attach to pid and perform a thread dump
     private static void runThreadDump(String pid, String args[]) throws Exception {
@@ -168,8 +153,7 @@
             } else {
                 x.printStackTrace();
             }
-            if ((x instanceof AttachNotSupportedException) &&
-                (loadSAClass() != null)) {
+            if ((x instanceof AttachNotSupportedException) && isAgentToolPresent()) {
                 System.err.println("The -F option can be used when the target " +
                     "process is not responding");
             }
@@ -208,7 +192,7 @@
         System.err.println("    jstack [-l] <pid>");
         System.err.println("        (to connect to running process)");
 
-        if (loadSAClass() != null) {
+        if (isAgentToolPresent()) {
             System.err.println("    jstack -F [-m] [-l] <pid>");
             System.err.println("        (to connect to a hung process)");
             System.err.println("    jstack [-m] [-l] <executable> <core>");
@@ -220,7 +204,7 @@
         System.err.println("");
         System.err.println("Options:");
 
-        if (loadSAClass() != null) {
+        if (isAgentToolPresent()) {
             System.err.println("    -F  to force a thread dump. Use when jstack <pid> does not respond" +
                 " (process is hung)");
             System.err.println("    -m  to print both java and native frames (mixed mode)");
diff --git a/jdk/src/jdk.jconsole/share/classes/module-info.java b/jdk/src/jdk.jconsole/share/classes/module-info.java
new file mode 100644
index 0000000..6dfeca0
--- /dev/null
+++ b/jdk/src/jdk.jconsole/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jconsole {
+    requires public java.desktop;
+    requires public java.management;
+    requires java.logging;
+    requires java.rmi;
+    requires jdk.attach;
+    requires jdk.jvmstat;
+    requires jdk.management;
+    exports com.sun.tools.jconsole;
+    uses com.sun.tools.jconsole.JConsolePlugin;
+}
+
diff --git a/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector b/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector
deleted file mode 100644
index e9ecb5e..0000000
--- a/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-# 
-
-#
-# List all Sun provided connector providers here. If there
-# are providers that are only available on a particular OS
-# then prefix the line with #[OS] and they will automatically
-# uncommented by the build process - see make/jpda/front/Makefile.
-#
-com.sun.tools.jdi.SunCommandLineLauncher
-com.sun.tools.jdi.RawCommandLineLauncher
-com.sun.tools.jdi.SocketAttachingConnector
-com.sun.tools.jdi.SocketListeningConnector
-#[windows]com.sun.tools.jdi.SharedMemoryAttachingConnector
-#[windows]com.sun.tools.jdi.SharedMemoryListeningConnector
-com.sun.tools.jdi.ProcessAttachingConnector
diff --git a/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.spi.TransportService b/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.spi.TransportService
deleted file mode 100644
index 603dcc9..0000000
--- a/jdk/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.spi.TransportService
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute 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.
-# 
-
-#
-# List any additional Sun provided transport services here.
-# If any transport services are OS specific then prefix the line
-# with #[OS] and they will automatically be uncommented in the
-# build process - see make/jpda/front/Makefile.
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java
new file mode 100644
index 0000000..0256cd5
--- /dev/null
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.jdi;
+
+/**
+ * Thrown to indicate that the requested module is invalid
+ * or became invalid after the module was unloaded.
+ * <p>
+ *
+ * @since  9
+ */
+public class InvalidModuleException extends RuntimeException {
+    private static final long serialVersionUID = 7907359387320658039L;
+
+    /**
+     * Constructs a {@code InvalidModuleException} with no detail message.
+     */
+    public InvalidModuleException() {
+        super();
+    }
+
+    /**
+     * Constructs a {@code InvalidModuleException} with the given detail
+     * message.
+     *
+     * @param msg
+     *        The detail message; can be {@code null}
+     */
+    public InvalidModuleException(String msg) {
+        super(msg);
+    }
+}
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
new file mode 100644
index 0000000..4c9d421
--- /dev/null
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ModuleReference.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.  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.jdi;
+
+
+/**
+ * A module in the target VM.
+ * <p>
+ * Any method on {@code ModuleReference} which directly or
+ * indirectly takes {@code ModuleReference} as an 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
+ * {@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
+ * {@link com.sun.jdi.InvalidModuleException} if the mirrored module
+ * has been unloaded.
+ *
+ * Not all target virtual machines support this class.
+ * Use {@link VirtualMachine#canGetModuleInfo()}
+ * to determine if the class is supported.
+ *
+ * @since  9
+ */
+public interface ModuleReference extends ObjectReference {
+
+    /**
+     * Returns the module name.
+     * This method returns {@code null}
+     * if this module is an unnamed module.
+     *
+     * @return the name of this module.
+     */
+    String name();
+
+    /**
+     * Returns the {@link ClassLoaderReference} object for this module.
+     *
+     * @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/jdi/ReferenceType.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java
index 30052d5..442b283 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ReferenceType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -117,6 +117,30 @@
     ClassLoaderReference classLoader();
 
     /**
+     * Gets the module object which contains the class corresponding
+     * to this type.
+     *
+     * Not all target virtual machines support this operation.
+     * Use {@link VirtualMachine#canGetModuleInfo()}
+     * to determine if the operation is supported.
+     *
+     * @implSpec
+     * The default implementation throws {@code UnsupportedOperationException}.
+     *
+     * @return a {@link ModuleReference} which mirrors the module in the target VM.
+     *
+     * @throws java.lang.UnsupportedOperationException if
+     * the target virtual machine does not support this
+     * operation.
+     *
+     * @since 9
+     */
+    default ModuleReference module() {
+        throw new java.lang.UnsupportedOperationException(
+            "The method module() must be implemented");
+    }
+
+    /**
      * Gets an identifying name for the source corresponding to the
      * declaration of this type. Interpretation of this string is
      * the responsibility of the source repository mechanism.
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java
index c54cc16..dcfd20cd 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -26,6 +26,7 @@
 package com.sun.jdi;
 
 import com.sun.jdi.event.EventQueue;
+import com.sun.jdi.ModuleReference;
 import com.sun.jdi.request.EventRequestManager;
 
 import java.util.List;
@@ -73,6 +74,32 @@
 public interface VirtualMachine extends Mirror {
 
     /**
+     * Returns all modules. For each module in the target
+     * VM a {@link ModuleReference} will be placed in the returned list.
+     * <P>
+     *
+     * Not all target virtual machines support this operation.
+     * Use {@link VirtualMachine#canGetModuleInfo()}
+     * to determine if the operation is supported.
+     *
+     * @implSpec
+     * The default implementation throws {@code UnsupportedOperationException}.
+     *
+     * @return a list of {@link ModuleReference} objects, each mirroring
+     * a module in the target VM.
+     *
+     * @throws java.lang.UnsupportedOperationException if
+     * the target virtual machine does not support this
+     * operation.
+     *
+     * @since 9
+     */
+    default List<ModuleReference> allModules() {
+        throw new java.lang.UnsupportedOperationException(
+            "The method allModules() must be implemented");
+    }
+
+    /**
      * Returns the loaded reference types that
      * match a given name. The name must be fully qualified
      * (for example, java.lang.String). The returned list
@@ -733,6 +760,24 @@
     boolean canGetConstantPool();
 
     /**
+     * Determines if the target VM supports getting information about modules.
+     *
+     * @return {@code true} if the feature is supported, {@code false} otherwise
+     *
+     * @implSpec
+     * The default implementation returns {@code false}.
+     *
+     * @see VirtualMachine#allModules()
+     * @see ReferenceType#module()
+     * @see ModuleReference
+     *
+     * @since 9
+     */
+    default boolean canGetModuleInfo() {
+        return false;
+    }
+
+    /**
      * Set this VM's default stratum (see {@link Location} for a
      * discussion of strata).  Overrides the per-class default set
      * in the class file.
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/JDWPException.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/JDWPException.java
index 6f3fdb5..268bd86 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/JDWPException.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/JDWPException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,8 @@
         switch (errorCode) {
             case JDWP.Error.INVALID_OBJECT:
                 return new ObjectCollectedException();
+            case JDWP.Error.INVALID_MODULE:
+                return new InvalidModuleException();
             case JDWP.Error.VM_DEAD:
                 return new VMDisconnectedException();
             case JDWP.Error.OUT_OF_MEMORY:
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
new file mode 100644
index 0000000..6c32368
--- /dev/null
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ModuleReferenceImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdi;
+
+import com.sun.jdi.*;
+
+
+class ModuleReferenceImpl extends ObjectReferenceImpl implements ModuleReference {
+
+    protected ModuleReferenceImpl(VirtualMachine aVm, long aRef) {
+        super(aVm, aRef);
+    }
+
+    protected String description() {
+        return "ModuleReference " + ref();
+    }
+
+    private String name;
+    private ClassLoaderReference classLoader;
+
+    private boolean cachedName = false;
+    private boolean cachedClassLoader = false;
+
+
+    public synchronized String name() {
+        if (cachedName) {
+            return name;
+        }
+        try {
+            name = JDWP.ModuleReference.Name.process(this.vm, this).name;
+            if (name != null && name.length() == 0) {
+                // The JDWP returns empty name for unnamed modules
+                name = null;
+            }
+            cachedName = true;
+        } catch (JDWPException ex) {
+            throw ex.toJDIException();
+        }
+        return name;
+    }
+
+    public synchronized ClassLoaderReference classLoader() {
+        if (cachedClassLoader) {
+            return classLoader;
+        }
+        try {
+            classLoader = JDWP.ModuleReference.ClassLoader.
+                process(this.vm, this).classLoader;
+            cachedClassLoader = true;
+        } catch (JDWPException ex) {
+            throw ex.toJDIException();
+        }
+        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/com/sun/tools/jdi/PacketStream.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/PacketStream.java
index a0cd2f3..ffafa3c 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/PacketStream.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/PacketStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, 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
@@ -154,6 +154,10 @@
         writeID(vm.sizeofMethodRef, data);
     }
 
+    void writeModuleRef(long data) {
+        writeID(vm.sizeofModuleRef, data);
+    }
+
     void writeFieldRef(long data) {
         writeID(vm.sizeofFieldRef, data);
     }
@@ -467,6 +471,11 @@
         return vm.referenceType(ref, tag);
     }
 
+    ModuleReferenceImpl readModule() {
+        long ref = readModuleRef();
+        return vm.moduleMirror(ref);
+    }
+
     /**
      * Read method reference represented as vm specific byte sequence.
      */
@@ -475,6 +484,13 @@
     }
 
     /**
+     * Read module reference represented as vm specific byte sequence.
+     */
+    long readModuleRef() {
+        return readID(vm.sizeofModuleRef);
+    }
+
+    /**
      * Read field reference represented as vm specific byte sequence.
      */
     long readFieldRef() {
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
index 88af45d..3225534 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
     private boolean isClassLoaderCached = false;
     private ClassLoaderReference classLoader = null;
     private ClassObjectReference classObject = null;
+    private ModuleReference module = null;
 
     private int status = 0;
     private boolean isPrepared = false;
@@ -219,6 +220,22 @@
         return classLoader;
     }
 
+    public ModuleReference module() {
+        if (module != null) {
+            return module;
+        }
+        // Does not need synchronization, since worst-case
+        // static info is fetched twice
+        try {
+            ModuleReferenceImpl m = JDWP.ReferenceType.Module.
+                process(vm, this).module;
+            module = vm.getModule(m.ref());
+        } catch (JDWPException exc) {
+            throw exc.toJDIException();
+        }
+        return module;
+    }
+
     public boolean isPublic() {
         if (modifiers == -1)
             getModifiers();
@@ -308,7 +325,8 @@
             if (vm.canGet1_5LanguageFeatures()) {
                 JDWP.ReferenceType.FieldsWithGeneric.FieldInfo[] jdwpFields;
                 try {
-                    jdwpFields = JDWP.ReferenceType.FieldsWithGeneric.process(vm, this).declared;
+                    jdwpFields = JDWP.ReferenceType.FieldsWithGeneric.
+                        process(vm, this).declared;
                 } catch (JDWPException exc) {
                     throw exc.toJDIException();
                 }
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
index 0529ee4..47e7434 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -26,6 +26,7 @@
 package com.sun.tools.jdi;
 
 import com.sun.jdi.*;
+import com.sun.jdi.ModuleReference;
 import com.sun.jdi.connect.spi.Connection;
 import com.sun.jdi.request.EventRequestManager;
 import com.sun.jdi.request.EventRequest;
@@ -48,6 +49,7 @@
     public final int sizeofObjectRef;
     public final int sizeofClassRef;
     public final int sizeofFrameRef;
+    public final int sizeofModuleRef;
 
     final int sequenceNumber;
 
@@ -75,6 +77,8 @@
     private TreeSet<ReferenceType> typesBySignature;
     private boolean retrievedAllTypes = false;
 
+    private Map<Long, ModuleReference> modulesByID;
+
     // For other languages support
     private String defaultStratum = null;
 
@@ -204,6 +208,7 @@
         sizeofObjectRef = idSizes.objectIDSize;
         sizeofClassRef = idSizes.referenceTypeIDSize;
         sizeofFrameRef  = idSizes.frameIDSize;
+        sizeofModuleRef = idSizes.objectIDSize;
 
         /**
          * Set up requests needed by internal event handler.
@@ -265,6 +270,12 @@
         return System.identityHashCode(this);
     }
 
+    public List<ModuleReference> allModules() {
+        validateVM();
+        List<ModuleReference> modules = retrieveAllModules();
+        return Collections.unmodifiableList(modules);
+    }
+
     public List<ReferenceType> classesByName(String className) {
         validateVM();
         String signature = JNITypeParser.typeNameToSignature(className);
@@ -585,7 +596,8 @@
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
-   }
+    }
+
     public String description() {
         validateVM();
 
@@ -674,20 +686,18 @@
             versionInfo().jdwpMinor >= 6;
     }
     public boolean canGetInstanceInfo() {
-        if (versionInfo().jdwpMajor < 1 ||
-            versionInfo().jdwpMinor < 6) {
+        if (versionInfo().jdwpMajor > 1 ||
+            versionInfo().jdwpMinor >= 6) {
+            validateVM();
+            return hasNewCapabilities() &&
+                capabilitiesNew().canGetInstanceInfo;
+        } else {
             return false;
         }
-        validateVM();
-        return hasNewCapabilities() &&
-            capabilitiesNew().canGetInstanceInfo;
     }
     public boolean canUseSourceNameFilters() {
-        if (versionInfo().jdwpMajor < 1 ||
-            versionInfo().jdwpMinor < 6) {
-            return false;
-        }
-        return true;
+        return versionInfo().jdwpMajor > 1 ||
+            versionInfo().jdwpMinor >= 6;
     }
     public boolean canForceEarlyReturn() {
         validateVM();
@@ -703,12 +713,8 @@
             capabilitiesNew().canGetSourceDebugExtension;
     }
     public boolean canGetClassFileVersion() {
-        if ( versionInfo().jdwpMajor < 1 &&
-             versionInfo().jdwpMinor  < 6) {
-            return false;
-        } else {
-            return true;
-        }
+        return versionInfo().jdwpMajor > 1 ||
+            versionInfo().jdwpMinor >= 6;
     }
     public boolean canGetConstantPool() {
         validateVM();
@@ -730,6 +736,10 @@
         return hasNewCapabilities() &&
             capabilitiesNew().canGetMonitorFrameInfo;
     }
+    public boolean canGetModuleInfo() {
+        validateVM();
+        return versionInfo().jdwpMajor >= 9;
+    }
 
     public void setDebugTraceMode(int traceFlags) {
         validateVM();
@@ -929,6 +939,48 @@
         return capabilitiesNew;
     }
 
+    private synchronized ModuleReference addModule(long id) {
+        if (modulesByID == null) {
+            modulesByID = new HashMap<Long, ModuleReference>(77);
+        }
+        ModuleReference module = new ModuleReferenceImpl(vm, id);
+        modulesByID.put(id, module);
+        return module;
+    }
+
+    ModuleReference getModule(long id) {
+        if (id == 0) {
+            return null;
+        } else {
+            ModuleReference module = null;
+            synchronized (this) {
+                if (modulesByID != null) {
+                    module = modulesByID.get(id);
+                }
+                if (module == null) {
+                    module = addModule(id);
+                }
+            }
+            return module;
+        }
+    }
+
+    private synchronized List<ModuleReference> retrieveAllModules() {
+        ModuleReferenceImpl[] reqModules;
+        try {
+            reqModules = JDWP.VirtualMachine.AllModules.process(vm).modules;
+        } catch (JDWPException exc) {
+            throw exc.toJDIException();
+        }
+        ArrayList<ModuleReference> modules = new ArrayList<>();
+        for (int i = 0; i < reqModules.length; i++) {
+            long moduleRef = reqModules[i].ref();
+            ModuleReference module = getModule(moduleRef);
+            modules.add(module);
+        }
+        return modules;
+    }
+
     private List<ReferenceType> retrieveClassesBySignature(String signature) {
         if ((vm.traceFlags & VirtualMachine.TRACE_REFTYPES) != 0) {
             vm.printTrace("Retrieving matching ReferenceTypes, sig=" + signature);
@@ -1364,6 +1416,10 @@
                                                       JDWP.Tag.CLASS_OBJECT);
     }
 
+    ModuleReferenceImpl moduleMirror(long id) {
+        return (ModuleReferenceImpl)getModule(id);
+    }
+
     /*
      * Implementation of PathSearchingVirtualMachine
      */
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
index 3704b41..069fd16 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, 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
@@ -47,8 +47,8 @@
     private final ThreadGroup mainGroupForJDI;
     private ResourceBundle messages = null;
     private int vmSequenceNumber = 0;
-    private static final int majorVersion = 1;
-    private static final int minorVersion = 8;
+    private static final int majorVersion = 9;
+    private static final int minorVersion = 0;
 
     private static final Object lock = new Object();
     private static VirtualMachineManagerImpl vmm;
diff --git a/jdk/src/jdk.jdi/share/classes/module-info.java b/jdk/src/jdk.jdi/share/classes/module-info.java
new file mode 100644
index 0000000..668c5b5
--- /dev/null
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jdi {
+    requires jdk.attach;
+
+    exports com.sun.jdi;
+    exports com.sun.jdi.connect;
+    exports com.sun.jdi.connect.spi;
+    exports com.sun.jdi.event;
+    exports com.sun.jdi.request;
+    exports com.sun.tools.jdi to jdk.hotspot.agent;
+
+    uses com.sun.jdi.connect.Connector;
+    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;
+}
+
diff --git a/jdk/src/jdk.jdi/windows/classes/module-info.java.extra b/jdk/src/jdk.jdi/windows/classes/module-info.java.extra
new file mode 100644
index 0000000..d048daa
--- /dev/null
+++ b/jdk/src/jdk.jdi/windows/classes/module-info.java.extra
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SharedMemoryAttachingConnector;
+provides com.sun.jdi.connect.Connector with 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
new file mode 100644
index 0000000..c456bbc
--- /dev/null
+++ b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jdwp.agent {
+}
+
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/JDWP.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/JDWP.h
index 35d9877..92a9f45 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/JDWP.h
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/JDWP.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2005, 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
@@ -60,7 +60,7 @@
            JDWP_InvokeOptions_INVOKE_ ## name
 #define JDWP_ERROR(name) \
            JDWP_Error_ ## name
-#define JDWP_HIGHEST_COMMAND_SET 17
+#define JDWP_HIGHEST_COMMAND_SET 18
 #define JDWP_REQUEST_NONE        -1
 
 /* This typedef helps keep the event and error types straight. */
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c
new file mode 100644
index 0000000..20cd986
--- /dev/null
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "util.h"
+#include "inStream.h"
+#include "outStream.h"
+#include "ModuleReferenceImpl.h"
+
+
+static jclass jlrM(JNIEnv *env) {
+    return findClass(env, "Ljava/lang/reflect/Module;");
+}
+
+static jboolean
+getName(PacketInputStream *in, PacketOutputStream *out)
+{
+    static jmethodID method = NULL;
+    JNIEnv *env = getEnv();
+    char *name = NULL;
+    jstring namestr;
+    jobject module;
+
+    if (method == NULL) {
+        method = getMethod(env, jlrM(env), "getName", "()Ljava/lang/String;");
+    }
+    module = inStream_readModuleRef(getEnv(), in);
+    if (inStream_error(in)) {
+        return JNI_TRUE;
+    }
+    namestr = (jstring)JNI_FUNC_PTR(env, CallObjectMethod) (env, module, method);
+    if (namestr != NULL) {
+        name = (char*)JNI_FUNC_PTR(env, GetStringUTFChars)(env, namestr, NULL);
+    } else {
+        // The JDWP converts null into an empty string
+    }
+    (void)outStream_writeString(out, name);
+    if (name != NULL) {
+        jvmtiDeallocate(name);
+    }
+    return JNI_TRUE;
+}
+
+static jboolean
+getClassLoader(PacketInputStream *in, PacketOutputStream *out)
+{
+    static jmethodID method = NULL;
+    JNIEnv *env = getEnv();
+    jobject loader;
+    jobject module;
+
+    if (method == NULL) {
+        method = getMethod(env, jlrM(env), "getClassLoader", "()Ljava/lang/ClassLoader;");
+    }
+    module = inStream_readModuleRef(env, in);
+    if (inStream_error(in)) {
+        return JNI_TRUE;
+    }
+    loader = JNI_FUNC_PTR(env, CallObjectMethod) (env, module, method);
+
+    (void)outStream_writeObjectRef(env, out, loader);
+    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.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.h
new file mode 100644
index 0000000..e2cba7c
--- /dev/null
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+extern void *ModuleReference_Cmds[];
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ReferenceTypeImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ReferenceTypeImpl.c
index 98ebd22..b885733 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ReferenceTypeImpl.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ReferenceTypeImpl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2005, 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
@@ -109,6 +109,26 @@
 }
 
 static jboolean
+getModule(PacketInputStream *in, PacketOutputStream *out)
+{
+    jobject clazz;
+    jobject module;
+    JNIEnv *env;
+
+    env = getEnv();
+
+    clazz = inStream_readClassRef(env, in);
+    if (inStream_error(in)) {
+        return JNI_TRUE;
+    }
+
+    module = JNI_FUNC_PTR(env, GetModule)(env, clazz);
+
+    (void)outStream_writeModuleRef(env, out, module);
+    return JNI_TRUE;
+}
+
+static jboolean
 modifiers(PacketInputStream *in, PacketOutputStream *out)
 {
     jint modifiers;
@@ -605,7 +625,7 @@
     return JNI_TRUE;
 }
 
-void *ReferenceType_Cmds[] = { (void *)18
+void *ReferenceType_Cmds[] = { (void *)19
     ,(void *)signature
     ,(void *)getClassLoader
     ,(void *)modifiers
@@ -624,4 +644,5 @@
     ,(void *)instances
     ,(void *)getClassVersion
     ,(void *)getConstantPool
+    ,(void *)getModule
 };
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
index e856392..2718ad1 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, 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
@@ -35,8 +35,8 @@
 #include "FrameID.h"
 
 static char *versionName = "Java Debug Wire Protocol (Reference Implementation)";
-static int majorVersion = 1;  /* JDWP major version */
-static int minorVersion = 8;  /* JDWP minor version */
+static int majorVersion = 9;  /* JDWP major version */
+static int minorVersion = 0;  /* JDWP minor version */
 
 static jboolean
 version(PacketInputStream *in, PacketOutputStream *out)
@@ -190,6 +190,41 @@
 }
 
 static jboolean
+allModules(PacketInputStream *in, PacketOutputStream *out)
+{
+    JNIEnv *env;
+
+    if (gdata->vmDead) {
+        outStream_setError(out, JDWP_ERROR(VM_DEAD));
+        return JNI_TRUE;
+    }
+
+    env = getEnv();
+
+    WITH_LOCAL_REFS(env, 1) {
+
+        jint count = 0;
+        jint i = 0;
+        jobject* modules = NULL;
+        jvmtiError error = JVMTI_ERROR_NONE;
+
+        error = JVMTI_FUNC_PTR(gdata->jvmti, GetAllModules) (gdata->jvmti, &count, &modules);
+        if (error != JVMTI_ERROR_NONE) {
+            outStream_setError(out, map2jdwpError(error));
+        } else {
+            (void)outStream_writeInt(out, count);
+            for (i = 0; i < count; i++) {
+                (void)outStream_writeModuleRef(env, out, modules[i]);
+            }
+            jvmtiDeallocate(modules);
+        }
+
+    } END_WITH_LOCAL_REFS(env);
+
+    return JNI_TRUE;
+}
+
+static jboolean
 allClasses1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics)
 {
     JNIEnv *env;
@@ -747,6 +782,7 @@
     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_constant_pool);
     /* 21 Can force early return */
     (void)outStream_writeBoolean(out, (jboolean)caps.can_force_early_return);
+
     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 22 */
     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 23 */
     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 24 */
@@ -823,7 +859,6 @@
 classPaths(PacketInputStream *in, PacketOutputStream *out)
 {
     char *ud;
-    char *bp;
     char *cp;
 
     ud = gdata->property_user_dir;
@@ -834,13 +869,9 @@
     if ( cp == NULL ) {
         cp = "";
     }
-    bp = gdata->property_sun_boot_class_path;
-    if ( bp == NULL ) {
-        bp = "";
-    }
     (void)outStream_writeString(out, ud);
     writePaths(out, cp);
-    writePaths(out, bp);
+    (void)outStream_writeInt(out, 0); // no bootclasspath
     return JNI_TRUE;
 }
 
@@ -890,7 +921,7 @@
     return JNI_TRUE;
 }
 
-void *VirtualMachine_Cmds[] = { (void *)21
+void *VirtualMachine_Cmds[] = { (void *)22
     ,(void *)version
     ,(void *)classesForSignature
     ,(void *)allClasses
@@ -912,4 +943,5 @@
     ,(void *)setDefaultStratum
     ,(void *)allClassesWithGeneric
     ,(void *)instanceCounts
+    ,(void *)allModules
 };
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugDispatch.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugDispatch.c
index e9e8c0e..0237fcb 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugDispatch.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugDispatch.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, 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
@@ -33,6 +33,7 @@
 #include "ArrayTypeImpl.h"
 #include "FieldImpl.h"
 #include "MethodImpl.h"
+#include "ModuleReferenceImpl.h"
 #include "ObjectReferenceImpl.h"
 #include "StringReferenceImpl.h"
 #include "ThreadReferenceImpl.h"
@@ -82,6 +83,7 @@
     l1Array[JDWP_COMMAND_SET(EventRequest)] = (void *)EventRequest_Cmds;
     l1Array[JDWP_COMMAND_SET(StackFrame)] = (void *)StackFrame_Cmds;
     l1Array[JDWP_COMMAND_SET(ClassObjectReference)] = (void *)ClassObjectReference_Cmds;
+    l1Array[JDWP_COMMAND_SET(ModuleReference)] = (void *)ModuleReference_Cmds;
 }
 
 void
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.c
index 0e1ca3f..3624e7e 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -165,6 +165,24 @@
 }
 
 /*
+ * Read a module from the stream. The ID used in the wire protocol
+ * is converted to a reference which is returned. The reference is
+ * global and strong, but it should *not* be deleted by the caller
+ * since it is freed when this stream is destroyed.
+ */
+jobject
+inStream_readModuleRef(JNIEnv *env, PacketInputStream *stream)
+{
+    jobject ref = inStream_readObjectRef(env, stream);
+    if (ref == NULL && stream->error == JDWP_ERROR(INVALID_OBJECT)) {
+        stream->error = JDWP_ERROR(INVALID_MODULE);
+        return NULL;
+    }
+
+    return ref;
+}
+
+/*
  * Read an object from the stream. The ID used in the wire protocol
  * is converted to a reference which is returned. The reference is
  * global and strong, but it should *not* be deleted by the caller
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.h
index 03d7225..f017a01 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.h
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/inStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, 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
@@ -60,6 +60,7 @@
 jfieldID inStream_readFieldID(PacketInputStream *stream);
 jlocation inStream_readLocation(PacketInputStream *stream);
 
+jobject inStream_readModuleRef(JNIEnv *env, PacketInputStream *stream);
 jobject inStream_readObjectRef(JNIEnv *env, PacketInputStream *stream);
 jclass inStream_readClassRef(JNIEnv *env, PacketInputStream *stream);
 jthread inStream_readThreadRef(JNIEnv *env, PacketInputStream *stream);
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.c
index 17edb14..f1bf5c7 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, 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
@@ -197,6 +197,12 @@
 }
 
 jdwpError
+outStream_writeModuleRef(JNIEnv *env, PacketOutputStream *stream, jobject val)
+{
+    return outStream_writeObjectRef(env, stream, val);
+}
+
+jdwpError
 outStream_writeObjectRef(JNIEnv *env, PacketOutputStream *stream, jobject val)
 {
     jlong id;
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.h
index a16e37f..13c1c51 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.h
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/outStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2008, 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
@@ -67,6 +67,7 @@
 jdwpError outStream_writeLong(PacketOutputStream *stream, jlong val);
 jdwpError outStream_writeFloat(PacketOutputStream *stream, jfloat val);
 jdwpError outStream_writeDouble(PacketOutputStream *stream, jdouble val);
+jdwpError outStream_writeModuleRef(JNIEnv *env, PacketOutputStream *stream, jobject val);
 jdwpError outStream_writeObjectRef(JNIEnv *env, PacketOutputStream *stream, jobject val);
 jdwpError outStream_writeObjectTag(JNIEnv *env, PacketOutputStream *stream, jobject val);
 jdwpError outStream_writeFrameID(PacketOutputStream *stream, FrameID val);
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.c
index 70b93dc..a870db1 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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 @@
     *pobj = NULL;
 }
 
-static jclass
+jclass
 findClass(JNIEnv *env, const char * name)
 {
     jclass x;
@@ -109,7 +109,7 @@
     return x;
 }
 
-static jmethodID
+jmethodID
 getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
 {
     jmethodID method;
@@ -250,8 +250,6 @@
                         = getPropertyUTF8(env, "java.vm.info");
         gdata->property_java_class_path
                         = getPropertyUTF8(env, "java.class.path");
-        gdata->property_sun_boot_class_path
-                        = getPropertyUTF8(env, "sun.boot.class.path");
         gdata->property_sun_boot_library_path
                         = getPropertyUTF8(env, "sun.boot.library.path");
         gdata->property_path_separator
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h
index 9ccb38c..17aefef6 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -113,7 +113,6 @@
     char* property_java_vm_name;          /* UTF8 java.vm.name */
     char* property_java_vm_info;          /* UTF8 java.vm.info */
     char* property_java_class_path;       /* UTF8 java.class.path */
-    char* property_sun_boot_class_path;   /* UTF8 sun.boot.class.path */
     char* property_sun_boot_library_path; /* UTF8 sun.boot.library.path */
     char* property_path_separator;        /* UTF8 path.separator */
     char* property_user_dir;              /* UTF8 user.dir */
@@ -194,6 +193,7 @@
 #define AGENT_ERROR_INVALID_EVENT_TYPE          _AGENT_ERROR(24)
 #define AGENT_ERROR_INVALID_OBJECT              _AGENT_ERROR(25)
 #define AGENT_ERROR_NO_MORE_FRAMES              _AGENT_ERROR(26)
+#define AGENT_ERROR_INVALID_MODULE              _AGENT_ERROR(27)
 
 /* Combined event information */
 
@@ -354,6 +354,9 @@
 
 void threadGroupInfo(jthreadGroup, jvmtiThreadGroupInfo *info);
 
+jclass findClass(JNIEnv *env, const char * name);
+jmethodID getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature);
+char *getModuleName(jclass);
 char *getClassname(jclass);
 jvmtiError classSignature(jclass, char**, char**);
 jint classStatus(jclass);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java
new file mode 100644
index 0000000..7090f76
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jimage;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Consumer;
+import jdk.tools.jlink.internal.ImageFileCreator;
+import jdk.tools.jlink.internal.Archive;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.DirArchive;
+/**
+ *
+ * Support for extracted image.
+ */
+public final class ExtractedImage {
+
+    private Set<Archive> archives = new HashSet<>();
+    private final ImagePluginStack plugins;
+
+    ExtractedImage(Path dirPath, ImagePluginStack plugins, PrintWriter log,
+            boolean verbose) throws IOException {
+        if (!Files.isDirectory(dirPath)) {
+            throw new IOException("Not a directory");
+        }
+        Consumer<String> cons = (String t) -> {
+            if (verbose) {
+                log.println(t);
+            }
+        };
+        this.plugins = plugins;
+        Files.walk(dirPath, 1).forEach((p) -> {
+            if (!dirPath.equals(p)) {
+                if (Files.isDirectory(p)) {
+                    Archive a = new DirArchive(p, cons);
+                    archives.add(a);
+                }
+            }
+        });
+        archives = Collections.unmodifiableSet(archives);
+    }
+
+    void recreateJImage(Path path) throws IOException {
+        ImageFileCreator.recreateJimage(path, archives, plugins);
+    }
+
+    private static String getPathName(Path path) {
+        return path.toString().replace(File.separatorChar, '/');
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java
new file mode 100644
index 0000000..44a6bcc
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jimage;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import static java.nio.file.StandardOpenOption.READ;
+import static java.nio.file.StandardOpenOption.WRITE;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.internal.jimage.BasicImageReader;
+import jdk.internal.jimage.ImageHeader;
+import static jdk.internal.jimage.ImageHeader.MAGIC;
+import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION;
+import static jdk.internal.jimage.ImageHeader.MINOR_VERSION;
+import jdk.internal.jimage.ImageLocation;
+import jdk.tools.jlink.internal.ImageResourcesTree;
+import jdk.tools.jlink.internal.ImagePluginConfiguration;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.TaskHelper;
+import jdk.tools.jlink.internal.TaskHelper.BadArgs;
+import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE;
+import jdk.tools.jlink.internal.TaskHelper.Option;
+import jdk.tools.jlink.internal.TaskHelper.OptionsHelper;
+
+class JImageTask {
+
+    static final Option<?>[] recognizedOptions = {
+        new Option<JImageTask>(true, (task, opt, arg) -> {
+            task.options.directory = arg;
+        }, "--dir"),
+        new Option<JImageTask>(false, (task, opt, arg) -> {
+            task.options.fullVersion = true;
+        }, true, "--fullversion"),
+        new Option<JImageTask>(false, (task, opt, arg) -> {
+            task.options.help = true;
+        }, "--help"),
+        new Option<JImageTask>(true, (task, opt, arg) -> {
+            task.options.flags = arg;
+        }, "--flags"),
+        new Option<JImageTask>(false, (task, opt, arg) -> {
+            task.options.verbose = true;
+        }, "--verbose"),
+        new Option<JImageTask>(false, (task, opt, arg) -> {
+            task.options.version = true;
+        }, "--version")
+    };
+    private static final TaskHelper taskHelper
+            = new TaskHelper(JIMAGE_BUNDLE);
+    private static final OptionsHelper<JImageTask> optionsHelper
+            = taskHelper.newOptionsHelper(JImageTask.class, recognizedOptions);
+
+    static class OptionsValues {
+        Task task = Task.LIST;
+        String directory = ".";
+        boolean fullVersion;
+        boolean help;
+        String flags;
+        boolean verbose;
+        boolean version;
+        List<File> jimages = new LinkedList<>();
+    }
+
+    private static final String PROGNAME = "jimage";
+    private final OptionsValues options = new OptionsValues();
+
+    enum Task {
+        EXTRACT,
+        INFO,
+        LIST,
+        RECREATE,
+        SET,
+        VERIFY
+    };
+
+    private String pad(String string, int width, boolean justifyRight) {
+        int length = string.length();
+
+        if (length == width) {
+            return string;
+        }
+
+        if (length > width) {
+            return string.substring(0, width);
+        }
+
+        int padding = width - length;
+
+        StringBuilder sb = new StringBuilder(width);
+        if (justifyRight) {
+            for (int i = 0; i < padding; i++) {
+                sb.append(' ');
+            }
+        }
+
+        sb.append(string);
+
+        if (!justifyRight) {
+            for (int i = 0; i < padding; i++) {
+                sb.append(' ');
+            }
+        }
+
+        return sb.toString();
+    }
+
+    private String pad(String string, int width) {
+        return pad(string, width, false);
+    }
+
+    private String pad(long value, int width) {
+        return pad(Long.toString(value), width, true);
+    }
+
+    private static final int EXIT_OK = 0;        // No errors.
+    private static final int EXIT_ERROR = 1;     // Completed but reported errors.
+    private static final int EXIT_CMDERR = 2;    // Bad command-line arguments and/or switches.
+    private static final int EXIT_SYSERR = 3;    // System error or resource exhaustion.
+    private static final int EXIT_ABNORMAL = 4;  // Terminated abnormally.
+
+    int run(String[] args) {
+        if (log == null) {
+            setLog(new PrintWriter(System.out));
+        }
+
+        try {
+            List<String> unhandled = optionsHelper.handleOptions(this, args);
+            if(!unhandled.isEmpty()) {
+                options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase());
+                for(int i = 1; i < unhandled.size(); i++) {
+                    options.jimages.add(new File(unhandled.get(i)));
+                }
+            }
+            if (options.help) {
+                optionsHelper.showHelp(PROGNAME);
+            }
+            if(optionsHelper.listPlugins()) {
+                optionsHelper.listPlugins(true);
+                return EXIT_OK;
+            }
+            if (options.version || options.fullVersion) {
+                taskHelper.showVersion(options.fullVersion);
+            }
+            boolean ok = run();
+            return ok ? EXIT_OK : EXIT_ERROR;
+        } catch (BadArgs e) {
+            taskHelper.reportError(e.key, e.args);
+            if (e.showUsage) {
+                log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
+            }
+            return EXIT_CMDERR;
+        } catch (Exception x) {
+            x.printStackTrace();
+            return EXIT_ABNORMAL;
+        } finally {
+            log.flush();
+        }
+    }
+
+    private void recreate() throws Exception, BadArgs {
+        File directory = new File(options.directory);
+        if (!directory.isDirectory()) {
+            throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath());
+        }
+        Path dirPath = directory.toPath();
+        if (options.jimages.isEmpty()) {
+            throw taskHelper.newBadArgs("err.jimage.not.specified");
+        } else if (options.jimages.size() != 1) {
+            throw taskHelper.newBadArgs("err.only.one.jimage");
+        }
+
+        Path jimage = options.jimages.get(0).toPath();
+
+        if (jimage.toFile().createNewFile()) {
+            ImagePluginStack pc = ImagePluginConfiguration.parseConfiguration(taskHelper.
+                    getPluginsConfig(null, false));
+            ExtractedImage img = new ExtractedImage(dirPath, pc, log, options.verbose);
+            img.recreateJImage(jimage);
+        } else {
+            throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName());
+        }
+    }
+
+    private void title(File file, BasicImageReader reader) {
+        log.println("jimage: " + file.getName());
+    }
+
+    private void listTitle(File file, BasicImageReader reader) {
+        title(file, reader);
+
+        if (options.verbose) {
+            log.print(pad("Offset", OFFSET_WIDTH + 1));
+            log.print(pad("Size", SIZE_WIDTH + 1));
+            log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1));
+            log.println(" Entry");
+        }
+    }
+
+    private interface JImageAction {
+        public void apply(File file, BasicImageReader reader) throws IOException, BadArgs;
+    }
+
+    private interface ResourceAction {
+        public void apply(BasicImageReader reader, String name,
+                ImageLocation location) throws IOException, BadArgs;
+    }
+
+    private void extract(BasicImageReader reader, String name,
+            ImageLocation location) throws IOException, BadArgs {
+        File directory = new File(options.directory);
+        byte[] bytes = reader.getResource(location);
+        File resource =  new File(directory, name);
+        File parent = resource.getParentFile();
+
+        if (parent.exists()) {
+            if (!parent.isDirectory()) {
+                throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath());
+            }
+        } else if (!parent.mkdirs()) {
+            throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath());
+        }
+
+        if (!ImageResourcesTree.isTreeInfoResource(name)) {
+            Files.write(resource.toPath(), bytes);
+        }
+    }
+
+    private static final int NUMBER_WIDTH = 12;
+    private static final int OFFSET_WIDTH = NUMBER_WIDTH;
+    private static final int SIZE_WIDTH = NUMBER_WIDTH;
+    private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH;
+
+    private void print(String entry, ImageLocation location) {
+        log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " ");
+        log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " ");
+        log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " ");
+        log.println(entry);
+    }
+
+    private void print(BasicImageReader reader, String entry) {
+        if (options.verbose) {
+            print(entry, reader.findLocation(entry));
+        } else {
+            log.println(entry);
+        }
+    }
+
+    private void info(File file, BasicImageReader reader) throws IOException {
+        ImageHeader header = reader.getHeader();
+
+        log.println(" Major Version:  " + header.getMajorVersion());
+        log.println(" Minor Version:  " + header.getMinorVersion());
+        log.println(" Flags:          " + Integer.toHexString(header.getMinorVersion()));
+        log.println(" Resource Count: " + header.getResourceCount());
+        log.println(" Table Length:   " + header.getTableLength());
+        log.println(" Offsets Size:   " + header.getOffsetsSize());
+        log.println(" Redirects Size: " + header.getRedirectSize());
+        log.println(" Locations Size: " + header.getLocationsSize());
+        log.println(" Strings Size:   " + header.getStringsSize());
+        log.println(" Index Size:     " + header.getIndexSize());
+    }
+
+    private void list(BasicImageReader reader, String name, ImageLocation location) {
+        print(reader, name);
+    }
+
+    void set(File file, BasicImageReader reader) throws BadArgs {
+        try {
+            ImageHeader oldHeader = reader.getHeader();
+
+            int value = 0;
+            try {
+                value = Integer.valueOf(options.flags);
+            } catch (NumberFormatException ex) {
+                throw taskHelper.newBadArgs("err.flags.not.int", options.flags);
+            }
+
+            ImageHeader newHeader = new ImageHeader(MAGIC, MAJOR_VERSION, MINOR_VERSION,
+                    value,
+                    oldHeader.getResourceCount(), oldHeader.getTableLength(),
+                    oldHeader.getLocationsSize(), oldHeader.getStringsSize());
+
+            ByteBuffer buffer = ByteBuffer.allocate(ImageHeader.getHeaderSize());
+            buffer.order(ByteOrder.nativeOrder());
+            newHeader.writeTo(buffer);
+            buffer.rewind();
+
+            try (FileChannel channel = FileChannel.open(file.toPath(), READ, WRITE)) {
+                channel.write(buffer, 0);
+            }
+        } catch (IOException ex) {
+            throw taskHelper.newBadArgs("err.cannot.update.file", file.getName());
+        }
+    }
+
+     void verify(BasicImageReader reader, String name, ImageLocation location) {
+        if (name.endsWith(".class")) {
+            byte[] bytes = reader.getResource(location);
+
+            if (bytes == null || bytes.length <= 4 ||
+                (bytes[0] & 0xFF) != 0xCA ||
+                (bytes[1] & 0xFF) != 0xFE ||
+                (bytes[2] & 0xFF) != 0xBA ||
+                (bytes[3] & 0xFF) != 0xBE) {
+                log.print(" NOT A CLASS: ");
+                print(reader, name);
+            }
+        }
+    }
+
+    private void iterate(JImageAction jimageAction,
+            ResourceAction resourceAction) throws IOException, BadArgs {
+        for (File file : options.jimages) {
+            if (!file.exists() || !file.isFile()) {
+                throw taskHelper.newBadArgs("err.not.a.jimage", file.getName());
+            }
+
+            try (BasicImageReader reader = BasicImageReader.open(file.toPath())) {
+                if (jimageAction != null) {
+                    jimageAction.apply(file, reader);
+                }
+
+                if (resourceAction != null) {
+                    String[] entryNames = reader.getEntryNames();
+
+                    for (String name : entryNames) {
+                        if (!ImageResourcesTree.isTreeInfoResource(name)) {
+                            ImageLocation location = reader.findLocation(name);
+                            resourceAction.apply(reader, name, location);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean run() throws Exception, BadArgs {
+        switch (options.task) {
+            case EXTRACT:
+                iterate(null, this::extract);
+                break;
+            case INFO:
+                iterate(this::info, null);
+                break;
+            case LIST:
+                iterate(this::listTitle, this::list);
+                break;
+            case RECREATE:
+                recreate();
+                break;
+            case SET:
+                iterate(this::set, null);
+                break;
+            case VERIFY:
+                iterate(this::title, this::verify);
+                break;
+            default:
+                throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true);
+        }
+        return true;
+    }
+
+    private PrintWriter log;
+    void setLog(PrintWriter out) {
+        log = out;
+        taskHelper.setLog(log);
+    }
+}
diff --git a/jdk/src/jdk.dev/share/classes/jdk/tools/jimage/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/Main.java
similarity index 100%
rename from jdk/src/jdk.dev/share/classes/jdk/tools/jimage/Main.java
rename to jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/Main.java
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties
new file mode 100644
index 0000000..857d52b
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties
@@ -0,0 +1,64 @@
+main.usage.summary=\
+Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\
+use --help for a list of possible options
+
+main.usage=\
+Usage: {0} <extract|info|list|recreate|set|verify> <options> jimage...\n\
+\n\
+\  extract  - Extract all jimage entries into separate files into the directory\n\
+\             specified by --dir=<directory> (default='.')\n\
+\  info     - Prints information specified in the jimage header.\n\
+\  list     - Prints the names of all the entries in the jimage.  When used with\n\
+\             --verbose will also print entry attributes ex. size and offset.\n\
+\  recreate - Reconstructs a jimage from an extracted directory (--dir)\n\
+\  set      - sets the value of specific jimage header entries\n\
+\  verify   - Reports errors on any .class entries that don't verify as classes.\n\
+\n\
+Possible options include:
+
+main.extended.help=\
+jimage recreate is extensible by the main of plugins. Following plugins have been discovered \
+thanks to ServiceLoader and can be used when re-creating a jimage.
+
+error.prefix=Error:
+warn.prefix=Warning:
+
+main.opt.dir=\
+\  --dir                                Target directory for extract/recreate
+
+main.opt.flags=\
+\  --flags=value                        Set the jimage flags to value
+
+main.opt.help=\
+\  --help                               Print this usage message
+
+main.opt.verbose=\
+\  --verbose                            Verbose listing
+
+main.opt.version=\
+\  --version                            Version information
+
+main.opt.configuration=\
+\  --configuration <path>               Path to properties file containing defaults\
+\ options for recreate
+
+main.command.files=\
+\  @<filename>                          Read options from file
+
+err.cannot.create.dir=cannot create directory: {0}
+err.cannot.read.file=cannot read file: {0}
+err.cannot.update.file=cannot update file: {0}
+err.file.not.found=cannot find file: {0}
+err.file.error=cannot access file: {0}
+err.flags.not.int=--flags value not integer: {0}
+err.internal.error=internal error: {0} {1} {2}
+err.invalid.arg.for.option=invalid argument for option: {0}
+err.invalid.task=task must be extract|recreate|info|list|verify: {0}
+err.jimage.already.exists=jimage already exists: {0}
+err.jimage.not.specified=no jimage specified
+err.missing.arg=no value given for {0}
+err.not.a.dir=not a directory: {0}
+err.not.a.jimage=not a jimage file: {0}
+err.only.one.jimage=only one jimage should be specified
+err.option.unsupported={0} not supported: {1}
+err.unknown.option=unknown option: {0}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
new file mode 100644
index 0000000..92d7eb6
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/Jlink.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink;
+
+import java.lang.reflect.Layer;
+import java.nio.ByteOrder;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import jdk.tools.jlink.internal.JlinkTask;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginContext;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.internal.PluginContextImpl;
+import jdk.tools.jlink.internal.PluginRepository;
+
+/**
+ * API to call jlink.
+ */
+public final class Jlink {
+
+    /**
+     * Create a plugin.
+     *
+     * @param name Plugin name
+     * @param configuration Plugin configuration.
+     * @param pluginsLayer Plugins Layer. null means boot layer.
+     * @return A new plugin or null if plugin is unknown.
+     */
+    public static Plugin newPlugin(String name,
+            Map<String, String> configuration, Layer pluginsLayer) {
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(configuration);
+        pluginsLayer = pluginsLayer == null ? Layer.boot() : pluginsLayer;
+        return PluginRepository.newPlugin(configuration, name, pluginsLayer);
+    }
+
+    /**
+     * A complete plugin configuration. Instances of this class are used to
+     * configure jlink.
+     */
+    public static final class PluginsConfiguration {
+
+        private final List<Plugin> plugins;
+        private final ImageBuilder imageBuilder;
+        private final String lastSorterPluginName;
+        private final PluginContext pluginContext;
+
+        /**
+         * Empty plugins configuration.
+         */
+        public PluginsConfiguration() {
+            this(Collections.emptyList());
+        }
+
+        /**
+         * Plugins configuration.
+         *
+         * @param plugins List of plugins.
+         */
+        public PluginsConfiguration(List<Plugin> plugins) {
+            this(plugins, null, null, null);
+        }
+
+        /**
+         * Plugins configuration with a last sorter and an ImageBuilder. No
+         * sorting can occur after the last sorter plugin. The ImageBuilder is
+         * in charge to layout the image content on disk.
+         *
+         * @param plugins List of transformer plugins.
+         * @param imageBuilder Image builder.
+         * @param lastSorterPluginName Name of last sorter plugin, no sorting
+         * can occur after it.
+         */
+        public PluginsConfiguration(List<Plugin> plugins,
+                ImageBuilder imageBuilder, String lastSorterPluginName) {
+            this(plugins, imageBuilder, lastSorterPluginName, null);
+        }
+
+        /**
+         * Plugins configuration with a last sorter and an ImageBuilder. No
+         * sorting can occur after the last sorter plugin. The ImageBuilder is
+         * in charge to layout the image content on disk.
+         *
+         * @param plugins List of transformer plugins.
+         * @param imageBuilder Image builder.
+         * @param lastSorterPluginName Name of last sorter plugin, no sorting
+         * @param ctx the plugin context
+         * can occur after it.
+         */
+        public PluginsConfiguration(List<Plugin> plugins,
+                ImageBuilder imageBuilder, String lastSorterPluginName,
+                PluginContext ctx) {
+            this.plugins = plugins == null ? Collections.emptyList()
+                    : plugins;
+            this.imageBuilder = imageBuilder;
+            this.lastSorterPluginName = lastSorterPluginName;
+            this.pluginContext = ctx != null? ctx : new PluginContextImpl();
+        }
+
+        /**
+         * @return the plugins
+         */
+        public List<Plugin> getPlugins() {
+            return plugins;
+        }
+
+        /**
+         * @return the imageBuilder
+         */
+        public ImageBuilder getImageBuilder() {
+            return imageBuilder;
+        }
+
+        /**
+         * @return the lastSorterPluginName
+         */
+        public String getLastSorterPluginName() {
+            return lastSorterPluginName;
+        }
+
+        /**
+         * @return the pluginContext
+         */
+        public PluginContext getPluginContext() {
+            return pluginContext;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("imagebuilder=").append(imageBuilder).append("\n");
+            StringBuilder pluginsBuilder = new StringBuilder();
+            for (Plugin p : plugins) {
+                pluginsBuilder.append(p).append(",");
+            }
+            builder.append("plugins=").append(pluginsBuilder).append("\n");
+            builder.append("lastsorter=").append(lastSorterPluginName).append("\n");
+
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Jlink configuration. Instances of this class are used to configure jlink.
+     */
+    public static final class JlinkConfiguration {
+
+        private final List<Path> modulepaths;
+        private final Path output;
+        private final Set<String> modules;
+        private final Set<String> limitmods;
+
+        private final ByteOrder endian;
+
+        /**
+         * jlink configuration,
+         *
+         * @param output Output directory, must not exist.
+         * @param modulepaths Modules paths
+         * @param modules Root modules to resolve
+         * @param limitmods Limit the universe of observable modules
+         * @param endian Jimage byte order. Native order by default
+         */
+        public JlinkConfiguration(Path output,
+                List<Path> modulepaths,
+                Set<String> modules,
+                Set<String> limitmods,
+                ByteOrder endian) {
+            this.output = output;
+            this.modulepaths = modulepaths == null ? Collections.emptyList() : modulepaths;
+            this.modules = modules == null ? Collections.emptySet() : modules;
+            this.limitmods = limitmods == null ? Collections.emptySet() : limitmods;
+            this.endian = endian == null ? ByteOrder.nativeOrder() : endian;
+        }
+
+        /**
+         * jlink configuration,
+         *
+         * @param output Output directory, must not exist.
+         * @param modulepaths Modules paths
+         * @param modules Root modules to resolve
+         * @param limitmods Limit the universe of observable modules
+         */
+        public JlinkConfiguration(Path output,
+                List<Path> modulepaths,
+                Set<String> modules,
+                Set<String> limitmods) {
+            this(output, modulepaths, modules, limitmods,
+                    ByteOrder.nativeOrder());
+        }
+
+        /**
+         * @return the modulepaths
+         */
+        public List<Path> getModulepaths() {
+            return modulepaths;
+        }
+
+        /**
+         * @return the byte ordering
+         */
+        public ByteOrder getByteOrder() {
+            return endian;
+        }
+
+        /**
+         * @return the output
+         */
+        public Path getOutput() {
+            return output;
+        }
+
+        /**
+         * @return the modules
+         */
+        public Set<String> getModules() {
+            return modules;
+        }
+
+        /**
+         * @return the limitmods
+         */
+        public Set<String> getLimitmods() {
+            return limitmods;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+
+            builder.append("output=").append(output).append("\n");
+            StringBuilder pathsBuilder = new StringBuilder();
+            for (Path p : modulepaths) {
+                pathsBuilder.append(p).append(",");
+            }
+            builder.append("modulepaths=").append(pathsBuilder).append("\n");
+
+            StringBuilder modsBuilder = new StringBuilder();
+            for (String p : modules) {
+                modsBuilder.append(p).append(",");
+            }
+            builder.append("modules=").append(modsBuilder).append("\n");
+
+            StringBuilder limitsBuilder = new StringBuilder();
+            for (String p : limitmods) {
+                limitsBuilder.append(p).append(",");
+            }
+            builder.append("limitmodules=").append(limitsBuilder).append("\n");
+            builder.append("endian=").append(endian).append("\n");
+            return builder.toString();
+        }
+    }
+
+    /**
+     * Jlink instance constructor, if a security manager is set, the jlink
+     * permission is checked.
+     */
+    public Jlink() {
+        if (System.getSecurityManager() != null) {
+            System.getSecurityManager().
+                    checkPermission(new JlinkPermission("jlink"));
+        }
+    }
+
+    /**
+     * Build the image.
+     *
+     * @param config Jlink config, must not be null.
+     * @throws PluginException
+     */
+    public void build(JlinkConfiguration config) {
+        build(config, null);
+    }
+
+    /**
+     * Build the image with a plugin configuration.
+     *
+     * @param config Jlink config, must not be null.
+     * @param pluginsConfig Plugins config, can be null
+     * @throws PluginException
+     */
+    public void build(JlinkConfiguration config, PluginsConfiguration pluginsConfig) {
+        Objects.requireNonNull(config);
+        try {
+            JlinkTask.createImage(config, pluginsConfig);
+        } catch (Exception ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+    /**
+     * Post process the image with a plugin configuration.
+     *
+     * @param image Existing image.
+     * @param plugins Plugins cannot be null
+     */
+    public void postProcess(ExecutableImage image, List<Plugin> plugins) {
+        Objects.requireNonNull(image);
+        Objects.requireNonNull(plugins);
+        try {
+            JlinkTask.postProcessImage(image, plugins);
+        } catch (Exception ex) {
+            throw new PluginException(ex);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java
new file mode 100644
index 0000000..0270f58
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/JlinkPermission.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink;
+
+import java.security.BasicPermission;
+
+/**
+ * The permission required to use jlink API. The permission target_name is
+ * "jlink". e.g.: permission jdk.tools.jlink.plugins.JlinkPermission "jlink";
+ *
+ */
+public final class JlinkPermission extends BasicPermission {
+
+    private static final long serialVersionUID = -3687912306077727801L;
+
+    public JlinkPermission(String name) {
+        super(name);
+    }
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
new file mode 100644
index 0000000..eb1e057
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.builder;
+
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.PluginException;
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.lang.module.ModuleDescriptor;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import jdk.tools.jlink.internal.BasicImageWriter;
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.Module;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+/**
+ *
+ * Default Image Builder. This builder creates the default runtime image layout.
+ */
+public class DefaultImageBuilder implements ImageBuilder {
+
+    /**
+     * The default java executable Image.
+     */
+    static class DefaultExecutableImage extends ExecutableImage {
+
+        public DefaultExecutableImage(Path home, Set<String> modules) {
+            super(home, modules, createArgs(home));
+        }
+
+        private static List<String> createArgs(Path home) {
+            Objects.requireNonNull(home);
+            List<String> javaArgs = new ArrayList<>();
+            javaArgs.add(home.resolve("bin").
+                    resolve(getJavaProcessName()).toString());
+            return javaArgs;
+        }
+
+        @Override
+        public void storeLaunchArgs(List<String> args) {
+            try {
+                patchScripts(this, args);
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+    }
+
+    private final Path root;
+    private final Path mdir;
+    private final boolean genBom;
+    private final Set<String> modules = new HashSet<>();
+
+    /**
+     * Default image builder constructor.
+     *
+     * @param genBom true, generates a bom file.
+     * @param root The image root directory.
+     * @throws IOException
+     */
+    public DefaultImageBuilder(boolean genBom, Path root) throws IOException {
+        Objects.requireNonNull(root);
+
+        this.genBom = genBom;
+
+        this.root = root;
+        this.mdir = root.resolve("lib");
+        Files.createDirectories(mdir);
+    }
+
+    private void storeFiles(Set<String> modules, String bom, Properties release) throws IOException {
+        if (release != null) {
+            addModules(release, modules);
+            File r = new File(root.toFile(), "release");
+            try (FileOutputStream fo = new FileOutputStream(r)) {
+                release.store(fo, null);
+            }
+        }
+        // Generate bom
+        if (genBom) {
+            File bomFile = new File(root.toFile(), "bom");
+            createUtf8File(bomFile, bom);
+        }
+    }
+
+    private void addModules(Properties release, Set<String> modules) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        int i = 0;
+        for (String m : modules) {
+            builder.append(m);
+            if (i < modules.size() - 1) {
+                builder.append(",");
+            }
+            i++;
+        }
+        release.setProperty("MODULES", builder.toString());
+    }
+
+    @Override
+    public void storeFiles(Pool files, String bom, Properties release) {
+        try {
+            for (ModuleData f : files.getContent()) {
+               if (!f.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
+                    accept(f);
+                }
+            }
+            for (Module m : files.getModules()) {
+                // Only add modules that contain packages
+                if (!m.getAllPackages().isEmpty()) {
+                    // Skip the fake module used by FileCopierPlugin when copying files.
+                    if (m.getName().equals(FileCopierPlugin.FAKE_MODULE)) {
+                       continue;
+                    }
+                    modules.add(m.getName());
+                }
+            }
+            storeFiles(modules, bom, release);
+
+            if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
+                // launchers in the bin directory need execute permission
+                Path bin = root.resolve("bin");
+                if (Files.isDirectory(bin)) {
+                    Files.list(bin)
+                            .filter(f -> !f.toString().endsWith(".diz"))
+                            .filter(f -> Files.isRegularFile(f))
+                            .forEach(this::setExecutable);
+                }
+
+                // jspawnhelper is in lib or lib/<arch>
+                Path lib = root.resolve("lib");
+                if (Files.isDirectory(lib)) {
+                    Files.find(lib, 2, (path, attrs) -> {
+                        return path.getFileName().toString().equals("jspawnhelper") ||
+                               path.getFileName().toString().equals("jexec");
+                    }).forEach(this::setExecutable);
+                }
+            }
+
+            prepareApplicationFiles(files, modules);
+        } catch (IOException ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+    @Override
+    public void storeFiles(Pool files, String bom) {
+        storeFiles(files, bom, new Properties());
+    }
+
+    /**
+     * Generates launcher scripts.
+     * @param imageContent The image content.
+     * @param modules The set of modules that the runtime image contains.
+     * @throws IOException
+     */
+    protected void prepareApplicationFiles(Pool imageContent, Set<String> modules) throws IOException {
+        // generate launch scripts for the modules with a main class
+        for (String module : modules) {
+            String path = "/" + module + "/module-info.class";
+            ModuleData res = imageContent.get(path);
+            if (res == null) {
+                throw new IOException("module-info.class not found for " + module + " module");
+            }
+            Optional<String> mainClass;
+            ByteArrayInputStream stream = new ByteArrayInputStream(res.getBytes());
+            mainClass = ModuleDescriptor.read(stream).mainClass();
+            if (mainClass.isPresent()) {
+                Path cmd = root.resolve("bin").resolve(module);
+                if (!Files.exists(cmd)) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("#!/bin/sh")
+                            .append("\n");
+                    sb.append("JLINK_VM_OPTIONS=")
+                            .append("\n");
+                    sb.append("DIR=`dirname $0`")
+                            .append("\n");
+                    sb.append("$DIR/java $JLINK_VM_OPTIONS -m ")
+                            .append(module).append('/')
+                            .append(mainClass.get())
+                            .append(" $@\n");
+
+                    try (BufferedWriter writer = Files.newBufferedWriter(cmd,
+                            StandardCharsets.ISO_8859_1,
+                            StandardOpenOption.CREATE_NEW)) {
+                        writer.write(sb.toString());
+                    }
+                    if (Files.getFileStore(root.resolve("bin"))
+                            .supportsFileAttributeView(PosixFileAttributeView.class)) {
+                        setExecutable(cmd);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public DataOutputStream getJImageOutputStream() {
+        try {
+            Path jimageFile = mdir.resolve(BasicImageWriter.MODULES_IMAGE_NAME);
+            OutputStream fos = Files.newOutputStream(jimageFile);
+            BufferedOutputStream bos = new BufferedOutputStream(fos);
+            return new DataOutputStream(bos);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    private void accept(ModuleData file) throws IOException {
+        String fullPath = file.getPath();
+        String module = "/" + file.getModule()+ "/";
+        String filename = fullPath.substring(module.length());
+        // Remove radical native|config|...
+        filename = filename.substring(filename.indexOf('/') + 1);
+        try (InputStream in = file.stream()) {
+            switch (file.getType()) {
+                case NATIVE_LIB:
+                    writeEntry(in, destFile(nativeDir(filename), filename));
+                    break;
+                case NATIVE_CMD:
+                    Path path = destFile("bin", filename);
+                    writeEntry(in, path);
+                    path.toFile().setExecutable(true);
+                    break;
+                case CONFIG:
+                    writeEntry(in, destFile("conf", filename));
+                    break;
+                case OTHER:
+                    if (file instanceof SymImageFile) {
+                        SymImageFile sym = (SymImageFile) file;
+                        Path target = root.resolve(sym.getTargetPath());
+                        if (!Files.exists(target)) {
+                            throw new IOException("Sym link target " + target
+                                    + " doesn't exist");
+                        }
+                        writeSymEntry(root.resolve(filename), target);
+                    } else {
+                        writeEntry(in, root.resolve(filename));
+                    }
+                    break;
+                default:
+                    throw new InternalError("unexpected entry: " + fullPath);
+            }
+        }
+    }
+
+    private Path destFile(String dir, String filename) {
+        return root.resolve(dir).resolve(filename);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Objects.requireNonNull(in);
+        Objects.requireNonNull(dstFile);
+        Files.createDirectories(Objects.requireNonNull(dstFile.getParent()));
+        Files.copy(in, dstFile);
+    }
+
+    private void writeSymEntry(Path dstFile, Path target) throws IOException {
+        Objects.requireNonNull(dstFile);
+        Objects.requireNonNull(target);
+        Files.createDirectories(Objects.requireNonNull(dstFile.getParent()));
+        Files.createLink(dstFile, target);
+    }
+
+    private static String nativeDir(String filename) {
+        if (isWindows()) {
+            if (filename.endsWith(".dll") || filename.endsWith(".diz")
+                    || filename.endsWith(".pdb") || filename.endsWith(".map")) {
+                return "bin";
+            } else {
+                return "lib";
+            }
+        } else {
+            return "lib";
+        }
+    }
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").startsWith("Windows");
+    }
+
+    /**
+     * chmod ugo+x file
+     */
+    private void setExecutable(Path file) {
+        try {
+            Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file);
+            perms.add(PosixFilePermission.OWNER_EXECUTE);
+            perms.add(PosixFilePermission.GROUP_EXECUTE);
+            perms.add(PosixFilePermission.OTHERS_EXECUTE);
+            Files.setPosixFilePermissions(file, perms);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    private static void createUtf8File(File file, String content) throws IOException {
+        try (OutputStream fout = new FileOutputStream(file);
+                Writer output = new OutputStreamWriter(fout, "UTF-8")) {
+            output.write(content);
+        }
+    }
+
+    @Override
+    public ExecutableImage getExecutableImage() {
+        return new DefaultExecutableImage(root, modules);
+    }
+
+    // This is experimental, we should get rid-off the scripts in a near future
+    private static void patchScripts(ExecutableImage img, List<String> args) throws IOException {
+        Objects.requireNonNull(args);
+        if (!args.isEmpty()) {
+            Files.find(img.getHome().resolve("bin"), 2, (path, attrs) -> {
+                return img.getModules().contains(path.getFileName().toString());
+            }).forEach((p) -> {
+                try {
+                    String pattern = "JLINK_VM_OPTIONS=";
+                    byte[] content = Files.readAllBytes(p);
+                    String str = new String(content, StandardCharsets.UTF_8);
+                    int index = str.indexOf(pattern);
+                    StringBuilder builder = new StringBuilder();
+                    if (index != -1) {
+                        builder.append(str.substring(0, index)).
+                                append(pattern);
+                        for (String s : args) {
+                            builder.append(s).append(" ");
+                        }
+                        String remain = str.substring(index + pattern.length());
+                        builder.append(remain);
+                        str = builder.toString();
+                        try (BufferedWriter writer = Files.newBufferedWriter(p,
+                                StandardCharsets.ISO_8859_1,
+                                StandardOpenOption.WRITE)) {
+                            writer.write(str);
+                        }
+                    }
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            });
+        }
+    }
+
+    private static String getJavaProcessName() {
+        return isWindows() ? "java.exe" : "java";
+    }
+
+    public static ExecutableImage getExecutableImage(Path root) {
+        if (Files.exists(root.resolve("bin").resolve(getJavaProcessName()))) {
+            return new DefaultImageBuilder.DefaultExecutableImage(root,
+                    retrieveModules(root));
+        }
+        return null;
+    }
+
+    private static Set<String> retrieveModules(Path root) {
+        Path releaseFile = root.resolve("release");
+        Set<String> modules = new HashSet<>();
+        if (Files.exists(releaseFile)) {
+            Properties release = new Properties();
+            try (FileInputStream fi = new FileInputStream(releaseFile.toFile())) {
+                release.load(fi);
+            } catch (IOException ex) {
+                System.err.println("Can't read release file " + ex);
+            }
+            String mods = release.getProperty("MODULES");
+            if (mods != null) {
+                String[] arr = mods.split(",");
+                for (String m : arr) {
+                    modules.add(m.trim());
+                }
+
+            }
+        }
+        return modules;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
new file mode 100644
index 0000000..5942bd6
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.builder;
+
+import java.io.DataOutputStream;
+import java.util.Properties;
+
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+
+/**
+ * Implement this interface to develop your own image layout. First the jimage
+ * is written onto the output stream returned by getOutputStream then storeFiles
+ * is called.
+ */
+public interface ImageBuilder {
+
+    /**
+     * Store the external files.
+     *
+     * @param content Pool of module content.
+     * @param bom The options used to build the image file.
+     * @param release the release properties
+     * @throws PluginException
+     */
+    public default void storeFiles(Pool content, String bom, Properties release) {
+        storeFiles(content, bom);
+    }
+
+    /**
+     * Store the external files.
+     *
+     * @param content Pool of module content.
+     * @param bom The options used to build the image file.
+     * @throws PluginException
+     */
+    public default void storeFiles(Pool content, String bom) {
+        throw new UnsupportedOperationException("storeFiles");
+    }
+
+    /**
+     * The OutputStream to store the jimage file.
+     *
+     * @return The output stream
+     * @throws PluginException
+     */
+    public DataOutputStream getJImageOutputStream();
+
+    /**
+     * Gets the executable image that is generated.
+     *
+     * @return The executable image.
+     * @throws PluginException
+     */
+    public ExecutableImage getExecutableImage();
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java
new file mode 100644
index 0000000..82571d3
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Archive.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * An Archive of all content, classes, resources, configuration files, and
+ * other, for a module.
+ */
+public interface Archive {
+
+    /**
+     * Entry is contained in an Archive
+     */
+    public abstract class Entry {
+
+        public static enum EntryType {
+
+            MODULE_NAME,
+            CLASS_OR_RESOURCE,
+            NATIVE_LIB,
+            NATIVE_CMD,
+            CONFIG,
+            SERVICE;
+        }
+
+        private final String name;
+        private final EntryType type;
+        private final Archive archive;
+        private final String path;
+
+        public Entry(Archive archive, String path, String name, EntryType type) {
+            Objects.requireNonNull(archive);
+            Objects.requireNonNull(path);
+            Objects.requireNonNull(name);
+            Objects.requireNonNull(type);
+            this.archive = archive;
+            this.path = path;
+            this.name = name;
+            this.type = type;
+        }
+
+        public Archive archive() {
+            return archive;
+        }
+
+        public String path() {
+            return path;
+        }
+
+        public EntryType type() {
+            return type;
+        }
+
+        /**
+         * Returns the name of this entry.
+         */
+        public String name() {
+            return name;
+        }
+
+        @Override
+        public String toString() {
+            return "type " + type.name() + " path " + path;
+        }
+
+        /**
+         * Returns the number of uncompressed bytes for this entry.
+         */
+        public abstract long size();
+
+        public abstract InputStream stream() throws IOException;
+    }
+
+    /**
+     * The module name.
+     */
+    String moduleName();
+
+    /**
+     * Returns the path to this module's content
+     */
+    Path getPath();
+
+    /**
+     * Stream of Entry.
+     * The stream of entries needs to be closed after use
+     * since it might cover lazy I/O based resources.
+     * So callers need to use a try-with-resources block.
+     */
+    Stream<Entry> entries();
+
+    /**
+     * Open the archive
+     */
+    void open() throws IOException;
+
+    /**
+     * Close the archive
+     */
+    void close() throws IOException;
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java
new file mode 100644
index 0000000..559cf69
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/BasicImageWriter.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+*/
+
+package jdk.tools.jlink.internal;
+
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.internal.jimage.ImageHeader;
+import jdk.internal.jimage.ImageStream;
+import jdk.internal.jimage.ImageStringsReader;
+
+public final class BasicImageWriter {
+    public static final String MODULES_IMAGE_NAME = "modules";
+
+    private final static int RETRY_LIMIT = 1000;
+
+    private ByteOrder byteOrder;
+    private ImageStringsWriter strings;
+    private int length;
+    private int[] redirect;
+    private ImageLocationWriter[] locations;
+    private List<ImageLocationWriter> input;
+    private ImageStream headerStream;
+    private ImageStream redirectStream;
+    private ImageStream locationOffsetStream;
+    private ImageStream locationStream;
+    private ImageStream allIndexStream;
+
+    public BasicImageWriter() {
+        this(ByteOrder.nativeOrder());
+    }
+
+    public BasicImageWriter(ByteOrder byteOrder) {
+        this.byteOrder = byteOrder;
+        this.input = new ArrayList<>();
+        this.strings = new ImageStringsWriter();
+        this.headerStream = new ImageStream(byteOrder);
+        this.redirectStream = new ImageStream(byteOrder);
+        this.locationOffsetStream = new ImageStream(byteOrder);
+        this.locationStream = new ImageStream(byteOrder);
+        this.allIndexStream = new ImageStream(byteOrder);
+    }
+
+    public ByteOrder getByteOrder() {
+        return byteOrder;
+    }
+
+    public int addString(String string) {
+        return strings.add(string);
+    }
+
+    public String getString(int offset) {
+        return strings.get(offset);
+    }
+
+    public void addLocation(String fullname, long contentOffset,
+            long compressedSize, long uncompressedSize) {
+        ImageLocationWriter location =
+                ImageLocationWriter.newLocation(fullname, strings,
+                        contentOffset, compressedSize, uncompressedSize);
+        input.add(location);
+        length++;
+    }
+
+    ImageLocationWriter[] getLocations() {
+        return locations;
+    }
+
+    int getLocationsCount() {
+        return input.size();
+    }
+
+    private void generatePerfectHash() {
+        PerfectHashBuilder<ImageLocationWriter> builder =
+            new PerfectHashBuilder<>(
+                        PerfectHashBuilder.Entry.class, // PerfectHashBuilder.Entry<ImageLocationWriter>().getClass()
+                        PerfectHashBuilder.Bucket.class); // PerfectHashBuilder.Bucket<ImageLocationWriter>().getClass()
+
+        input.forEach((location) -> {
+            builder.put(location.getFullName(), location);
+        });
+
+        builder.generate();
+
+        length = builder.getCount();
+        redirect = builder.getRedirect();
+        PerfectHashBuilder.Entry<ImageLocationWriter>[] order = builder.getOrder();
+        locations = new ImageLocationWriter[length];
+
+        for (int i = 0; i < length; i++) {
+            locations[i] = order[i].getValue();
+        }
+    }
+
+    private void prepareStringBytes() {
+        strings.getStream().align(2);
+    }
+
+    private void prepareRedirectBytes() {
+        for (int i = 0; i < length; i++) {
+            redirectStream.putInt(redirect[i]);
+        }
+    }
+
+    private void prepareLocationBytes() {
+        // Reserve location offset zero for empty locations
+        locationStream.put(ImageLocationWriter.ATTRIBUTE_END << 3);
+
+        for (int i = 0; i < length; i++) {
+            ImageLocationWriter location = locations[i];
+
+            if (location != null) {
+                location.writeTo(locationStream);
+            }
+        }
+
+        locationStream.align(2);
+    }
+
+    private void prepareOffsetBytes() {
+        for (int i = 0; i < length; i++) {
+            ImageLocationWriter location = locations[i];
+            int offset = location != null ? location.getLocationOffset() : 0;
+            locationOffsetStream.putInt(offset);
+        }
+    }
+
+    private void prepareHeaderBytes() {
+        ImageHeader header = new ImageHeader(input.size(), length,
+                locationStream.getSize(), strings.getSize());
+        header.writeTo(headerStream);
+    }
+
+    private void prepareTableBytes() {
+        allIndexStream.put(headerStream);
+        allIndexStream.put(redirectStream);
+        allIndexStream.put(locationOffsetStream);
+        allIndexStream.put(locationStream);
+        allIndexStream.put(strings.getStream());
+    }
+
+    public byte[] getBytes() {
+        if (allIndexStream.getSize() == 0) {
+            generatePerfectHash();
+            prepareStringBytes();
+            prepareRedirectBytes();
+            prepareLocationBytes();
+            prepareOffsetBytes();
+            prepareHeaderBytes();
+            prepareTableBytes();
+        }
+
+        return allIndexStream.toArray();
+    }
+
+    ImageLocationWriter find(String key) {
+        int index = redirect[ImageStringsReader.hashCode(key) % length];
+
+        if (index < 0) {
+            index = -index - 1;
+        } else {
+            index = ImageStringsReader.hashCode(key, index) % length;
+        }
+
+        return locations[index];
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/DirArchive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/DirArchive.java
new file mode 100644
index 0000000..48fd1d5
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/DirArchive.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+/**
+ * An Archive backed by a directory.
+ */
+public class DirArchive implements Archive {
+
+    /**
+     * A File located in a Directory.
+     */
+    private class FileEntry extends Archive.Entry {
+
+        private final long size;
+        private final Path path;
+
+        FileEntry(Path path, String name) {
+            super(DirArchive.this, getPathName(path), name,
+                    Archive.Entry.EntryType.CLASS_OR_RESOURCE);
+            this.path = path;
+            try {
+                size = Files.size(path);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        /**
+         * Returns the number of bytes of this file.
+         */
+        @Override
+        public long size() {
+            return size;
+        }
+
+        @Override
+        public InputStream stream() throws IOException {
+            InputStream stream = Files.newInputStream(path);
+            open.add(stream);
+            return stream;
+        }
+    }
+
+    private static final String MODULE_INFO = "module-info.class";
+
+    private final Path dirPath;
+    private final String moduleName;
+    private final List<InputStream> open = new ArrayList<>();
+    private final int chop;
+    private final Consumer<String> log;
+    private static final Consumer<String> noopConsumer = (String t) -> {
+    };
+
+    public DirArchive(Path dirPath) {
+        this(dirPath, noopConsumer);
+    }
+
+    public DirArchive(Path dirPath, Consumer<String> log) {
+        Objects.requireNonNull(dirPath);
+        if (!Files.isDirectory(dirPath)) {
+            throw new IllegalArgumentException("Not a directory");
+        }
+        chop = dirPath.toString().length() + 1;
+        this.moduleName = Objects.requireNonNull(dirPath.getFileName()).toString();
+        this.dirPath = dirPath;
+        this.log = log;
+    }
+
+    @Override
+    public String moduleName() {
+        return moduleName;
+    }
+
+    @Override
+    public Path getPath() {
+        return dirPath;
+    }
+
+    @Override
+    public Stream<Entry> entries() {
+        Stream<Entry> ret = null;
+        try {
+            ret = Files.walk(dirPath).map(this::toEntry).filter(n -> n != null);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+        return ret;
+    }
+
+    private Archive.Entry toEntry(Path p) {
+        if (Files.isDirectory(p)) {
+            return null;
+        }
+        String name = getPathName(p).substring(chop);
+        if (name.startsWith("_")) {
+            return null;
+        }
+        log.accept(moduleName + "/" + name);
+        if (name.equals(MODULE_INFO)) {
+            name = moduleName + "/" + MODULE_INFO;
+        }
+        return new FileEntry(p, name);
+    }
+
+    @Override
+    public void close() throws IOException {
+        IOException e = null;
+        for (InputStream stream : open) {
+            try {
+                stream.close();
+            } catch (IOException ex) {
+                if (e == null) {
+                    e = ex;
+                } else {
+                    e.addSuppressed(ex);
+                }
+            }
+        }
+        if (e != null) {
+            throw e;
+        }
+    }
+
+    @Override
+    public void open() throws IOException {
+        // NOOP
+    }
+
+    private static String getPathName(Path path) {
+        return path.toString().replace(File.separatorChar, '/');
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
new file mode 100644
index 0000000..5e8d85b
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteOrder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+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 jdk.tools.jlink.internal.Archive.Entry;
+import jdk.tools.jlink.internal.Archive.Entry.EntryType;
+import jdk.tools.jlink.internal.PoolImpl.CompressedModuleData;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+
+/**
+ * An image (native endian.)
+ * <pre>{@code
+ * {
+ *   u4 magic;
+ *   u2 major_version;
+ *   u2 minor_version;
+ *   u4 resource_count;
+ *   u4 table_length;
+ *   u4 location_attributes_size;
+ *   u4 strings_size;
+ *   u4 redirect[table_length];
+ *   u4 offsets[table_length];
+ *   u1 location_attributes[location_attributes_size];
+ *   u1 strings[strings_size];
+ *   u1 content[if !EOF];
+ * }
+ * }</pre>
+ */
+public final class ImageFileCreator {
+    private final Map<String, List<Entry>> entriesForModule = new HashMap<>();
+    private final ImagePluginStack plugins;
+    private ImageFileCreator(ImagePluginStack plugins) {
+        this.plugins = plugins;
+    }
+
+    public static ExecutableImage create(Set<Archive> archives,
+            ImagePluginStack plugins)
+            throws IOException {
+        return ImageFileCreator.create(archives, ByteOrder.nativeOrder(),
+                plugins);
+    }
+
+    public static ExecutableImage create(Set<Archive> archives,
+            ByteOrder byteOrder)
+            throws IOException {
+        return ImageFileCreator.create(archives, byteOrder,
+                new ImagePluginStack(null));
+    }
+
+    public static ExecutableImage create(Set<Archive> archives,
+            ByteOrder byteOrder,
+            ImagePluginStack plugins)
+            throws IOException
+    {
+        ImageFileCreator image = new ImageFileCreator(plugins);
+        try {
+            image.readAllEntries(archives);
+            // write to modular image
+            image.writeImage(archives, byteOrder);
+        } finally {
+            //Close all archives
+            for (Archive a : archives) {
+                a.close();
+            }
+        }
+
+        return plugins.getExecutableImage();
+    }
+
+    private void readAllEntries(Set<Archive> archives) {
+        archives.stream().forEach((archive) -> {
+            Map<Boolean, List<Entry>> es;
+            try (Stream<Entry> entries = archive.entries()) {
+                es = entries.collect(Collectors.partitioningBy(n -> n.type()
+                        == EntryType.CLASS_OR_RESOURCE));
+            }
+            String mn = archive.moduleName();
+            List<Entry> all = new ArrayList<>();
+            all.addAll(es.get(false));
+            all.addAll(es.get(true));
+            entriesForModule.put(mn, all);
+        });
+    }
+
+    public static boolean isClassPackage(String path) {
+        return path.endsWith(".class") && !path.endsWith("module-info.class");
+    }
+
+    public static void recreateJimage(Path jimageFile,
+            Set<Archive> archives,
+            ImagePluginStack pluginSupport)
+            throws IOException {
+        try {
+            Map<String, List<Entry>> entriesForModule
+                    = archives.stream().collect(Collectors.toMap(
+                                    Archive::moduleName,
+                                    a -> {
+                                        try (Stream<Entry> entries = a.entries()) {
+                                            return entries.collect(Collectors.toList());
+                                        }
+                                    }));
+            ByteOrder order = ByteOrder.nativeOrder();
+            BasicImageWriter writer = new BasicImageWriter(order);
+            PoolImpl pool = createPools(archives, entriesForModule, order, writer);
+            try (OutputStream fos = Files.newOutputStream(jimageFile);
+                    BufferedOutputStream bos = new BufferedOutputStream(fos);
+                    DataOutputStream out = new DataOutputStream(bos)) {
+                generateJImage(pool, writer, pluginSupport, out);
+            }
+        } finally {
+            //Close all archives
+            for (Archive a : archives) {
+                a.close();
+            }
+        }
+    }
+
+    private void writeImage(Set<Archive> archives,
+            ByteOrder byteOrder)
+            throws IOException {
+        BasicImageWriter writer = new BasicImageWriter(byteOrder);
+        PoolImpl allContent = createPools(archives,
+                entriesForModule, byteOrder, writer);
+        PoolImpl result = generateJImage(allContent,
+             writer, plugins, plugins.getJImageFileOutputStream());
+
+        //Handle files.
+        try {
+            plugins.storeFiles(allContent, result, writer);
+        } catch (Exception ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    private static PoolImpl generateJImage(PoolImpl allContent,
+            BasicImageWriter writer,
+            ImagePluginStack pluginSupport,
+            DataOutputStream out
+    ) throws IOException {
+        PoolImpl resultResources;
+        try {
+            resultResources = pluginSupport.visitResources(allContent);
+        } catch (Exception ex) {
+            throw new IOException(ex);
+        }
+        Set<String> duplicates = new HashSet<>();
+        long offset = 0;
+
+        List<ModuleData> content = new ArrayList<>();
+        List<String> paths = new ArrayList<>();
+                 // the order of traversing the resources and the order of
+        // the module content being written must be the same
+        for (ModuleData res : resultResources.getContent()) {
+            if (res.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+                String path = res.getPath();
+                content.add(res);
+                long uncompressedSize = res.getLength();
+                long compressedSize = 0;
+                if (res instanceof CompressedModuleData) {
+                    CompressedModuleData comp
+                            = (CompressedModuleData) res;
+                    compressedSize = res.getLength();
+                    uncompressedSize = comp.getUncompressedSize();
+                }
+                long onFileSize = res.getLength();
+
+                if (duplicates.contains(path)) {
+                    System.err.format("duplicate resource \"%s\", skipping%n",
+                            path);
+                    // TODO Need to hang bytes on resource and write
+                    // from resource not zip.
+                    // Skipping resource throws off writing from zip.
+                    offset += onFileSize;
+                    continue;
+                }
+                duplicates.add(path);
+                writer.addLocation(path, offset, compressedSize, uncompressedSize);
+                paths.add(path);
+                offset += onFileSize;
+            }
+        }
+
+        ImageResourcesTree tree = new ImageResourcesTree(offset, writer, paths);
+
+        // write header and indices
+        byte[] bytes = writer.getBytes();
+        out.write(bytes, 0, bytes.length);
+
+        // write module content
+        for (ModuleData res : content) {
+            byte[] buf = res.getBytes();
+            out.write(buf, 0, buf.length);
+        }
+
+        tree.addContent(out);
+
+        out.close();
+
+        return resultResources;
+    }
+
+    private static Pool.ModuleDataType mapImageFileType(EntryType type) {
+        switch(type) {
+            case CONFIG: {
+                return Pool.ModuleDataType.CONFIG;
+            }
+            case NATIVE_CMD: {
+                return Pool.ModuleDataType.NATIVE_CMD;
+            }
+            case NATIVE_LIB: {
+                return Pool.ModuleDataType.NATIVE_LIB;
+            }
+        }
+        return null;
+    }
+
+    private static PoolImpl createPools(Set<Archive> archives,
+            Map<String, List<Entry>> entriesForModule,
+            ByteOrder byteOrder,
+            BasicImageWriter writer) throws IOException {
+        PoolImpl resources = new PoolImpl(byteOrder, new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return writer.addString(str);
+            }
+
+            @Override
+            public String getString(int id) {
+                return writer.getString(id);
+            }
+        });
+        for (Archive archive : archives) {
+            String mn = archive.moduleName();
+            for (Entry entry : entriesForModule.get(mn)) {
+
+                if (entry.type() == EntryType.CLASS_OR_RESOURCE) {
+                    // Removal of "classes/" radical.
+                    String path = entry.name();
+                    try (InputStream stream = entry.stream()) {
+                        byte[] bytes = readAllBytes(stream);
+                        if (path.endsWith("module-info.class")) {
+                            path = "/" + path;
+                        } else {
+                            path = "/" + mn + "/" + path;
+                        }
+                        try {
+                            resources.add(Pool.newResource(path, bytes));
+                        } catch (Exception ex) {
+                            throw new IOException(ex);
+                        }
+                    }
+                } else {
+                    try {
+                        // Entry.path() contains the kind of file native, conf, bin, ...
+                        // Keep it to avoid naming conflict (eg: native/jvm.cfg and config/jvm.cfg
+                        resources.add(Pool.newImageFile(mn,
+                                "/" + mn + "/" + entry.path(), mapImageFileType(entry.type()),
+                                entry.stream(), entry.size()));
+                    } catch (Exception ex) {
+                        throw new IOException(ex);
+                    }
+                }
+            }
+        }
+        return resources;
+    }
+
+    private static final int BUF_SIZE = 8192;
+
+    private static byte[] readAllBytes(InputStream is) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buf = new byte[BUF_SIZE];
+        while (true) {
+            int n = is.read(buf);
+            if (n < 0) {
+                break;
+            }
+            baos.write(buf, 0, n);
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * Helper method that splits a Resource path onto 3 items: module, parent
+     * and resource name.
+     *
+     * @param path
+     * @return An array containing module, parent and name.
+     */
+    public static String[] splitPath(String path) {
+        Objects.requireNonNull(path);
+        String noRoot = path.substring(1);
+        int pkgStart = noRoot.indexOf("/");
+        String module = noRoot.substring(0, pkgStart);
+        List<String> result = new ArrayList<>();
+        result.add(module);
+        String pkg = noRoot.substring(pkgStart + 1);
+        String resName;
+        int pkgEnd = pkg.lastIndexOf("/");
+        if (pkgEnd == -1) { // No package.
+            resName = pkg;
+        } else {
+            resName = pkg.substring(pkgEnd + 1);
+        }
+
+        pkg = toPackage(pkg, false);
+        result.add(pkg);
+        result.add(resName);
+
+        String[] array = new String[result.size()];
+        return result.toArray(array);
+    }
+
+    private static String toPackage(String name, boolean log) {
+        int index = name.lastIndexOf('/');
+        if (index > 0) {
+            return name.substring(0, index).replace('/', '.');
+        } else {
+            // ## unnamed package
+            if (log) {
+                System.err.format("Warning: %s in unnamed package%n", name);
+            }
+            return "";
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java
new file mode 100644
index 0000000..e66ba64
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import jdk.internal.jimage.ImageLocation;
+import jdk.internal.jimage.ImageStream;
+import jdk.internal.jimage.ImageStringsReader;
+
+public final class ImageLocationWriter extends ImageLocation {
+    private int locationOffset;
+
+    private ImageLocationWriter(ImageStringsWriter strings) {
+        super(new long[ATTRIBUTE_COUNT], strings);
+    }
+
+    void writeTo(ImageStream stream) {
+        byte[] bytes = ImageLocation.compress(attributes);
+        locationOffset = stream.getPosition();
+        stream.put(bytes, 0, bytes.length);
+    }
+
+    private ImageLocationWriter addAttribute(int kind, long value) {
+        assert ATTRIBUTE_END < kind &&
+               kind < ATTRIBUTE_COUNT : "Invalid attribute kind";
+        attributes[kind] = value;
+        return this;
+    }
+
+    private ImageLocationWriter addAttribute(int kind, String value) {
+        return addAttribute(kind, strings.add(value));
+    }
+
+    static ImageLocationWriter newLocation(String fullName,
+            ImageStringsWriter strings,
+            long contentOffset, long compressedSize, long uncompressedSize) {
+        String moduleName = "";
+        String parentName = "";
+        String baseName;
+        String extensionName = "";
+
+        int offset = fullName.indexOf('/', 1);
+        if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) {
+            moduleName = fullName.substring(1, offset);
+            fullName = fullName.substring(offset + 1);
+        }
+
+        offset = fullName.lastIndexOf('/');
+        if (1 < offset) {
+            parentName = fullName.substring(0, offset);
+            fullName = fullName.substring(offset + 1);
+        }
+
+        offset = fullName.lastIndexOf('.');
+        if (offset != -1) {
+            baseName = fullName.substring(0, offset);
+            extensionName = fullName.substring(offset + 1);
+        } else {
+            baseName = fullName;
+        }
+
+        return new ImageLocationWriter(strings)
+               .addAttribute(ATTRIBUTE_MODULE, moduleName)
+               .addAttribute(ATTRIBUTE_PARENT, parentName)
+               .addAttribute(ATTRIBUTE_BASE, baseName)
+               .addAttribute(ATTRIBUTE_EXTENSION, extensionName)
+               .addAttribute(ATTRIBUTE_OFFSET, contentOffset)
+               .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize)
+               .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize);
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode(ImageStringsReader.HASH_MULTIPLIER);
+    }
+
+    int hashCode(int seed) {
+        int hash = seed;
+
+        if (getModuleOffset() != 0) {
+            hash = ImageStringsReader.hashCode("/", hash);
+            hash = ImageStringsReader.hashCode(getModule(), hash);
+            hash = ImageStringsReader.hashCode("/", hash);
+        }
+
+        if (getParentOffset() != 0) {
+            hash = ImageStringsReader.hashCode(getParent(), hash);
+            hash = ImageStringsReader.hashCode("/", hash);
+        }
+
+        hash = ImageStringsReader.hashCode(getBase(), hash);
+
+        if (getExtensionOffset() != 0) {
+            hash = ImageStringsReader.hashCode(".", hash);
+            hash = ImageStringsReader.hashCode(getExtension(), hash);
+        }
+
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (!(obj instanceof ImageLocationWriter)) {
+            return false;
+        }
+
+        ImageLocationWriter other = (ImageLocationWriter) obj;
+
+        return getModuleOffset() == other.getModuleOffset() &&
+               getParentOffset() == other.getParentOffset() &&
+               getBaseOffset() == other.getBaseOffset() &&
+               getExtensionOffset() == other.getExtensionOffset();
+    }
+
+    int getLocationOffset() {
+        return locationOffset;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
new file mode 100644
index 0000000..ac96a79
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.DataOutputStream;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Properties;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginContext;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Plugin.CATEGORY;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ * Plugins configuration.
+ */
+public final class ImagePluginConfiguration {
+
+    private static final List<Plugin.CATEGORY> CATEGORIES_ORDER = new ArrayList<>();
+
+    static {
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.FILTER);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.TRANSFORMER);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.MODULEINFO_TRANSFORMER);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.SORTER);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.COMPRESSOR);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.VERIFIER);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.PROCESSOR);
+        CATEGORIES_ORDER.add(Plugin.CATEGORY.PACKAGER);
+    }
+
+    private ImagePluginConfiguration() {
+    }
+
+    public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration plugins)
+            throws Exception {
+        return parseConfiguration(plugins, null);
+    }
+
+    /*
+     * Create a stack of plugins from a a configuration.
+     *
+     */
+    public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration pluginsConfiguration,
+            String bom)
+            throws Exception {
+        if (pluginsConfiguration == null) {
+            return new ImagePluginStack(bom);
+        }
+        Map<Plugin.CATEGORY, List<Plugin>> plugins = new LinkedHashMap<>();
+        for (Plugin.CATEGORY cat : CATEGORIES_ORDER) {
+            plugins.put(cat, new ArrayList<>());
+        }
+
+        List<String> seen = new ArrayList<>();
+        // split into categories and check for plugin with same name.
+        for (Plugin plug : pluginsConfiguration.getPlugins()) {
+            if (seen.contains(plug.getName())) {
+                throw new Exception("Plugin " + plug.getName()
+                        + " added more than once to stack ");
+            }
+            seen.add(plug.getName());
+            CATEGORY category = Utils.getCategory(plug);
+            if (category == null) {
+                throw new PluginException("Invalid category for "
+                        + plug.getName());
+            }
+            List<Plugin> lst = plugins.get(category);
+            lst.add(plug);
+        }
+
+        List<TransformerPlugin> transformerPlugins = new ArrayList<>();
+        List<PostProcessorPlugin> postProcessingPlugins = new ArrayList<>();
+        for (Entry<Plugin.CATEGORY, List<Plugin>> entry : plugins.entrySet()) {
+            // Sort according to plugin constraints
+            List<Plugin> orderedPlugins = PluginOrderingGraph.sort(entry.getValue());
+            CATEGORY category = entry.getKey();
+            for (Plugin p : orderedPlugins) {
+                if (Utils.isPostProcessor(category)) {
+                    @SuppressWarnings("unchecked")
+                    PostProcessorPlugin pp = (PostProcessorPlugin) p;
+                    postProcessingPlugins.add(pp);
+                } else {
+                    @SuppressWarnings("unchecked")
+                    TransformerPlugin trans = (TransformerPlugin) p;
+                    transformerPlugins.add(trans);
+                }
+            }
+        }
+        Plugin lastSorter = null;
+        for (Plugin plugin : transformerPlugins) {
+            if (plugin.getName().equals(pluginsConfiguration.getLastSorterPluginName())) {
+                lastSorter = plugin;
+                break;
+            }
+        }
+        if (pluginsConfiguration.getLastSorterPluginName() != null && lastSorter == null) {
+            throw new IOException("Unknown last plugin "
+                    + pluginsConfiguration.getLastSorterPluginName());
+        }
+        ImageBuilder builder = pluginsConfiguration.getImageBuilder();
+        if (builder == null) {
+            // This should be the case for jimage only creation or post-install.
+            builder = new ImageBuilder() {
+
+                @Override
+                public DataOutputStream getJImageOutputStream() {
+                    throw new PluginException("No directory setup to store files");
+                }
+
+                @Override
+                public ExecutableImage getExecutableImage() {
+                    throw new PluginException("No directory setup to store files");
+                }
+
+                @Override
+                public void storeFiles(Pool files, String bom) {
+                    throw new PluginException("No directory setup to store files");
+                }
+            };
+        }
+
+        PluginContext ctxt = pluginsConfiguration.getPluginContext();
+        return new ImagePluginStack(builder, transformerPlugins,
+                lastSorter, postProcessingPlugins, ctxt, bom);
+    }
+}
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
new file mode 100644
index 0000000..646cc5c
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.jimage.decompressor.Decompressor;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginContext;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+
+/**
+ * Plugins Stack. Plugins entry point to apply transformations onto resources
+ * and files.
+ */
+public final class ImagePluginStack {
+
+    public interface ImageProvider {
+
+        ExecutableImage retrieve(ImagePluginStack stack) throws IOException;
+    }
+
+    public static final class OrderedResourcePool extends PoolImpl {
+
+        private final List<ModuleData> orderedList = new ArrayList<>();
+
+        public OrderedResourcePool(ByteOrder order, StringTable table) {
+            super(order, table);
+        }
+
+        /**
+         * Add a resource.
+         *
+         * @param resource The Resource to add.
+         */
+        @Override
+        public void add(ModuleData resource) {
+            super.add(resource);
+            orderedList.add(resource);
+        }
+
+        List<ModuleData> getOrderedList() {
+            return Collections.unmodifiableList(orderedList);
+        }
+    }
+
+    private final static class CheckOrderResourcePool extends PoolImpl {
+
+        private final List<ModuleData> orderedList;
+        private int currentIndex;
+
+        public CheckOrderResourcePool(ByteOrder order, List<ModuleData> orderedList, StringTable table) {
+            super(order, table);
+            this.orderedList = orderedList;
+        }
+
+        /**
+         * Add a resource.
+         *
+         * @param resource The Resource to add.
+         */
+        @Override
+        public void add(ModuleData resource) {
+            ModuleData ordered = orderedList.get(currentIndex);
+            if (!resource.equals(ordered)) {
+                throw new PluginException("Resource " + resource.getPath() + " not in the right order");
+            }
+            super.add(resource);
+            currentIndex += 1;
+        }
+    }
+
+    private static final class PreVisitStrings implements StringTable {
+
+        private int currentid = 0;
+        private final Map<String, Integer> stringsUsage = new HashMap<>();
+
+        private final Map<String, Integer> stringsMap = new HashMap<>();
+        private final Map<Integer, String> reverseMap = new HashMap<>();
+
+        @Override
+        public int addString(String str) {
+            Objects.requireNonNull(str);
+            Integer count = stringsUsage.get(str);
+            if (count == null) {
+                count = 0;
+            }
+            count += 1;
+            stringsUsage.put(str, count);
+            Integer id = stringsMap.get(str);
+            if (id == null) {
+                id = currentid;
+                stringsMap.put(str, id);
+                currentid += 1;
+                reverseMap.put(id, str);
+            }
+
+            return id;
+        }
+
+        private List<String> getSortedStrings() {
+            Stream<java.util.Map.Entry<String, Integer>> stream
+                    = stringsUsage.entrySet().stream();
+            // Remove strings that have a single occurence
+            List<String> result = stream.sorted(Comparator.comparing(e -> e.getValue(),
+                    Comparator.reverseOrder())).filter((e) -> {
+                        return e.getValue() > 1;
+                    }).map(java.util.Map.Entry::getKey).
+                    collect(Collectors.toList());
+            return result;
+        }
+
+        @Override
+        public String getString(int id) {
+            return reverseMap.get(id);
+        }
+    }
+
+    private final Plugin lastSorter;
+    private final List<TransformerPlugin> contentPlugins = new ArrayList<>();
+    private final List<PostProcessorPlugin> postProcessingPlugins = new ArrayList<>();
+    private final List<ResourcePrevisitor> resourcePrevisitors = new ArrayList<>();
+
+    private final ImageBuilder imageBuilder;
+    private final Properties release;
+    private final String bom;
+
+    public ImagePluginStack(String bom) {
+        this(null, Collections.emptyList(), null,
+                Collections.emptyList(), null, bom);
+    }
+
+    public ImagePluginStack(ImageBuilder imageBuilder,
+            List<TransformerPlugin> contentPlugins,
+            Plugin lastSorter,
+            List<PostProcessorPlugin> postprocessingPlugins,
+            String bom) {
+        this(imageBuilder, contentPlugins, lastSorter,
+            postprocessingPlugins, null, bom);
+    }
+
+    public ImagePluginStack(ImageBuilder imageBuilder,
+            List<TransformerPlugin> contentPlugins,
+            Plugin lastSorter,
+            List<PostProcessorPlugin> postprocessingPlugins,
+            PluginContext ctxt,
+            String bom) {
+        Objects.requireNonNull(contentPlugins);
+        this.lastSorter = lastSorter;
+        for (TransformerPlugin p : contentPlugins) {
+            Objects.requireNonNull(p);
+            if (p instanceof ResourcePrevisitor) {
+                resourcePrevisitors.add((ResourcePrevisitor) p);
+            }
+            this.contentPlugins.add(p);
+        }
+        for (PostProcessorPlugin p : postprocessingPlugins) {
+            Objects.requireNonNull(p);
+            this.postProcessingPlugins.add(p);
+        }
+        this.imageBuilder = imageBuilder;
+        this.release = ctxt != null? ctxt.getReleaseProperties() : new Properties();
+        this.bom = bom;
+    }
+
+    public void operate(ImageProvider provider) throws Exception {
+        ExecutableImage img = provider.retrieve(this);
+        List<String> arguments = new ArrayList<>();
+        for (PostProcessorPlugin plugin : postProcessingPlugins) {
+            List<String> lst = plugin.process(img);
+            if (lst != null) {
+                arguments.addAll(lst);
+            }
+        }
+        img.storeLaunchArgs(arguments);
+    }
+
+    public DataOutputStream getJImageFileOutputStream() throws IOException {
+        return imageBuilder.getJImageOutputStream();
+    }
+
+    public ImageBuilder getImageBuilder() {
+        return imageBuilder;
+    }
+
+    /**
+     * Resource Plugins stack entry point. All resources are going through all
+     * the plugins.
+     *
+     * @param resources The set of resources to visit
+     * @return The result of the visit.
+     * @throws IOException
+     */
+    public PoolImpl visitResources(PoolImpl resources)
+            throws Exception {
+        Objects.requireNonNull(resources);
+        resources.setReadOnly();
+        if (resources.isEmpty()) {
+            return new PoolImpl(resources.getByteOrder(),
+                    resources.getStringTable());
+        }
+        PreVisitStrings previsit = new PreVisitStrings();
+        for (ResourcePrevisitor p : resourcePrevisitors) {
+            p.previsit(resources, previsit);
+        }
+
+        // Store the strings resulting from the previsit.
+        List<String> sorted = previsit.getSortedStrings();
+        for (String s : sorted) {
+            resources.getStringTable().addString(s);
+        }
+
+        PoolImpl current = resources;
+        List<Pool.ModuleData> frozenOrder = null;
+        for (TransformerPlugin p : contentPlugins) {
+            current.setReadOnly();
+            PoolImpl output = null;
+            if (p == lastSorter) {
+                if (frozenOrder != null) {
+                    throw new Exception("Order of resources is already frozen. Plugin "
+                            + p.getName() + " is badly located");
+                }
+                // Create a special Resource pool to compute the indexes.
+                output = new OrderedResourcePool(current.getByteOrder(),
+                        resources.getStringTable());
+            } else {// If we have an order, inject it
+                if (frozenOrder != null) {
+                    output = new CheckOrderResourcePool(current.getByteOrder(),
+                            frozenOrder, resources.getStringTable());
+                } else {
+                    output = new PoolImpl(current.getByteOrder(),
+                            resources.getStringTable());
+                }
+            }
+            p.visit(current, output);
+            if (output.isEmpty()) {
+                throw new Exception("Invalid resource pool for plugin " + p);
+            }
+            if (output instanceof OrderedResourcePool) {
+                frozenOrder = ((OrderedResourcePool) output).getOrderedList();
+            }
+
+            current = output;
+        }
+        current.setReadOnly();
+        return current;
+    }
+
+    /**
+     * This pool wrap the original pool and automatically uncompress moduledata
+     * if needed.
+     */
+    private class LastPool extends Pool {
+        private class LastModule implements Module {
+
+            private final Module module;
+
+            LastModule(Module module) {
+                this.module = module;
+            }
+
+            @Override
+            public String getName() {
+                return module.getName();
+            }
+
+            @Override
+            public ModuleData get(String path) {
+                ModuleData d = module.get(path);
+                return getUncompressed(d);
+            }
+
+            @Override
+            public ModuleDescriptor getDescriptor() {
+                return module.getDescriptor();
+            }
+
+            @Override
+            public void add(ModuleData data) {
+                throw new PluginException("pool is readonly");
+            }
+
+            @Override
+            public Set<String> getAllPackages() {
+                return module.getAllPackages();
+            }
+
+            @Override
+            public String toString() {
+                return getName();
+            }
+
+            @Override
+            public Collection<ModuleData> getContent() {
+                List<ModuleData> lst = new ArrayList<>();
+                for(ModuleData md : module.getContent()) {
+                    lst.add(getUncompressed(md));
+                }
+                return lst;
+            }
+        }
+        private final PoolImpl pool;
+        Decompressor decompressor = new Decompressor();
+        Collection<ModuleData> content;
+
+        LastPool(PoolImpl pool) {
+            this.pool = pool;
+        }
+
+        @Override
+        public boolean isReadOnly() {
+            return true;
+        }
+
+        @Override
+        public void add(ModuleData resource) {
+            throw new PluginException("pool is readonly");
+        }
+
+        /**
+         * Retrieves the module of the provided name.
+         *
+         * @param name The module name
+         * @return the module or null if the module doesn't exist.
+         */
+        @Override
+        public Module getModule(String name) {
+            Module module = pool.getModule(name);
+            if (module != null) {
+                module = new LastModule(module);
+            }
+            return module;
+        }
+
+        /**
+         * The collection of modules contained in this pool.
+         *
+         * @return The collection of modules.
+         */
+        @Override
+        public Collection<Module> getModules() {
+            List<Module> modules = new ArrayList<>();
+            for (Module m : pool.getModules()) {
+                modules.add(new LastModule(m));
+            }
+            return modules;
+        }
+
+        /**
+         * Get all resources contained in this pool instance.
+         *
+         * @return The collection of resources;
+         */
+        @Override
+        public Collection<ModuleData> getContent() {
+            if (content == null) {
+                content = new ArrayList<>();
+                for (ModuleData md : pool.getContent()) {
+                    content.add(getUncompressed(md));
+                }
+            }
+            return content;
+        }
+
+        /**
+         * Get the resource for the passed path.
+         *
+         * @param path A resource path
+         * @return A Resource instance or null if the resource is not found
+         */
+        @Override
+        public ModuleData get(String path) {
+            Objects.requireNonNull(path);
+            Pool.ModuleData res = pool.get(path);
+            return getUncompressed(res);
+        }
+
+        @Override
+        public boolean contains(ModuleData res) {
+            return pool.contains(res);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return pool.isEmpty();
+        }
+
+        @Override
+        public void visit(Visitor visitor, Pool output) {
+            pool.visit(visitor, output);
+        }
+
+        @Override
+        public ByteOrder getByteOrder() {
+            return pool.getByteOrder();
+        }
+
+        private ModuleData getUncompressed(ModuleData res) {
+            if (res != null) {
+                if (res instanceof PoolImpl.CompressedModuleData) {
+                    try {
+                        byte[] bytes = decompressor.decompressResource(getByteOrder(),
+                                (int offset) -> pool.getStringTable().getString(offset),
+                                res.getBytes());
+                        res = Pool.newResource(res.getPath(),
+                                new ByteArrayInputStream(bytes),
+                                bytes.length);
+                    } catch (IOException ex) {
+                        throw new PluginException(ex);
+                    }
+                }
+            }
+            return res;
+        }
+    }
+
+    /**
+     * Make the imageBuilder to store files.
+     *
+     * @param original
+     * @param transformed
+     * @param writer
+     * @throws java.lang.Exception
+     */
+    public void storeFiles(PoolImpl original, PoolImpl transformed,
+            BasicImageWriter writer)
+            throws Exception {
+        Objects.requireNonNull(original);
+        try {
+            // fill release information available from transformed "java.base" module!
+            ModuleDescriptor desc = transformed.getModule("java.base").getDescriptor();
+            desc.osName().ifPresent(s -> release.put("OS_NAME", s));
+            desc.osVersion().ifPresent(s -> release.put("OS_VERSION", s));
+            desc.osArch().ifPresent(s -> release.put("OS_ARCH", s));
+        } catch (Exception ignored) {
+        }
+
+        imageBuilder.storeFiles(new LastPool(transformed), bom, release);
+    }
+
+    public ExecutableImage getExecutableImage() throws IOException {
+        return imageBuilder.getExecutableImage();
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java
new file mode 100644
index 0000000..5f64f25
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageResourcesTree.java
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * A class to build a sorted tree of Resource paths as a tree of ImageLocation.
+ *
+ */
+// XXX Public only due to the JImageTask / JImageTask code duplication
+public final class ImageResourcesTree {
+    public static boolean isTreeInfoResource(String path) {
+        return path.startsWith("/packages") || path.startsWith("/modules");
+    }
+
+    /**
+     * Path item tree node.
+     */
+    private static class Node {
+
+        private final String name;
+        private final Map<String, Node> children = new TreeMap<>();
+        private final Node parent;
+        private ImageLocationWriter loc;
+
+        private Node(String name, Node parent) {
+            this.name = name;
+            this.parent = parent;
+
+            if (parent != null) {
+                parent.children.put(name, this);
+            }
+        }
+
+        public String getPath() {
+            if (parent == null) {
+                return "/";
+            }
+            return buildPath(this);
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public Node getChildren(String name) {
+            Node item = children.get(name);
+            return item;
+        }
+
+        private static String buildPath(Node item) {
+            if (item == null) {
+                return null;
+            }
+            String path = buildPath(item.parent);
+            if (path == null) {
+                return item.getName();
+            } else {
+                return path + "/" + item.getName();
+            }
+        }
+    }
+
+    private static final class ResourceNode extends Node {
+
+        public ResourceNode(String name, Node parent) {
+            super(name, parent);
+        }
+    }
+
+    private static class PackageNode extends Node {
+        /**
+         * A reference to a package. Empty packages can be located inside one or
+         * more modules. A package with classes exist in only one module.
+         */
+        final static class PackageReference {
+
+            private final String name;
+            private final boolean isEmpty;
+
+            PackageReference(String name, boolean isEmpty) {
+                Objects.requireNonNull(name);
+                this.name = name;
+                this.isEmpty = isEmpty;
+            }
+
+            @Override
+            public String toString() {
+                return name + "[empty:" + isEmpty + "]";
+            }
+        }
+
+        private final Map<String, PackageReference> references = new TreeMap<>();
+
+        PackageNode(String name, Node parent) {
+            super(name, parent);
+        }
+
+        private void addReference(String name, boolean isEmpty) {
+            PackageReference ref = references.get(name);
+            if (ref == null) {
+                references.put(name, new PackageReference(name, isEmpty));
+            } else {
+                if (ref.isEmpty) { // replace with new one incase non empty.
+                    references.put(name, new PackageReference(name, isEmpty));
+                }
+            }
+        }
+
+        private void validate() {
+            boolean exists = false;
+            for (PackageReference ref : references.values()) {
+                if (!ref.isEmpty) {
+                    if (exists) {
+                        throw new RuntimeException("Multiple modules to contain package "
+                                + getName());
+                    } else {
+                        exists = true;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Tree of nodes.
+     */
+    private static final class Tree {
+
+        private final Map<String, Node> directAccess = new HashMap<>();
+        private final List<String> paths;
+        private final Node root;
+        private Node modules;
+        private Node packages;
+
+        private Tree(List<String> paths) {
+            this.paths = paths;
+            root = new Node("", null);
+            buildTree();
+        }
+
+        private void buildTree() {
+            modules = new Node("modules", root);
+            directAccess.put(modules.getPath(), modules);
+
+            Map<String, Set<String>> moduleToPackage = new TreeMap<>();
+            Map<String, Set<String>> packageToModule = new TreeMap<>();
+
+            for (String p : paths) {
+                if (!p.startsWith("/")) {
+                    continue;
+                }
+                String[] split = p.split("/");
+                // minimum length is 3 items: /<mod>/<pkg>
+                if (split.length < 3) {
+                    System.err.println("Resources tree, invalid data structure, "
+                            + "skipping " + p);
+                    continue;
+                }
+                Node current = modules;
+                String module = null;
+                for (int i = 0; i < split.length; i++) {
+                    // When a non terminal node is marked as being a resource, something is wrong.
+                    // It has been observed some badly created jar file to contain
+                    // invalid directory entry marled as not directory (see 8131762)
+                    if (current instanceof ResourceNode) {
+                        System.err.println("Resources tree, invalid data structure, "
+                                + "skipping " + p);
+                        continue;
+                    }
+                    String s = split[i];
+                    if (!s.isEmpty()) {
+                        // First item, this is the module, simply add a new node to the
+                        // tree.
+                        if (module == null) {
+                            module = s;
+                        }
+                        Node n = current.children.get(s);
+                        if (n == null) {
+                            if (i == split.length - 1) { // Leaf
+                                n = new ResourceNode(s, current);
+                                String pkg = toPackageName(n.parent);
+                                //System.err.println("Adding a resource node. pkg " + pkg + ", name " + s);
+                                if (pkg != null && !pkg.startsWith("META-INF")) {
+                                    Set<String> pkgs = moduleToPackage.get(module);
+                                    if (pkgs == null) {
+                                        pkgs = new TreeSet<>();
+                                        moduleToPackage.put(module, pkgs);
+                                    }
+                                    pkgs.add(pkg);
+                                }
+                            } else { // put only sub trees, no leaf
+                                n = new Node(s, current);
+                                directAccess.put(n.getPath(), n);
+                                String pkg = toPackageName(n);
+                                if (pkg != null && !pkg.startsWith("META-INF")) {
+                                    Set<String> mods = packageToModule.get(pkg);
+                                    if (mods == null) {
+                                        mods = new TreeSet<>();
+                                        packageToModule.put(pkg, mods);
+                                    }
+                                    mods.add(module);
+                                }
+                            }
+                        }
+                        current = n;
+                    }
+                }
+            }
+            packages = new Node("packages", root);
+            directAccess.put(packages.getPath(), packages);
+            // The subset of package nodes that have some content.
+            // These packages exist only in a single module.
+            for (Map.Entry<String, Set<String>> entry : moduleToPackage.entrySet()) {
+                for (String pkg : entry.getValue()) {
+                    PackageNode pkgNode = new PackageNode(pkg, packages);
+                    pkgNode.addReference(entry.getKey(), false);
+                    directAccess.put(pkgNode.getPath(), pkgNode);
+                }
+            }
+
+            // All packages
+            for (Map.Entry<String, Set<String>> entry : packageToModule.entrySet()) {
+                // Do we already have a package node?
+                PackageNode pkgNode = (PackageNode) packages.getChildren(entry.getKey());
+                if (pkgNode == null) {
+                    pkgNode = new PackageNode(entry.getKey(), packages);
+                }
+                for (String module : entry.getValue()) {
+                    pkgNode.addReference(module, true);
+                }
+                directAccess.put(pkgNode.getPath(), pkgNode);
+            }
+            // Validate that the packages are well formed.
+            for (Node n : packages.children.values()) {
+                PackageNode pkg = (PackageNode) n;
+                pkg.validate();
+            }
+
+        }
+
+        public String toResourceName(Node node) {
+            if (!node.children.isEmpty()) {
+                throw new RuntimeException("Node is not a resource");
+            }
+            return removeRadical(node);
+        }
+
+        public String getModule(Node node) {
+            if (node.parent == null || node.getName().equals("modules")
+                    || node.getName().startsWith("packages")) {
+                return null;
+            }
+            String path = removeRadical(node);
+            // "/xxx/...";
+            path = path.substring(1);
+            int i = path.indexOf("/");
+            if (i == -1) {
+                return path;
+            } else {
+                return path.substring(0, i);
+            }
+        }
+
+        public String toPackageName(Node node) {
+            if (node.parent == null) {
+                return null;
+            }
+            String path = removeRadical(node.getPath(), "/modules/");
+            String module = getModule(node);
+            if (path.equals(module)) {
+                return null;
+            }
+            String pkg = removeRadical(path, module + "/");
+            return pkg.replaceAll("/", ".");
+        }
+
+        public String removeRadical(Node node) {
+            return removeRadical(node.getPath(), "/modules");
+        }
+
+        private String removeRadical(String path, String str) {
+            if (!(path.length() < str.length())) {
+                path = path.substring(str.length());
+            }
+            return path;
+        }
+
+        public Node getRoot() {
+            return root;
+        }
+
+        public Map<String, Node> getMap() {
+            return directAccess;
+        }
+    }
+
+    private static final class LocationsAdder {
+
+        private long offset;
+        private final List<byte[]> content = new ArrayList<>();
+        private final BasicImageWriter writer;
+        private final Tree tree;
+
+        LocationsAdder(Tree tree, long offset, BasicImageWriter writer) {
+            this.tree = tree;
+            this.offset = offset;
+            this.writer = writer;
+            addLocations(tree.getRoot());
+        }
+
+        private int addLocations(Node current) {
+            if (current instanceof PackageNode) {
+                PackageNode pkgNode = (PackageNode) current;
+                int size = pkgNode.references.size() * 8;
+                writer.addLocation(current.getPath(), offset, 0, size);
+                offset += size;
+            } else {
+                int[] ret = new int[current.children.size()];
+                int i = 0;
+                for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
+                    ret[i] = addLocations(entry.getValue());
+                    i += 1;
+                }
+                if (current != tree.getRoot() && !(current instanceof ResourceNode)) {
+                    int size = ret.length * 4;
+                    writer.addLocation(current.getPath(), offset, 0, size);
+                    offset += size;
+                }
+            }
+            return 0;
+        }
+
+        private List<byte[]> computeContent() {
+            // Map used to associate Tree item with locations offset.
+            Map<String, ImageLocationWriter> outLocations = new HashMap<>();
+            for (ImageLocationWriter wr : writer.getLocations()) {
+                outLocations.put(wr.getFullName(), wr);
+            }
+            // Attach location to node
+            for (Map.Entry<String, ImageLocationWriter> entry : outLocations.entrySet()) {
+                Node item = tree.getMap().get(entry.getKey());
+                if (item != null) {
+                    item.loc = entry.getValue();
+                }
+            }
+            computeContent(tree.getRoot(), outLocations);
+            return content;
+        }
+
+        private int computeContent(Node current, Map<String, ImageLocationWriter> outLocations) {
+            if (current instanceof PackageNode) {
+                // /packages/<pkg name>
+                PackageNode pkgNode = (PackageNode) current;
+                int size = pkgNode.references.size() * 8;
+                ByteBuffer buff = ByteBuffer.allocate(size);
+                buff.order(writer.getByteOrder());
+                for (PackageNode.PackageReference mod : pkgNode.references.values()) {
+                    buff.putInt(mod.isEmpty ? 1 : 0);
+                    buff.putInt(writer.addString(mod.name));
+                }
+                byte[] arr = buff.array();
+                content.add(arr);
+                current.loc = outLocations.get(current.getPath());
+            } else {
+                int[] ret = new int[current.children.size()];
+                int i = 0;
+                for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
+                    ret[i] = computeContent(entry.getValue(), outLocations);
+                    i += 1;
+                }
+                if (ret.length > 0) {
+                    int size = ret.length * 4;
+                    ByteBuffer buff = ByteBuffer.allocate(size);
+                    buff.order(writer.getByteOrder());
+                    for (int val : ret) {
+                        buff.putInt(val);
+                    }
+                    byte[] arr = buff.array();
+                    content.add(arr);
+                } else {
+                    if (current instanceof ResourceNode) {
+                        // A resource location, remove "/modules"
+                        String s = tree.toResourceName(current);
+                        current.loc = outLocations.get(s);
+                    } else {
+                        // empty "/packages" or empty "/modules" paths
+                        current.loc = outLocations.get(current.getPath());
+                    }
+                }
+                if (current.loc == null && current != tree.getRoot()) {
+                    System.err.println("Invalid path in metadata, skipping " + current.getPath());
+                }
+            }
+            return current.loc == null ? 0 : current.loc.getLocationOffset();
+        }
+    }
+
+    private final List<String> paths;
+    private final LocationsAdder adder;
+
+    public ImageResourcesTree(long offset, BasicImageWriter writer, List<String> paths) {
+        this.paths = new ArrayList<>();
+        this.paths.addAll(paths);
+        Collections.sort(this.paths);
+        Tree tree = new Tree(this.paths);
+        adder = new LocationsAdder(tree, offset, writer);
+    }
+
+    public void addContent(DataOutputStream out) throws IOException {
+        List<byte[]> content = adder.computeContent();
+        for (byte[] c : content) {
+            out.write(c, 0, c.length);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java
new file mode 100644
index 0000000..30a15a6
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageStringsWriter.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import jdk.internal.jimage.ImageStream;
+import jdk.internal.jimage.ImageStrings;
+import jdk.internal.jimage.ImageStringsReader;
+
+class ImageStringsWriter implements ImageStrings {
+    private static final int NOT_FOUND = -1;
+    static final int EMPTY_OFFSET = 0;
+
+    private final HashMap<String, Integer> stringToOffsetMap;
+    private final ImageStream stream;
+
+    ImageStringsWriter() {
+        this.stringToOffsetMap = new HashMap<>();
+        this.stream = new ImageStream();
+
+        // Reserve 0 offset for empty string.
+        int offset = addString("");
+        assert offset == 0 : "Empty string not zero offset";
+        // Reserve 1 offset for frequently used ".class".
+        addString("class");
+    }
+
+    private int addString(final String string) {
+        int offset = stream.getPosition();
+        byte[] bytes = ImageStringsReader.mutf8FromString(string);
+        stream.put(bytes, 0, bytes.length);
+        stream.put('\0');
+        stringToOffsetMap.put(string, offset);
+
+        return offset;
+    }
+
+    @Override
+    public int add(final String string) {
+        int offset = find(string);
+
+        return offset == NOT_FOUND ? addString(string) : offset;
+    }
+
+    int find(final String string) {
+        Integer offset = stringToOffsetMap.get(string);
+
+        return offset != null ? offset : NOT_FOUND;
+    }
+
+    @Override
+    public String get(int offset) {
+        ByteBuffer buffer = stream.getBuffer();
+        int capacity = buffer.capacity();
+        assert 0 <= offset && offset < capacity : "String buffer offset out of range";
+        int zero = NOT_FOUND;
+        for (int i = offset; i < capacity; i++) {
+            if (buffer.get(i) == '\0') {
+                zero = i;
+                break;
+            }
+        }
+        assert zero != NOT_FOUND;
+        int length = zero - offset;
+        byte[] bytes = new byte[length];
+        int mark = buffer.position();
+        buffer.position(offset);
+        buffer.get(bytes);
+        buffer.position(mark);
+
+        return ImageStringsReader.stringFromMUTF8(bytes);
+    }
+
+    ImageStream getStream() {
+        return stream;
+    }
+
+    int getSize() {
+        return stream.getSize();
+    }
+
+    int getCount() {
+        return stringToOffsetMap.size();
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java
new file mode 100644
index 0000000..579746f
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import jdk.tools.jlink.internal.Archive.Entry.EntryType;
+
+/**
+ * An Archive backed by a jar file.
+ */
+public abstract class JarArchive implements Archive {
+
+    /**
+     * An entry located in a jar file.
+     */
+    private class JarEntry extends Entry {
+
+        private final long size;
+        private final ZipEntry entry;
+        private final ZipFile file;
+
+        JarEntry(String path, String name, EntryType type, ZipFile file, ZipEntry entry) {
+            super(JarArchive.this, path, name, type);
+            this.entry = entry;
+            this.file = file;
+            size = entry.getSize();
+        }
+
+        /**
+         * Returns the number of uncompressed bytes for this entry.
+         */
+        @Override
+        public long size() {
+            return size;
+        }
+
+        @Override
+        public InputStream stream() throws IOException {
+            return file.getInputStream(entry);
+        }
+    }
+
+    private static final String MODULE_INFO = "module-info.class";
+
+    private final Path file;
+    private final String moduleName;
+    // currently processed ZipFile
+    private ZipFile zipFile;
+
+    protected JarArchive(String mn, Path file) {
+        Objects.requireNonNull(mn);
+        Objects.requireNonNull(file);
+        this.moduleName = mn;
+        this.file = file;
+    }
+
+    @Override
+    public String moduleName() {
+        return moduleName;
+    }
+
+    @Override
+    public Path getPath() {
+        return file;
+    }
+
+    @Override
+    public Stream<Entry> entries() {
+        try {
+            if (zipFile == null) {
+                open();
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+        return zipFile.stream().map(this::toEntry).filter(n -> n != null);
+    }
+
+    abstract EntryType toEntryType(String entryName);
+
+    abstract String getFileName(String entryName);
+
+    private Entry toEntry(ZipEntry ze) {
+        String name = ze.getName();
+        String fn = getFileName(name);
+
+        if (ze.isDirectory() || fn.startsWith("_")) {
+            return null;
+        }
+
+        EntryType rt = toEntryType(name);
+
+        if (fn.equals(MODULE_INFO)) {
+            fn = moduleName + "/" + MODULE_INFO;
+        }
+        return new JarEntry(ze.getName(), fn, rt, zipFile, ze);
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (zipFile != null) {
+            zipFile.close();
+        }
+    }
+
+    @Override
+    public void open() throws IOException {
+        if (zipFile != null) {
+            zipFile.close();
+        }
+        zipFile = new ZipFile(file.toFile());
+    }
+}
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
new file mode 100644
index 0000000..e3b225f
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
@@ -0,0 +1,568 @@
+/*
+ * 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 jdk.tools.jlink.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UncheckedIOException;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolutionException;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.nio.ByteOrder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Date;
+import java.util.Formatter;
+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.stream.Collectors;
+
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.ConfigurableModuleFinder.Phase;
+import jdk.tools.jlink.internal.TaskHelper.BadArgs;
+import static jdk.tools.jlink.internal.TaskHelper.JLINK_BUNDLE;
+import jdk.tools.jlink.internal.TaskHelper.Option;
+import jdk.tools.jlink.internal.TaskHelper.OptionsHelper;
+import jdk.tools.jlink.internal.ImagePluginStack.ImageProvider;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.Jlink.JlinkConfiguration;
+import jdk.tools.jlink.Jlink.PluginsConfiguration;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+import jdk.tools.jlink.plugin.Plugin;
+
+/**
+ * Implementation for the jlink tool.
+ *
+ * ## Should use jdk.joptsimple some day.
+ */
+public class JlinkTask {
+
+    private static <T extends Throwable> void fail(Class<T> type,
+            String format,
+            Object... args) throws T {
+        String msg = new Formatter().format(format, args).toString();
+        try {
+            T t = type.getConstructor(String.class).newInstance(msg);
+            throw t;
+        } catch (InstantiationException |
+                InvocationTargetException |
+                NoSuchMethodException |
+                IllegalAccessException e) {
+            throw new InternalError("Unable to create an instance of " + type, e);
+        }
+    }
+
+    private static final TaskHelper taskHelper
+            = new TaskHelper(JLINK_BUNDLE);
+
+    static Option<?>[] recognizedOptions = {
+        new Option<JlinkTask>(false, (task, opt, arg) -> {
+            task.options.help = true;
+        }, "--help"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            String[] dirs = arg.split(File.pathSeparator);
+            task.options.modulePath = new Path[dirs.length];
+            int i = 0;
+            for (String dir : dirs) {
+                task.options.modulePath[i++] = Paths.get(dir);
+            }
+        }, "--modulepath", "--mp"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            for (String mn : arg.split(",")) {
+                if (mn.isEmpty()) {
+                    throw taskHelper.newBadArgs("err.mods.must.be.specified",
+                            "--limitmods");
+                }
+                task.options.limitMods.add(mn);
+            }
+        }, "--limitmods"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            for (String mn : arg.split(",")) {
+                if (mn.isEmpty()) {
+                    throw taskHelper.newBadArgs("err.mods.must.be.specified",
+                            "--addmods");
+                }
+                task.options.addMods.add(mn);
+            }
+        }, "--addmods"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            Path path = Paths.get(arg);
+            task.options.output = path;
+        }, "--output"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            if ("little".equals(arg)) {
+                task.options.endian = ByteOrder.LITTLE_ENDIAN;
+            } else if ("big".equals(arg)) {
+                task.options.endian = ByteOrder.BIG_ENDIAN;
+            } else {
+                throw taskHelper.newBadArgs("err.unknown.byte.order", arg);
+            }
+        }, "--endian"),
+        new Option<JlinkTask>(false, (task, opt, arg) -> {
+            task.options.version = true;
+        }, "--version"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            Path path = Paths.get(arg);
+            if (Files.exists(path)) {
+                throw taskHelper.newBadArgs("err.dir.exists", path);
+            }
+            task.options.packagedModulesPath = path;
+        }, true, "--keep-packaged-modules"),
+        new Option<JlinkTask>(false, (task, opt, arg) -> {
+            task.options.genbom = true;
+        }, true, "--genbom"),
+        new Option<JlinkTask>(true, (task, opt, arg) -> {
+            task.options.saveoptsfile = arg;
+        }, "--saveopts"),
+        new Option<JlinkTask>(false, (task, opt, arg) -> {
+            task.options.fullVersion = true;
+        }, true, "--fullversion"),};
+
+    private static final String PROGNAME = "jlink";
+    private final OptionsValues options = new OptionsValues();
+
+    private static final OptionsHelper<JlinkTask> optionsHelper
+            = taskHelper.newOptionsHelper(JlinkTask.class, recognizedOptions);
+    private PrintWriter log;
+
+    void setLog(PrintWriter out) {
+        log = out;
+        taskHelper.setLog(log);
+    }
+
+    /**
+     * Result codes.
+     */
+    static final int EXIT_OK = 0, // Completed with no errors.
+            EXIT_ERROR = 1, // Completed but reported errors.
+            EXIT_CMDERR = 2, // Bad command-line arguments
+            EXIT_SYSERR = 3, // System error or resource exhaustion.
+            EXIT_ABNORMAL = 4;// terminated abnormally
+
+    static class OptionsValues {
+        boolean help;
+        boolean genbom;
+        String  saveoptsfile;
+        boolean version;
+        boolean fullVersion;
+        Path[] modulePath;
+        Set<String> limitMods = new HashSet<>();
+        Set<String> addMods = new HashSet<>();
+        Path output;
+        Path packagedModulesPath;
+        ByteOrder endian = ByteOrder.nativeOrder();
+    }
+
+    int run(String[] args) {
+        if (log == null) {
+            setLog(new PrintWriter(System.err));
+        }
+        try {
+            optionsHelper.handleOptions(this, args);
+            if (options.help) {
+                optionsHelper.showHelp(PROGNAME);
+                return EXIT_OK;
+            }
+            if (optionsHelper.listPlugins()) {
+                optionsHelper.listPlugins(true);
+                return EXIT_OK;
+            }
+            if (options.version || options.fullVersion) {
+                taskHelper.showVersion(options.fullVersion);
+                return EXIT_OK;
+            }
+            if (taskHelper.getExistingImage() == null) {
+                if (options.modulePath == null || options.modulePath.length == 0) {
+                    throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true);
+                }
+                createImage();
+            } else {
+                postProcessOnly(taskHelper.getExistingImage());
+            }
+
+            if (options.saveoptsfile != null) {
+                Files.write(Paths.get(options.saveoptsfile), getSaveOpts().getBytes());
+            }
+
+            return EXIT_OK;
+        } catch (UncheckedIOException | PluginException | IOException | ResolutionException e) {
+            log.println(taskHelper.getMessage("error.prefix") + " " + e.getMessage());
+            log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
+            return EXIT_ERROR;
+        } catch (BadArgs e) {
+            taskHelper.reportError(e.key, e.args);
+            if (e.showUsage) {
+                log.println(taskHelper.getMessage("main.usage.summary", PROGNAME));
+            }
+            return EXIT_CMDERR;
+        } catch (Throwable x) {
+            log.println(taskHelper.getMessage("main.msg.bug"));
+            x.printStackTrace(log);
+            return EXIT_ABNORMAL;
+        } finally {
+            log.flush();
+        }
+    }
+
+    private static Map<String, Path> modulesToPath(Configuration cf) {
+        Map<String, Path> modPaths = new HashMap<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleReference mref = resolvedModule.reference();
+            URI uri = mref.location().get();
+            modPaths.put(mref.descriptor().name(), Paths.get(uri));
+        }
+        return modPaths;
+    }
+
+    /*
+     * Jlink API entry point.
+     */
+    public static void createImage(JlinkConfiguration config,
+            PluginsConfiguration plugins)
+            throws Exception {
+        Objects.requireNonNull(config);
+        Objects.requireNonNull(config.getOutput());
+        plugins = plugins == null ? new PluginsConfiguration() : plugins;
+
+        if (config.getModulepaths().isEmpty()) {
+            throw new Exception("Empty module paths");
+        }
+        Path[] arr = new Path[config.getModulepaths().size()];
+        arr = config.getModulepaths().toArray(arr);
+        ModuleFinder finder
+                = newModuleFinder(arr, config.getLimitmods(), config.getModules());
+
+        // First create the image provider
+        ImageProvider imageProvider
+                = createImageProvider(finder,
+                                      checkAddMods(config.getModules()),
+                                      config.getLimitmods(),
+                                      config.getByteOrder(),
+                                      null);
+
+        // Then create the Plugin Stack
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins,
+                genBOMContent(config, plugins));
+
+        //Ask the stack to proceed;
+        stack.operate(imageProvider);
+    }
+
+    /*
+     * Jlink API entry point.
+     */
+    public static void postProcessImage(ExecutableImage image, List<Plugin> postProcessorPlugins)
+            throws Exception {
+        Objects.requireNonNull(image);
+        Objects.requireNonNull(postProcessorPlugins);
+        PluginsConfiguration config = new PluginsConfiguration(postProcessorPlugins);
+        ImagePluginStack stack = ImagePluginConfiguration.
+                parseConfiguration(config);
+
+        stack.operate((ImagePluginStack stack1) -> image);
+    }
+
+    private void postProcessOnly(Path existingImage) throws Exception {
+        PluginsConfiguration config = taskHelper.getPluginsConfig(null, false);
+        ExecutableImage img = DefaultImageBuilder.getExecutableImage(existingImage);
+        if (img == null) {
+            throw taskHelper.newBadArgs("err.existing.image.invalid");
+        }
+        postProcessImage(img, config.getPlugins());
+    }
+
+    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);
+        try {
+            options.addMods = checkAddMods(options.addMods);
+        } catch (IllegalArgumentException ex) {
+            throw taskHelper.newBadArgs("err.mods.must.be.specified", "--addmods")
+                    .showUsage(true);
+        }
+        // First create the image provider
+        ImageProvider imageProvider
+                = createImageProvider(finder,
+                        options.addMods,
+                        options.limitMods,
+                        options.endian,
+                        options.packagedModulesPath);
+
+        // Then create the Plugin Stack
+        ImagePluginStack stack = ImagePluginConfiguration.
+                parseConfiguration(taskHelper.getPluginsConfig(options.output, options.genbom),
+                        genBOMContent());
+
+        //Ask the stack to proceed
+        stack.operate(imageProvider);
+    }
+
+    private static Set<String> checkAddMods(Set<String> addMods) {
+        if (addMods.isEmpty()) {
+            throw new IllegalArgumentException("no modules to add");
+        }
+        return addMods;
+    }
+
+    private static ModuleFinder newModuleFinder(Path[] paths,
+            Set<String> limitMods,
+            Set<String> addMods) {
+        ModuleFinder finder = ModuleFinder.of(paths);
+
+        // jmods are located at link-time
+        if (finder instanceof ConfigurableModuleFinder) {
+            ((ConfigurableModuleFinder) finder).configurePhase(Phase.LINK_TIME);
+        }
+
+        // if limitmods is specified then limit the universe
+        if (!limitMods.isEmpty()) {
+            finder = limitFinder(finder, limitMods, addMods);
+        }
+        return finder;
+    }
+
+    private static ImageProvider createImageProvider(ModuleFinder finder,
+                                                     Set<String> addMods,
+                                                     Set<String> limitMods,
+                                                     ByteOrder order,
+                                                     Path retainModulesPath)
+            throws IOException
+    {
+        if (addMods.isEmpty()) {
+            throw new IllegalArgumentException("empty modules and limitmods");
+        }
+
+        Configuration cf = Configuration.empty()
+                .resolveRequires(finder,
+                                 ModuleFinder.empty(),
+                                 addMods);
+
+        Map<String, Path> mods = modulesToPath(cf);
+        return new ImageHelper(cf, mods, order, retainModulesPath);
+    }
+
+    /**
+     * Returns a ModuleFinder that limits observability to the given root
+     * modules, their transitive dependences, plus a set of other modules.
+     */
+    private static ModuleFinder limitFinder(ModuleFinder finder,
+            Set<String> roots,
+            Set<String> otherMods) {
+
+        // resolve all root modules
+        Configuration cf = Configuration.empty()
+                .resolveRequires(finder,
+                                 ModuleFinder.empty(),
+                                 roots);
+
+        // module name -> reference
+        Map<String, ModuleReference> map = new HashMap<>();
+        cf.modules().forEach(m -> {
+            ModuleReference mref = m.reference();
+            map.put(mref.descriptor().name(), mref);
+        });
+
+        // set of modules that are observable
+        Set<ModuleReference> mrefs = new HashSet<>(map.values());
+
+        // add the other modules
+        for (String mod : otherMods) {
+            Optional<ModuleReference> omref = finder.find(mod);
+            if (omref.isPresent()) {
+                ModuleReference mref = omref.get();
+                map.putIfAbsent(mod, mref);
+                mrefs.add(mref);
+            } else {
+                // no need to fail
+            }
+        }
+
+        return new ModuleFinder() {
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                return Optional.ofNullable(map.get(name));
+            }
+
+            @Override
+            public Set<ModuleReference> findAll() {
+                return mrefs;
+            }
+        };
+    }
+
+    private String getSaveOpts() {
+        StringBuilder sb = new StringBuilder();
+        sb.append('#').append(new Date()).append("\n");
+        for (String c : optionsHelper.getInputCommand()) {
+            sb.append(c).append(" ");
+        }
+
+        return sb.toString();
+    }
+
+    private static String getBomHeader() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("#").append(new Date()).append("\n");
+        sb.append("#Please DO NOT Modify this file").append("\n");
+        return sb.toString();
+    }
+
+    private String genBOMContent() throws IOException {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getBomHeader());
+        StringBuilder command = new StringBuilder();
+        for (String c : optionsHelper.getInputCommand()) {
+            command.append(c).append(" ");
+        }
+        sb.append("command").append(" = ").append(command);
+        sb.append("\n");
+
+        return sb.toString();
+    }
+
+    private static String genBOMContent(JlinkConfiguration config,
+            PluginsConfiguration plugins)
+            throws IOException {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getBomHeader());
+        sb.append(config);
+        sb.append(plugins);
+        return sb.toString();
+    }
+
+    private static class ImageHelper implements ImageProvider {
+
+        final Set<Archive> archives;
+        final ByteOrder order;
+        final Path packagedModulesPath;
+
+        ImageHelper(Configuration cf,
+                    Map<String, Path> modsPaths,
+                    ByteOrder order,
+                    Path packagedModulesPath) throws IOException {
+            archives = modsPaths.entrySet().stream()
+                                .map(e -> newArchive(e.getKey(), e.getValue()))
+                                .collect(Collectors.toSet());
+            this.order = order;
+            this.packagedModulesPath = packagedModulesPath;
+        }
+
+        private Archive newArchive(String module, Path path) {
+            if (path.toString().endsWith(".jmod")) {
+                return new JmodArchive(module, path);
+            } else if (path.toString().endsWith(".jar")) {
+                return new ModularJarArchive(module, path);
+            } else if (Files.isDirectory(path)) {
+                return new DirArchive(path);
+            } else {
+                fail(RuntimeException.class,
+                        "Selected module %s (%s) not in jmod or modular jar format",
+                        module,
+                        path);
+            }
+            return null;
+        }
+
+        @Override
+        public ExecutableImage retrieve(ImagePluginStack stack) throws IOException {
+            ExecutableImage image = ImageFileCreator.create(archives, order, stack);
+            if (packagedModulesPath != null) {
+                // copy the packaged modules to the given path
+                Files.createDirectories(packagedModulesPath);
+                for (Archive a : archives) {
+                    Path file = a.getPath();
+                    Path dest = packagedModulesPath.resolve(file.getFileName());
+                    Files.copy(file, dest);
+                }
+            }
+            return image;
+        }
+    }
+
+    private static enum Section {
+        NATIVE_LIBS("native", nativeDir()),
+        NATIVE_CMDS("bin", "bin"),
+        CLASSES("classes", "classes"),
+        CONFIG("conf", "conf"),
+        UNKNOWN("unknown", "unknown");
+
+        private static String nativeDir() {
+            if (System.getProperty("os.name").startsWith("Windows")) {
+                return "bin";
+            } else {
+                return "lib";
+            }
+        }
+
+        private final String jmodDir;
+        private final String imageDir;
+
+        Section(String jmodDir, String imageDir) {
+            this.jmodDir = jmodDir;
+            this.imageDir = imageDir;
+        }
+
+        String imageDir() {
+            return imageDir;
+        }
+
+        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/JmodArchive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java
new file mode 100644
index 0000000..39a1734
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JmodArchive.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import jdk.tools.jlink.internal.JarArchive;
+import java.nio.file.Path;
+import java.util.Objects;
+import jdk.tools.jlink.internal.Archive.Entry.EntryType;
+
+/**
+ * An Archive backed by a jmod file.
+ */
+public class JmodArchive extends JarArchive {
+
+    private static final String JMOD_EXT = ".jmod";
+    private static final String MODULE_NAME = "module";
+    private static final String MODULE_INFO = "module-info.class";
+    private static final String CLASSES     = "classes";
+    private static final String NATIVE_LIBS = "native";
+    private static final String NATIVE_CMDS = "bin";
+    private static final String CONFIG      = "conf";
+
+    public JmodArchive(String mn, Path jmod) {
+        super(mn, jmod);
+        String filename = Objects.requireNonNull(jmod.getFileName()).toString();
+        if (!filename.endsWith(JMOD_EXT))
+            throw new UnsupportedOperationException("Unsupported format: " + filename);
+    }
+
+    @Override
+    EntryType toEntryType(String entryName) {
+        String section = getSection(entryName.replace('\\', '/'));
+        switch (section) {
+            case CLASSES:
+                return EntryType.CLASS_OR_RESOURCE;
+            case NATIVE_LIBS:
+                return EntryType.NATIVE_LIB;
+            case NATIVE_CMDS:
+                return EntryType.NATIVE_CMD;
+            case CONFIG:
+                return EntryType.CONFIG;
+            case MODULE_NAME:
+                return EntryType.MODULE_NAME;
+            default:
+                //throw new InternalError("unexpected entry: " + name + " " + zipfile.toString()); //TODO
+                throw new InternalError("unexpected entry: " + section);
+        }
+    }
+
+    private static String getSection(String entryName) {
+        int i = entryName.indexOf('/');
+        // Unnamed section.
+        String section = "";
+        if (i > 0) {
+            section = entryName.substring(0, entryName.indexOf('/'));
+        }
+        return section;
+    }
+
+    @Override
+    String getFileName(String entryName) {
+        entryName = entryName.replace('\\', '/');
+        return entryName.substring(entryName.indexOf('/') + 1);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java
new file mode 100644
index 0000000..651480d
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.*;
+
+public class Main {
+    public static void main(String... args) throws Exception {
+        JlinkTask t = new JlinkTask();
+        int rc = t.run(args);
+        System.exit(rc);
+    }
+
+
+    /**
+     * Entry point that does <i>not</i> call System.exit.
+     *
+     * @param args command line arguments
+     * @param out output stream
+     * @return an exit code. 0 means success, non-zero means an error occurred.
+     */
+    public static int run(String[] args, PrintWriter out) {
+        JlinkTask t = new JlinkTask();
+        t.setLog(out);
+        return t.run(args);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java
new file mode 100644
index 0000000..3afcfe4
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.nio.file.Path;
+import java.util.Objects;
+import jdk.tools.jlink.internal.Archive.Entry.EntryType;
+
+/**
+ * An Archive backed by a jar file.
+ */
+public class ModularJarArchive extends JarArchive {
+
+    private static final String JAR_EXT = ".jar";
+
+    public ModularJarArchive(String mn, Path jmod) {
+        super(mn, jmod);
+        String filename = Objects.requireNonNull(jmod.getFileName()).toString();
+        if (!filename.endsWith(JAR_EXT))
+            throw new UnsupportedOperationException("Unsupported format: " + filename);
+    }
+
+    @Override
+    EntryType toEntryType(String section) {
+        return EntryType.CLASS_OR_RESOURCE;
+    }
+
+    @Override
+    String getFileName(String entryName) {
+        return entryName;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PerfectHashBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PerfectHashBuilder.java
new file mode 100644
index 0000000..5f888dd
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PerfectHashBuilder.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+*/
+
+package jdk.tools.jlink.internal;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.jimage.ImageStringsReader;
+
+/*
+ * The algorithm used here is outlined in Applications of Finite Automata
+ * Representing Large Vocabularies - Claudio L Lucchesi and Tomasz Kowaltowski,
+ * 1992, and A Practical Minimal Perfect Hashing Method - Fabiano C. Botelho1,
+ * Yoshiharu Kohayakawa, and Nivio Ziviani, 2005.
+ *
+ * The primary JDK use of this algorithm is managing the jimage location index.
+ *
+ * The goal of PerfectHashBuilder is to construct an automaton which maps a
+ * string key to a unique index 0..N-1, where N is the number of key-value pairs.
+ * What makes MPHM effective is that the size of the lookup table is N or very
+ * near N, and the minimum lookup is O(1) maximum lookup is O(2).
+ *
+ * The result of PerfectHashBuilder is two integer arrays, redirect and order.
+ * The redirect table provides a 1-1 mapping to the order table, using the
+ * reader algorithm described further on.  The order table provides a mapping
+ * to entries.  If entries are fixed size and can be put in a direct table, then
+ * the order table can be used to construct the direct table and then discarded.
+ *
+ * The steps for constructing the lookup tables are as follows;
+ *
+ *   - Compute an MPHM hash for each key, based on a fixed base value modulo N.
+ *     Note, the hash is based on the modified UTF-8 of the key, simplifying
+ *     computation in native code.
+ *
+ *   - Combine keys that map to the same hash code (collisions) into bucket
+ *     chains.
+ *
+ *   - Sort bucket chains by length of chains, longest first (most collisions.)
+ *     Sorting is done to pack the redirect table with the worst collision
+ *     offenders first.
+ *
+ *   - For each chain, recompute the hash of each key using a new base value.
+ *     Recomputation should give a different key distribution. A tally is kept
+ *     of where the key maps, using the order table. The tally is used to detect
+ *     new collisions. If there are further collisions, then restart
+ *     redistribution using a different hash base value.  If a chain is
+ *     successfully distributed, then the base value used to compute the hash
+ *     is recorded in the redirect table.
+ *
+ *   - Once all colliding chains are resolved (length > 1), then the chains with
+ *     only one entry are used to fill in the empty slots in the order table.
+ *     These keys are recorded in the redirect table using the twos complement
+ *     of the order index.
+ *
+ *   - It is possible that a given set of keys cannot be packed into a table of
+ *     size N.  If this situation occurs then the size of the table is
+ *     adjusted so that keys distribute differently.
+ *
+ * Readers algoritm;
+ *
+ *   - Compute the hash for the key using the fixed base value modulo N.  This
+ *     will provide an index into the redirect table. The integer value in the
+ *     redirect table will determine the next step.
+ *
+ *   - If the value in the redirect table is positive, then that value is used
+ *     to rehash the key to get the index into the order table.
+ *
+ *   - If the value in the redirect table is negative, then that value is the
+ *     twos complement of the index into the order table.
+ *
+ *   - If the value in the redirect table is zero, then there is no matching
+ *     entry.
+ *
+ *   - Note that the resulting entry needs to be validated to ensure a match.
+ *     This is typically done by comparing the key with the key in entry.
+ */
+public class PerfectHashBuilder<E> {
+    private static final int RETRY_LIMIT = 1000;
+
+    private Class<?> entryComponent;
+    private Class<?> bucketComponent;
+
+    private final Map<String, Entry<E>> map = new LinkedHashMap<>();
+    private int[] redirect;
+    private Entry<E>[] order;
+    private int count = 0;
+
+    @SuppressWarnings("EqualsAndHashcode")
+    public static class Entry<E> {
+        private final String key;
+        private final E value;
+
+        Entry() {
+            this("", null);
+        }
+
+        Entry(String key, E value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        String getKey() {
+            return key;
+        }
+
+        E getValue() {
+            return value;
+        }
+
+        int hashCode(int seed) {
+            return ImageStringsReader.hashCode(key, seed);
+        }
+
+        @Override
+        public int hashCode() {
+            return ImageStringsReader.hashCode(key);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other == this) {
+                return true;
+            }
+            if (!(other instanceof Entry)) {
+                return false;
+            }
+            Entry<?> entry = (Entry<?>) other;
+            return entry.key.equals(key);
+        }
+    }
+
+    static class Bucket<E> implements Comparable<Bucket<E>> {
+        final List<Entry<E>> list = new ArrayList<>();
+
+        void add(Entry<E> entry) {
+            list.add(entry);
+        }
+
+        int getSize() {
+            return list.size();
+        }
+
+        List<Entry<E>> getList() {
+            return list;
+        }
+
+        Entry<E> getFirst() {
+            assert !list.isEmpty() : "bucket should never be empty";
+            return list.get(0);
+        }
+
+        @Override
+        public int hashCode() {
+            return getFirst().hashCode();
+        }
+
+        @Override
+        @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+        public boolean equals(Object obj) {
+            return this == obj;
+        }
+
+        @Override
+        public int compareTo(Bucket<E> o) {
+            return o.getSize() - getSize();
+        }
+    }
+
+    public PerfectHashBuilder(Class<?> entryComponent, Class<?> bucketComponent) {
+        this.entryComponent = entryComponent;
+        this.bucketComponent = bucketComponent;
+    }
+
+    public int getCount() {
+        return map.size();
+    }
+
+    public int[] getRedirect() {
+        return redirect.clone();
+    }
+
+    public Entry<E>[] getOrder() {
+        return order.clone();
+    }
+
+    public Entry<E> put(String key, E value) {
+        return put(new Entry<>(key, value));
+    }
+
+    public Entry<E> put(Entry<E> entry) {
+        Entry<E> old = map.put(entry.key, entry);
+
+        if (old == null) {
+            count++;
+        }
+
+        return old;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void generate() {
+        // If the table is empty then exit early.
+        boolean redo = count != 0;
+
+        // Repeat until a valid packing is achieved.
+        while (redo) {
+            redo = false;
+
+            // Allocate the resulting redirect and order tables.
+            redirect = new int[count];
+            order = (Entry<E>[])Array.newInstance(entryComponent, count);
+
+            // Place all the entries in bucket chains based on hash. Sort by
+            // length of chain.
+            Bucket<E>[] sorted = createBuckets();
+            int free = 0;
+
+            // Iterate through the chains, longest first.
+            for (Bucket<E> bucket : sorted) {
+                if (bucket.getSize() != 1) {
+                    // Attempt to pack entries until no collisions occur.
+                    if (!collidedEntries(bucket, count)) {
+                        // Failed to pack. Meed to grow table.
+                        redo = true;
+                        break;
+                    }
+                } else {
+                    // A no collision entry (bucket.getSize() == 1). Find a free
+                    // spot in the order table.
+                    for ( ; free < count && order[free] != null; free++) {}
+
+                    // If none found, then grow table.
+                    if (free >= count) {
+                        redo = true;
+                        break;
+                    }
+
+                    // Store entry in order table.
+                    order[free] = bucket.getFirst();
+                    // Twos complement of order index stired in the redirect table.
+                    redirect[(bucket.hashCode() & 0x7FFFFFFF) % count] = -1 - free;
+                    // Update free slot index.
+                    free++;
+                }
+            }
+
+            // If packing failed, then bump table size. Make odd to increase
+            // chances of being relatively prime.
+            if (redo) {
+                count = (count + 1) | 1;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private Bucket<E>[] createBuckets() {
+        // Build bucket chains based on key hash.  Collisions end up in same chain.
+        Bucket<E>[] buckets = (Bucket<E>[])Array.newInstance(bucketComponent, count);
+
+        map.values().stream().forEach((entry) -> {
+            int index = (entry.hashCode() & 0x7FFFFFFF) % count;
+            Bucket<E> bucket = buckets[index];
+
+            if (bucket == null) {
+                buckets[index] = bucket = new Bucket<>();
+            }
+
+            bucket.add(entry);
+        });
+
+        // Sort chains, longest first.
+        Bucket<E>[] sorted = Arrays.asList(buckets).stream()
+                .filter((bucket) -> (bucket != null))
+                .sorted()
+                .toArray((length) -> {
+                    return (Bucket<E>[])Array.newInstance(bucketComponent, length);
+                });
+
+        return sorted;
+    }
+
+    private boolean collidedEntries(Bucket<E> bucket, int count) {
+        // Track packing attempts.
+        List<Integer> undo = new ArrayList<>();
+        // Start with a new hash seed.
+        int seed = ImageStringsReader.HASH_MULTIPLIER + 1;
+        int retry = 0;
+
+        // Attempt to pack all the entries in a single chain.
+        redo:
+        while (true) {
+            for (Entry<E> entry : bucket.getList()) {
+                // Compute new hash.
+                int index = entry.hashCode(seed) % count;
+
+                // If a collision is detected.
+                if (order[index] != null) {
+                    // Only retry so many times with current table size.
+                    if (++retry > RETRY_LIMIT) {
+                        return false;
+                    }
+
+                    // Undo the attempted packing.
+                    undo.stream().forEach((i) -> {
+                        order[i] = null;
+                    });
+
+                    // Reset the undo list and bump up the hash seed.
+                    undo.clear();
+                    seed++;
+
+                    // Zero seed is not valid.
+                    if (seed == 0) {
+                        seed = 1;
+                    }
+
+                    // Try again.
+                    continue redo;
+                }
+
+                // No collision.
+                order[index] = entry;
+                undo.add(index);
+            }
+
+            // Entire chain packed. Record hash seed used.
+            redirect[(bucket.hashCode() & 0x7FFFFFFF) % count] = seed;
+
+            break;
+        }
+
+        return true;
+    }
+ }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java
new file mode 100644
index 0000000..7fe7dce
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginContextImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.util.Properties;
+
+import jdk.tools.jlink.plugin.PluginContext;
+
+public final class PluginContextImpl implements PluginContext {
+    private final Properties releaseProps = new Properties();
+
+    public Properties getReleaseProperties() {
+        return releaseProps;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginOrderingGraph.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginOrderingGraph.java
new file mode 100644
index 0000000..8e389b0
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginOrderingGraph.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginException;
+
+/**
+ *
+ * @author jdenise
+ */
+public class PluginOrderingGraph {
+
+    static class Node {
+
+        Plugin plugin;
+        Set<Node> nexts = new HashSet<>();
+        Set<Node> previous = new HashSet<>();
+
+        @Override
+        public String toString() {
+            return plugin.getName();
+        }
+    }
+
+    public static List<Plugin> sort(List<Plugin> plugs) {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.addAll(plugs);
+
+        // for each plugin creates its graph.
+        Map<Plugin, Node> graphs = buildGraphs(plugins);
+
+        // At this points all individual graphs are connected
+        // Check for cycles.
+        for (Node n : graphs.values()) {
+            checkCycle(n);
+        }
+
+        List<Plugin> orderedPlugins = new ArrayList<>();
+        // Retrieve the current roots, add them to the result, remove them from
+        while (!plugins.isEmpty()) {
+            // Build the current set of graphs from the list of input plugins
+            Map<Plugin, Node> currentGraphs = buildGraphs(plugins);
+            // Retrieve the root nodes (no previous)
+            List<Node> roots = getRoots(currentGraphs);
+            for (Node n : roots) {
+                // add them to the ordered list.
+                orderedPlugins.add(n.plugin);
+                // remove them from the input list.
+                plugins.remove(n.plugin);
+            }
+        }
+        return orderedPlugins;
+    }
+
+    // Create a grapth according to list of plugins.
+    private static Map<Plugin, Node> buildGraphs(List<Plugin> plugins) {
+        Map<String, Node> nodeStore = new HashMap<>();
+        for (Plugin p : plugins) {
+            Node newNode = new Node();
+            newNode.plugin = p;
+            nodeStore.put(p.getName(), newNode);
+        }
+        // for each plugin creates its graph.
+        Map<Plugin, Node> graphs = new LinkedHashMap<>();
+        for (Plugin p : plugins) {
+            Node node = nodeStore.get(p.getName());
+            for (String after : p.isAfter()) {
+                Node previous = nodeStore.get(after);
+                if (previous == null) {
+                    continue;
+                }
+                node.previous.add(previous);
+                previous.nexts.add(node);
+            }
+            for (String before : p.isBefore()) {
+                Node next = nodeStore.get(before);
+                if (next == null) {
+                    continue;
+                }
+                node.nexts.add(next);
+                next.previous.add(node);
+            }
+            graphs.put(p, node);
+
+        }
+        return graphs;
+    }
+
+    private static List<Node> getRoots(Map<Plugin, Node> graphs) {
+        List<Node> ret = new ArrayList<>();
+        for (Node n : graphs.values()) {
+            if (n.previous.isEmpty()) {
+                ret.add(n);
+            }
+        }
+        return ret;
+    }
+
+    private static void checkCycle(Node root) {
+        for (Node next : root.nexts) {
+            Set<Node> path = new LinkedHashSet<>();
+            path.add(root);
+            checkCycle(next, root, path);
+        }
+    }
+
+    private static void checkCycle(Node current, Node root, Set<Node> path) {
+        path.add(current);
+        if (current == root) {
+            StringBuilder builder = new StringBuilder();
+            for (Node p : path) {
+                builder.append(p.plugin.getName()).append(">");
+            }
+            builder.append(root);
+            throw new PluginException("Cycle detected for " + builder.toString()
+                    + ". Please fix Plugin ordering (before, after constraints).");
+        }
+
+        for (Node n : current.nexts) {
+            checkCycle(n, root, path);
+        }
+    }
+}
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
new file mode 100644
index 0000000..e4dd7b3
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.lang.reflect.Layer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.ServiceLoader;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ *
+ * Plugin Providers repository. Plugin Providers are
+ * retrieved thanks to the ServiceLoader mechanism.
+ */
+public final class PluginRepository {
+
+    private PluginRepository() {
+    }
+
+    private static final Map<String, Plugin> registeredPlugins = new HashMap<>();
+
+    /**
+     * Retrieves the plugin associated to the passed name. If multiple providers
+     * exist for the same name,
+     * then an exception is thrown.
+     * @param name The plugin provider name.
+     * @param pluginsLayer
+     * @return A provider or null if not found.
+     */
+    public static Plugin getPlugin(String name,
+            Layer pluginsLayer) {
+        Plugin tp = getPlugin(TransformerPlugin.class, name, pluginsLayer);
+        Plugin ppp = getPlugin(PostProcessorPlugin.class, name, pluginsLayer);
+
+        // We should not have a transformer plugin and a post processor plugin
+        // of the same name. That kind of duplicate is detected here.
+        if (tp != null && ppp != null) {
+            throw new PluginException("Multiple plugin "
+                        + "for the name " + name);
+        }
+
+        return tp != null? tp : ppp;
+    }
+
+    /**
+     * Build plugin for the passed name.
+     *
+     * @param config Optional config.
+     * @param name Non null name.
+     * @param pluginsLayer
+     * @return A plugin or null if no plugin found.
+     */
+    public static Plugin newPlugin(Map<String, String> config, String name,
+            Layer pluginsLayer) {
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(pluginsLayer);
+        Plugin plugin = getPlugin(name, pluginsLayer);
+        if (plugin != null) {
+            plugin.configure(config);
+        }
+        return plugin;
+    }
+
+    /**
+     * Explicit registration of a plugin in the repository. Used by unit tests
+     * @param plugin The plugin to register.
+     */
+    public synchronized static void registerPlugin(Plugin plugin) {
+        Objects.requireNonNull(plugin);
+        registeredPlugins.put(plugin.getName(), plugin);
+    }
+
+    /**
+     * Explicit unregistration of a plugin in the repository. Used by unit
+     * tests
+     *
+     * @param name Plugin name
+     */
+    public synchronized static void unregisterPlugin(String name) {
+        Objects.requireNonNull(name);
+        registeredPlugins.remove(name);
+    }
+
+    public static List<Plugin> getPlugins(Layer pluginsLayer) {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.addAll(getPlugins(TransformerPlugin.class, pluginsLayer));
+        plugins.addAll(getPlugins(PostProcessorPlugin.class, pluginsLayer));
+        return plugins;
+    }
+
+    private static <T extends Plugin> T getPlugin(Class<T> clazz, String name,
+            Layer pluginsLayer) {
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(pluginsLayer);
+        @SuppressWarnings("unchecked")
+        T provider = null;
+        List<T> javaProviders = getPlugins(clazz, pluginsLayer);
+        for(T factory : javaProviders) {
+            if (factory.getName().equals(name)) {
+                if (provider != null) {
+                    throw new PluginException("Multiple plugin "
+                            + "for the name " + name);
+                }
+                provider = factory;
+            }
+        }
+        return provider;
+    }
+
+    /**
+     * The post processors accessible in the current context.
+     *
+     * @param pluginsLayer
+     * @return The list of post processors.
+     */
+    private static <T extends Plugin> List<T> getPlugins(Class<T> clazz, Layer pluginsLayer) {
+        Objects.requireNonNull(pluginsLayer);
+        List<T> factories = new ArrayList<>();
+        try {
+            Iterator<T> providers
+                    = ServiceLoader.load(pluginsLayer, clazz).iterator();
+            while (providers.hasNext()) {
+                factories.add(providers.next());
+            }
+            registeredPlugins.values().stream().forEach((fact) -> {
+                if (clazz.isInstance(fact)) {
+                    @SuppressWarnings("unchecked")
+                    T trans = (T) fact;
+                    factories.add(trans);
+                }
+            });
+            return factories;
+        } catch (Exception ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java
new file mode 100644
index 0000000..2b1dd82
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PoolImpl.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Objects;
+import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.tools.jlink.plugin.Pool;
+
+/**
+ * Pool of module data.
+ */
+public class PoolImpl extends Pool {
+
+    /**
+     * A resource that has been compressed.
+     */
+    public static final class CompressedModuleData extends ModuleData {
+
+        private final long uncompressed_size;
+
+        private CompressedModuleData(String module, String path,
+                InputStream stream, long size,
+                long uncompressed_size) {
+            super(module, path, ModuleDataType.CLASS_OR_RESOURCE, stream, size);
+            this.uncompressed_size = uncompressed_size;
+        }
+
+        public long getUncompressedSize() {
+            return uncompressed_size;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof CompressedModuleData)) {
+                return false;
+            }
+            CompressedModuleData f = (CompressedModuleData) other;
+            return f.getPath().equals(getPath());
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+    }
+
+    private boolean isReadOnly;
+    private final StringTable table;
+
+    public PoolImpl() {
+        this(ByteOrder.nativeOrder(), new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+    }
+
+    public PoolImpl(ByteOrder order) {
+        this(order, new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+    }
+
+    public PoolImpl(ByteOrder order, StringTable table) {
+        super(order);
+        this.table = table;
+    }
+
+    public StringTable getStringTable() {
+        return table;
+    }
+
+    /**
+     * Make this Resources instance read-only. No resource can be added.
+     */
+    public void setReadOnly() {
+        isReadOnly = true;
+    }
+
+    /**
+     * Read only state.
+     *
+     * @return true if readonly false otherwise.
+     */
+    @Override
+    public boolean isReadOnly() {
+        return isReadOnly;
+    }
+
+    public static CompressedModuleData newCompressedResource(ModuleData original,
+            ByteBuffer compressed,
+            String plugin, String pluginConfig, StringTable strings,
+            ByteOrder order) {
+        Objects.requireNonNull(original);
+        Objects.requireNonNull(compressed);
+        Objects.requireNonNull(plugin);
+
+        boolean isTerminal = !(original instanceof CompressedModuleData);
+        long uncompressed_size = original.getLength();
+        if (original instanceof CompressedModuleData) {
+            CompressedModuleData comp = (CompressedModuleData) original;
+            uncompressed_size = comp.getUncompressedSize();
+        }
+        int nameOffset = strings.addString(plugin);
+        int configOffset = -1;
+        if (pluginConfig != null) {
+            configOffset = strings.addString(plugin);
+        }
+        CompressedResourceHeader rh
+                = new CompressedResourceHeader(compressed.limit(), original.getLength(),
+                        nameOffset, configOffset, isTerminal);
+        // Merge header with content;
+        byte[] h = rh.getBytes(order);
+        ByteBuffer bb = ByteBuffer.allocate(compressed.limit() + h.length);
+        bb.order(order);
+        bb.put(h);
+        bb.put(compressed);
+        byte[] contentWithHeader = bb.array();
+
+        CompressedModuleData compressedResource
+                = new CompressedModuleData(original.getModule(), original.getPath(),
+                        new ByteArrayInputStream(contentWithHeader),
+                        contentWithHeader.length, uncompressed_size);
+        return compressedResource;
+    }
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
new file mode 100644
index 0000000..d9c5bab
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePrevisitor.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import jdk.tools.jlink.plugin.Pool;
+
+/**
+ * Plugin wishing to pre-visit the resources must implement this interface.
+ * Pre-visit can be useful when some activities are required prior to the actual
+ * Resource visit.
+ * The StringTable plays a special role during previsit. The passed Strings are NOT
+ * added to the jimage file. The string usage is tracked in order to build an efficient
+ * string storage.
+ */
+public interface ResourcePrevisitor {
+
+    /**
+     * Previsit the collection of resources.
+     *
+     * @param resources Read only resources.
+     * @param strings StringTable instance. Add string to the StringTable to track string
+     * usage.
+     * @throws PluginException
+     */
+    public void previsit(Pool resources, StringTable strings);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/StringTable.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/StringTable.java
new file mode 100644
index 0000000..d98233b
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/StringTable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+/**
+* Added strings are stored in the jimage strings table.
+*/
+public interface StringTable {
+    /**
+     * Add a string to the jimage strings table.
+     * @param str The string to add.
+     * @return a String identifier.
+     */
+    public int addString(String str);
+
+    /**
+     * Retrieve a string from the passed id.
+     * @param id The string id.
+     * @return The string referenced by the passed id.
+     */
+    public String getString(int id);
+}
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
new file mode 100644
index 0000000..11df906
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
@@ -0,0 +1,730 @@
+/*
+ * 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 jdk.tools.jlink.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+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.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.ConfigurableModuleFinder.Phase;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.Jlink.PluginsConfiguration;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Plugin.CATEGORY;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
+import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
+import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+
+/**
+ *
+ * JLink and JImage tools shared helper.
+ */
+public final class TaskHelper {
+
+    public static final String JLINK_BUNDLE = "jdk.tools.jlink.resources.jlink";
+    public static final String JIMAGE_BUNDLE = "jdk.tools.jimage.resources.jimage";
+
+    private static final String DEFAULTS_PROPERTY = "jdk.jlink.defaults";
+
+    public final class BadArgs extends Exception {
+
+        static final long serialVersionUID = 8765093759964640721L;
+
+        private BadArgs(String key, Object... args) {
+            super(bundleHelper.getMessage(key, args));
+            this.key = key;
+            this.args = args;
+        }
+
+        public BadArgs showUsage(boolean b) {
+            showUsage = b;
+            return this;
+        }
+        public final String key;
+        public final Object[] args;
+        public boolean showUsage;
+    }
+
+    public static class Option<T> {
+
+        public interface Processing<T> {
+
+            void process(T task, String opt, String arg) throws BadArgs;
+        }
+
+        final boolean hasArg;
+        final Processing<T> processing;
+        final boolean hidden;
+        final String[] aliases;
+
+        public Option(boolean hasArg, Processing<T> processing, boolean hidden, String... aliases) {
+            this.hasArg = hasArg;
+            this.processing = processing;
+            this.aliases = aliases;
+            this.hidden = hidden;
+        }
+
+        public Option(boolean hasArg, Processing<T> processing, String... aliases) {
+            this(hasArg, processing, false, aliases);
+        }
+
+        public boolean isHidden() {
+            return hidden;
+        }
+
+        public boolean matches(String opt) {
+            for (String a : aliases) {
+                if (a.equals(opt)) {
+                    return true;
+                } else if (opt.startsWith("--")
+                        && (hasArg && opt.startsWith(a + "="))) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public boolean ignoreRest() {
+            return false;
+        }
+
+        void process(T task, String opt, String arg) throws BadArgs {
+            processing.process(task, opt, arg);
+        }
+    }
+
+    private static class PlugOption extends Option<PluginsOptions> {
+
+        public PlugOption(boolean hasArg,
+                Processing<PluginsOptions> processing, boolean hidden, String... aliases) {
+            super(hasArg, processing, hidden, aliases);
+        }
+
+        public PlugOption(boolean hasArg,
+                Processing<PluginsOptions> processing, String... aliases) {
+            super(hasArg, processing, aliases);
+        }
+    }
+
+    private final class PluginsOptions {
+
+        private static final String PLUGINS_PATH = "--plugin-module-path";
+        private static final String POST_PROCESS = "--post-process-path";
+
+        private Layer pluginsLayer = Layer.boot();
+        private String lastSorter;
+        private boolean listPlugins;
+        private Path existingImage;
+
+        // plugin to args maps. Each plugin may be used more than once in command line.
+        // Each such occurrence results in a Map of arguments. So, there could be multiple
+        // args maps per plugin instance.
+        private final Map<Plugin, List<Map<String, String>>> pluginToMaps = new HashMap<>();
+        private final List<PlugOption> pluginsOptions = new ArrayList<>();
+        private final List<PlugOption> mainOptions = new ArrayList<>();
+
+        private PluginsOptions(String pp) throws BadArgs {
+
+            if (pp != null) {
+                String[] dirs = pp.split(File.pathSeparator);
+                List<Path> paths = new ArrayList<>(dirs.length);
+                for (String dir : dirs) {
+                    paths.add(Paths.get(dir));
+                }
+
+                pluginsLayer = createPluginsLayer(paths);
+            }
+
+            Set<String> optionsSeen = new HashSet<>();
+            for (Plugin plugin : PluginRepository.
+                    getPlugins(pluginsLayer)) {
+                if (!Utils.isDisabled(plugin)) {
+                    addOrderedPluginOptions(plugin, optionsSeen);
+                }
+            }
+            mainOptions.add(new PlugOption(false,
+                    (task, opt, arg) -> {
+                        // This option is handled prior
+                        // to have the options parsed.
+                    },
+                    "--plugins-modulepath"));
+            mainOptions.add(new PlugOption(true, (task, opt, arg) -> {
+                Path path = Paths.get(arg);
+                if (!Files.exists(path) || !Files.isDirectory(path)) {
+                    throw newBadArgs("err.existing.image.must.exist");
+                }
+                existingImage = path.toAbsolutePath();
+            }, true, POST_PROCESS));
+            mainOptions.add(new PlugOption(true,
+                    (task, opt, arg) -> {
+                        lastSorter = arg;
+                    },
+                    true, "--resources-last-sorter"));
+            mainOptions.add(new PlugOption(false,
+                    (task, opt, arg) -> {
+                        listPlugins = true;
+                    },
+                    "--list-plugins"));
+        }
+
+        private List<Map<String, String>> argListFor(Plugin plugin) {
+            List<Map<String, String>> mapList = pluginToMaps.get(plugin);
+            if (mapList == null) {
+                mapList = new ArrayList<>();
+                pluginToMaps.put(plugin, mapList);
+            }
+            return mapList;
+        }
+
+        private void addEmptyArgumentMap(Plugin plugin) {
+            argListFor(plugin).add(Collections.emptyMap());
+        }
+
+        private Map<String, String> addArgumentMap(Plugin plugin) {
+            Map<String, String> map = new HashMap<>();
+            argListFor(plugin).add(map);
+            return map;
+        }
+
+        private void addOrderedPluginOptions(Plugin plugin,
+            Set<String> optionsSeen) throws BadArgs {
+            String option = plugin.getOption();
+            if (option == null) {
+                return;
+            }
+
+            // make sure that more than one plugin does not use the same option!
+            if (optionsSeen.contains(option)) {
+                throw new BadArgs("err.plugin.mutiple.options",
+                        option);
+            }
+            optionsSeen.add(option);
+
+            PlugOption plugOption
+                    = new PlugOption(plugin.hasArguments(),
+                            (task, opt, arg) -> {
+                                if (!Utils.isFunctional(plugin)) {
+                                    throw newBadArgs("err.provider.not.functional",
+                                            option);
+                                }
+
+                                if (! plugin.hasArguments()) {
+                                    addEmptyArgumentMap(plugin);
+                                    return;
+                                }
+
+                                Map<String, String> m = addArgumentMap(plugin);
+                                // handle one or more arguments
+                                if (arg.indexOf(':') == -1) {
+                                    // single argument case
+                                    m.put(option, arg);
+                                } else {
+                                    // This option can accept more than one arguments
+                                    // like --option_name=arg_value:arg2=value2:arg3=value3
+
+                                    // ":" followed by word char condition takes care of args that
+                                    // like Windows absolute paths "C:\foo", "C:/foo" [cygwin] etc.
+                                    // This enforces that key names start with a word character.
+                                    String[] args = arg.split(":(?=\\w)", -1);
+                                    String firstArg = args[0];
+                                    if (firstArg.isEmpty()) {
+                                        throw newBadArgs("err.provider.additional.arg.error",
+                                            option, arg);
+                                    }
+                                    m.put(option, firstArg);
+                                    // process the additional arguments
+                                    for (int i = 1; i < args.length; i++) {
+                                        String addArg = args[i];
+                                        int eqIdx = addArg.indexOf('=');
+                                        if (eqIdx == -1) {
+                                            throw newBadArgs("err.provider.additional.arg.error",
+                                                option, arg);
+                                        }
+
+                                        String addArgName = addArg.substring(0, eqIdx);
+                                        String addArgValue = addArg.substring(eqIdx+1);
+                                        if (addArgName.isEmpty() || addArgValue.isEmpty()) {
+                                            throw newBadArgs("err.provider.additional.arg.error",
+                                                option, arg);
+                                        }
+                                        m.put(addArgName, addArgValue);
+                                    }
+                                }
+                            },
+                            "--" + option);
+            pluginsOptions.add(plugOption);
+
+            if (Utils.isFunctional(plugin)) {
+                if (Utils.isAutoEnabled(plugin)) {
+                    addEmptyArgumentMap(plugin);
+                }
+
+                if (plugin instanceof DefaultCompressPlugin) {
+                    plugOption
+                        = new PlugOption(false,
+                            (task, opt, arg) -> {
+                                Map<String, String> m = addArgumentMap(plugin);
+                                m.put(DefaultCompressPlugin.NAME, DefaultCompressPlugin.LEVEL_2);
+                            }, "-c");
+                    mainOptions.add(plugOption);
+                } else if (plugin instanceof StripDebugPlugin) {
+                    plugOption
+                        = new PlugOption(false,
+                            (task, opt, arg) -> {
+                                addArgumentMap(plugin);
+                            }, "-G");
+                    mainOptions.add(plugOption);
+                }
+            }
+        }
+
+        private PlugOption getOption(String name) throws BadArgs {
+            for (PlugOption o : pluginsOptions) {
+                if (o.matches(name)) {
+                    return o;
+                }
+            }
+            for (PlugOption o : mainOptions) {
+                if (o.matches(name)) {
+                    return o;
+                }
+            }
+            return null;
+        }
+
+        private PluginsConfiguration getPluginsConfig(Path output,
+                boolean genbom) throws IOException, BadArgs {
+            if (output != null) {
+                if (Files.exists(output)) {
+                    throw new PluginException(PluginsResourceBundle.
+                            getMessage("err.dir.already.exits", output));
+                }
+            }
+
+            PluginContextImpl pluginContext = new PluginContextImpl();
+            List<Plugin> pluginsList = new ArrayList<>();
+            for (Entry<Plugin, List<Map<String, String>>> entry : pluginToMaps.entrySet()) {
+                Plugin plugin = entry.getKey();
+                List<Map<String, String>> argsMaps = entry.getValue();
+
+                // same plugin option may be used multiple times in command line.
+                // we call configure once for each occurrence. It is upto the plugin
+                // to 'merge' and/or 'override' arguments.
+                for (Map<String, String> map : argsMaps) {
+                    plugin.configure(Collections.unmodifiableMap(map), pluginContext);
+                }
+
+                if (!Utils.isDisabled(plugin)) {
+                    pluginsList.add(plugin);
+                }
+            }
+
+            // recreate or postprocessing don't require an output directory.
+            ImageBuilder builder = null;
+            if (output != null) {
+                builder = new DefaultImageBuilder(genbom, output);
+
+            }
+            return new Jlink.PluginsConfiguration(pluginsList,
+                    builder, lastSorter, pluginContext);
+        }
+    }
+
+    private static final class ResourceBundleHelper {
+
+        private final ResourceBundle bundle;
+        private final ResourceBundle pluginBundle;
+
+        ResourceBundleHelper(String path) {
+            Locale locale = Locale.getDefault();
+            try {
+                bundle = ResourceBundle.getBundle(path, locale);
+                pluginBundle = ResourceBundle.getBundle("jdk.tools.jlink.resources.plugins", locale);
+            } catch (MissingResourceException e) {
+                throw new InternalError("Cannot find jlink resource bundle for locale " + locale);
+            }
+        }
+
+        String getMessage(String key, Object... args) {
+            String val;
+            try {
+                val = bundle.getString(key);
+            } catch (MissingResourceException e) {
+                // XXX OK, check in plugin bundle
+                val = pluginBundle.getString(key);
+            }
+            return MessageFormat.format(val, args);
+        }
+
+    }
+
+    public final class OptionsHelper<T> {
+
+        private final List<Option<T>> options;
+        private String[] command;
+        private String defaults;
+
+        OptionsHelper(List<Option<T>> options) {
+            this.options = options;
+        }
+
+        private boolean hasArgument(String optionName) throws BadArgs {
+            Option<?> opt = getOption(optionName);
+            if (opt == null) {
+                opt = pluginOptions.getOption(optionName);
+                if (opt == null) {
+                    throw new BadArgs("err.unknown.option", optionName).
+                            showUsage(true);
+                }
+            }
+            return opt.hasArg;
+        }
+
+        public boolean listPlugins() {
+            return pluginOptions.listPlugins;
+        }
+
+        private String getPluginsPath(String[] args) throws BadArgs {
+            String pp = null;
+            for (int i = 0; i < args.length; i++) {
+                if (args[i].equals(PluginsOptions.PLUGINS_PATH)) {
+                    if (i == args.length - 1) {
+                        throw new BadArgs("err.no.plugins.path").showUsage(true);
+                    } else {
+                        i += 1;
+                        pp = args[i];
+                        if (!pp.isEmpty() && pp.charAt(0) == '-') {
+                            throw new BadArgs("err.no.plugins.path").showUsage(true);
+                        }
+                        break;
+                    }
+                }
+            }
+            return pp;
+        }
+
+        public List<String> handleOptions(T task, String[] args) throws BadArgs {
+            // findbugs warning, copy instead of keeping a reference.
+            command = Arrays.copyOf(args, args.length);
+
+            // Must extract it prior to do any option analysis.
+            // Required to interpret custom plugin options.
+            // Unit tests can call Task multiple time in same JVM.
+            pluginOptions = new PluginsOptions(getPluginsPath(args));
+
+            // First extract plugins path if any
+            String pp = null;
+            List<String> filteredArgs = new ArrayList<>();
+            for (int i = 0; i < args.length; i++) {
+                if (args[i].equals(PluginsOptions.PLUGINS_PATH)) {
+                    if (i == args.length - 1) {
+                        throw new BadArgs("err.no.plugins.path").showUsage(true);
+                    } else {
+                        warning("warn.thirdparty.plugins.enabled");
+                        log.println(bundleHelper.getMessage("warn.thirdparty.plugins"));
+                        i += 1;
+                        String arg = args[i];
+                        if (!arg.isEmpty() && arg.charAt(0) == '-') {
+                            throw new BadArgs("err.no.plugins.path").showUsage(true);
+                        }
+                        pp = args[i];
+                    }
+                } else {
+                    filteredArgs.add(args[i]);
+                }
+            }
+            String[] arr = new String[filteredArgs.size()];
+            args = filteredArgs.toArray(arr);
+
+            List<String> rest = new ArrayList<>();
+            // process options
+            for (int i = 0; i < args.length; i++) {
+                if (!args[i].isEmpty() && args[i].charAt(0) == '-') {
+                    String name = args[i];
+                    PlugOption pluginOption = null;
+                    Option<T> option = getOption(name);
+                    if (option == null) {
+                        pluginOption = pluginOptions.getOption(name);
+                        if (pluginOption == null) {
+
+                            throw new BadArgs("err.unknown.option", name).
+                                    showUsage(true);
+                        }
+                    }
+                    Option<?> opt = pluginOption == null ? option : pluginOption;
+                    String param = null;
+                    if (opt.hasArg) {
+                        if (name.startsWith("--") && name.indexOf('=') > 0) {
+                            param = name.substring(name.indexOf('=') + 1,
+                                    name.length());
+                        } else if (i + 1 < args.length) {
+                            param = args[++i];
+                        }
+                        if (param == null || param.isEmpty()
+                                || (param.length() >= 2 && param.charAt(0) == '-'
+                                && param.charAt(1) == '-')) {
+                            throw new BadArgs("err.missing.arg", name).
+                                    showUsage(true);
+                        }
+                    }
+                    if (pluginOption != null) {
+                        pluginOption.process(pluginOptions, name, param);
+                    } else {
+                        option.process(task, name, param);
+                    }
+                    if (opt.ignoreRest()) {
+                        i = args.length;
+                    }
+                } else {
+                    rest.add(args[i]);
+                }
+            }
+            return rest;
+        }
+
+        private Option<T> getOption(String name) {
+            for (Option<T> o : options) {
+                if (o.matches(name)) {
+                    return o;
+                }
+            }
+            return null;
+        }
+
+        public void showHelp(String progName) {
+            showHelp(progName, true);
+        }
+
+        private void showHelp(String progName, boolean showsImageBuilder) {
+            log.println(bundleHelper.getMessage("main.usage", progName));
+            for (Option<?> o : options) {
+                String name = o.aliases[0].substring(1); // there must always be at least one name
+                name = name.charAt(0) == '-' ? name.substring(1) : name;
+                if (o.isHidden() || name.equals("h")) {
+                    continue;
+                }
+                log.println(bundleHelper.getMessage("main.opt." + name));
+            }
+
+            for (Option<?> o : pluginOptions.mainOptions) {
+                if (o.aliases[0].equals(PluginsOptions.POST_PROCESS)
+                        && !showsImageBuilder) {
+                    continue;
+                }
+                String name = o.aliases[0].substring(1); // there must always be at least one name
+                name = name.charAt(0) == '-' ? name.substring(1) : name;
+                if (o.isHidden()) {
+                    continue;
+                }
+                log.println(bundleHelper.getMessage("plugin.opt." + name));
+            }
+
+            log.println(bundleHelper.getMessage("main.command.files"));
+        }
+
+        public void listPlugins(boolean showsImageBuilder) {
+            log.println("\n" + bundleHelper.getMessage("main.extended.help"));
+            List<Plugin> pluginList = PluginRepository.
+                    getPlugins(pluginOptions.pluginsLayer);
+            for (Plugin plugin : Utils.
+                    getSortedPreProcessors(pluginList)) {
+                showPlugin(plugin, log, showsImageBuilder);
+            }
+
+            if (showsImageBuilder) {
+                for (Plugin plugin : Utils.getSortedPostProcessors(pluginList)) {
+                    showPlugin(plugin, log, showsImageBuilder);
+                }
+            }
+        }
+
+        private void showPlugin(Plugin plugin, PrintWriter log, boolean showsImageBuilder) {
+            if (showsPlugin(plugin, showsImageBuilder)) {
+                log.println("\n" + bundleHelper.getMessage("main.plugin.name")
+                        + ": " + plugin.getName());
+
+                // print verbose details for non-builtin plugins
+                if (!Utils.isBuiltin(plugin)) {
+                    log.println(bundleHelper.getMessage("main.plugin.class")
+                         + ": " + plugin.getClass().getName());
+                    log.println(bundleHelper.getMessage("main.plugin.module")
+                         + ": " + plugin.getClass().getModule().getName());
+                    CATEGORY category = Utils.getCategory(plugin);
+                    log.println(bundleHelper.getMessage("main.plugin.category")
+                         + ": " + category.getName());
+                    log.println(bundleHelper.getMessage("main.plugin.state")
+                        + ": " + plugin.getStateDescription());
+                }
+
+                String option = plugin.getOption();
+                if (option != null) {
+                    log.println(bundleHelper.getMessage("main.plugin.option")
+                        + ": --" + plugin.getOption()
+                        + (plugin.hasArguments()? ("=" + plugin.getArgumentsDescription()) : ""));
+                }
+
+                // description can be long spanning more than one line and so
+                // print a newline after description label.
+                log.println(bundleHelper.getMessage("main.plugin.description")
+                        + ": " + plugin.getDescription());
+            }
+        }
+
+        String[] getInputCommand() {
+            return command;
+        }
+
+        String getDefaults() {
+            return defaults;
+        }
+
+        public Layer getPluginsLayer() {
+            return pluginOptions.pluginsLayer;
+        }
+    }
+
+    private PluginsOptions pluginOptions;
+    private PrintWriter log;
+    private final ResourceBundleHelper bundleHelper;
+
+    public TaskHelper(String path) {
+        if (!JLINK_BUNDLE.equals(path) && !JIMAGE_BUNDLE.equals(path)) {
+            throw new IllegalArgumentException("Invalid Bundle");
+        }
+        this.bundleHelper = new ResourceBundleHelper(path);
+    }
+
+    public <T> OptionsHelper<T> newOptionsHelper(Class<T> clazz,
+            Option<?>[] options) {
+        List<Option<T>> optionsList = new ArrayList<>();
+        for (Option<?> o : options) {
+            @SuppressWarnings("unchecked")
+            Option<T> opt = (Option<T>) o;
+            optionsList.add(opt);
+        }
+        return new OptionsHelper<>(optionsList);
+    }
+
+    public BadArgs newBadArgs(String key, Object... args) {
+        return new BadArgs(key, args);
+    }
+
+    public String getMessage(String key, Object... args) {
+        return bundleHelper.getMessage(key, args);
+    }
+
+    public void setLog(PrintWriter log) {
+        this.log = log;
+    }
+
+    public void reportError(String key, Object... args) {
+        log.println(bundleHelper.getMessage("error.prefix") + " "
+                + bundleHelper.getMessage(key, args));
+    }
+
+    public void reportUnknownError(String message) {
+        log.println(bundleHelper.getMessage("error.prefix") + " " + message);
+    }
+
+    public void warning(String key, Object... args) {
+        log.println(bundleHelper.getMessage("warn.prefix") + " "
+                + bundleHelper.getMessage(key, args));
+    }
+
+    public PluginsConfiguration getPluginsConfig(Path output, boolean genbom)
+            throws IOException, BadArgs {
+        return pluginOptions.getPluginsConfig(output, genbom);
+    }
+
+    public Path getExistingImage() {
+        return pluginOptions.existingImage;
+    }
+
+    public void showVersion(boolean full) {
+        log.println(version(full ? "full" : "release"));
+    }
+
+    public String version(String key) {
+        return System.getProperty("java.version");
+    }
+
+    static Layer createPluginsLayer(List<Path> paths) {
+        Path[] arr = new Path[paths.size()];
+        paths.toArray(arr);
+        ModuleFinder finder = ModuleFinder.of(arr);
+
+        // jmods are located at link-time
+        if (finder instanceof ConfigurableModuleFinder) {
+            ((ConfigurableModuleFinder) finder).configurePhase(Phase.LINK_TIME);
+        }
+
+        Configuration bootConfiguration = Layer.boot().configuration();
+        try {
+            Configuration cf = bootConfiguration
+                .resolveRequiresAndUses(ModuleFinder.empty(),
+                                        finder,
+                                        Collections.emptySet());
+            ClassLoader scl = ClassLoader.getSystemClassLoader();
+            return Layer.boot().defineModulesWithOneLoader(cf, scl);
+        } catch (Exception ex) {
+            // Malformed plugin modules (e.g.: same package in multiple modules).
+            throw new PluginException("Invalid modules in the plugins path: " + ex);
+        }
+    }
+
+    // Display all plugins or pre processors only.
+    private static boolean showsPlugin(Plugin plugin, boolean showsImageBuilder) {
+        if (!Utils.isDisabled(plugin) && plugin.getOption() != null) {
+            if (Utils.isPostProcessor(plugin) && !showsImageBuilder) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java
new file mode 100644
index 0000000..ac278a0
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.lang.reflect.Module;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Function;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Plugin.PluginType;
+
+/**
+ *
+ * @author jdenise
+ */
+public class Utils {
+
+    private Utils() {}
+
+    // current module
+    private static final Module THIS_MODULE = Utils.class.getModule();
+
+    public static final Function<String, String[]> listParser = (argument) -> {
+        String[] arguments = null;
+        if (argument != null) {
+            arguments = argument.split(",");
+            for (int i = 0; i < arguments.length; i++) {
+                arguments[i] = arguments[i].trim();
+            }
+        }
+        return arguments;
+    };
+
+    public static boolean isPostProcessor(Plugin.CATEGORY category) {
+        return category.equals(Plugin.CATEGORY.VERIFIER)
+                || category.equals(Plugin.CATEGORY.PROCESSOR)
+                || category.equals(Plugin.CATEGORY.PACKAGER);
+    }
+
+    public static boolean isPreProcessor(Plugin.CATEGORY category) {
+        return category.equals(Plugin.CATEGORY.COMPRESSOR)
+                || category.equals(Plugin.CATEGORY.FILTER)
+                || category.equals(Plugin.CATEGORY.MODULEINFO_TRANSFORMER)
+                || category.equals(Plugin.CATEGORY.SORTER)
+                || category.equals(Plugin.CATEGORY.TRANSFORMER);
+    }
+
+    public static boolean isPostProcessor(Plugin prov) {
+        if (prov.getType() != null) {
+            for (PluginType pt : prov.getType()) {
+                if (pt instanceof Plugin.CATEGORY) {
+                    return isPostProcessor((Plugin.CATEGORY) pt);
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isPreProcessor(Plugin prov) {
+        if (prov.getType() != null) {
+            for (PluginType pt : prov.getType()) {
+                if (pt instanceof Plugin.CATEGORY) {
+                    return isPreProcessor((Plugin.CATEGORY) pt);
+                }
+            }
+        }
+        return false;
+    }
+
+    public static Plugin.CATEGORY getCategory(Plugin provider) {
+        if (provider.getType() != null) {
+            for (Plugin.PluginType t : provider.getType()) {
+                if (t instanceof Plugin.CATEGORY) {
+                    return (Plugin.CATEGORY) t;
+                }
+            }
+        }
+        return null;
+    }
+
+    public static List<Plugin> getPostProcessors(List<Plugin> plugins) {
+        List<Plugin> res = new ArrayList<>();
+        for (Plugin p : plugins) {
+            if (isPostProcessor(p)) {
+                res.add(p);
+            }
+        }
+        return res;
+    }
+
+    public static List<Plugin> getSortedPostProcessors(List<Plugin> plugins) {
+        List<Plugin> res = getPostProcessors(plugins);
+        res.sort(new Comparator<Plugin>() {
+            @Override
+            public int compare(Plugin o1, Plugin o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        return res;
+    }
+
+    public static List<Plugin> getSortedPreProcessors(List<Plugin> plugins) {
+        List<Plugin> res = getPreProcessors(plugins);
+        res.sort(new Comparator<Plugin>() {
+            @Override
+            public int compare(Plugin o1, Plugin o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        return res;
+    }
+
+    public static List<Plugin> getPreProcessors(List<Plugin> plugins) {
+        List<Plugin> res = new ArrayList<>();
+        for (Plugin p : plugins) {
+            if (isPreProcessor(p)) {
+                res.add(p);
+            }
+        }
+        return res;
+    }
+
+    public static boolean isFunctional(Plugin prov) {
+        return prov.getState().contains(Plugin.STATE.FUNCTIONAL);
+    }
+
+    public static boolean isAutoEnabled(Plugin prov) {
+        return prov.getState().contains(Plugin.STATE.AUTO_ENABLED);
+    }
+
+    public static boolean isDisabled(Plugin prov) {
+        return prov.getState().contains(Plugin.STATE.DISABLED);
+    }
+
+    // is this a builtin (jdk.jlink) plugin?
+    public static boolean isBuiltin(Plugin prov) {
+        return THIS_MODULE.equals(prov.getClass().getModule());
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
new file mode 100644
index 0000000..e29f42e
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.ResourcePrevisitor;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * ZIP and String Sharing compression plugin
+ */
+public final class DefaultCompressPlugin implements TransformerPlugin, ResourcePrevisitor {
+    public static final String NAME = "compress";
+    public static final String FILTER = "filter";
+    public static final String LEVEL_0 = "0";
+    public static final String LEVEL_1 = "1";
+    public static final String LEVEL_2 = "2";
+
+    private StringSharingPlugin ss;
+    private ZipPlugin zip;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        if (ss != null && zip != null) {
+            Pool output = new ImagePluginStack.OrderedResourcePool(in.getByteOrder(),
+                    ((PoolImpl) in).getStringTable());
+            ss.visit(in, output);
+            zip.visit(output, out);
+        } else if (ss != null) {
+            ss.visit(in, out);
+        } else if (zip != null) {
+            zip.visit(in, out);
+        }
+    }
+
+    @Override
+    public void previsit(Pool resources, StringTable strings) {
+        if (ss != null) {
+            ss.previsit(resources, strings);
+        }
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.COMPRESSOR);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String filter = config.get(FILTER);
+            String[] patterns = filter == null ? null
+                    : Utils.listParser.apply(filter);
+            ResourceFilter resFilter = new ResourceFilter(patterns);
+            String level = config.get(NAME);
+            if (level != null) {
+                switch (level) {
+                    case LEVEL_0:
+                        ss = new StringSharingPlugin(resFilter);
+                        break;
+                    case LEVEL_1:
+                        zip = new ZipPlugin(resFilter);
+                        break;
+                    case LEVEL_2:
+                        ss = new StringSharingPlugin(resFilter);
+                        zip = new ZipPlugin(resFilter);
+                        break;
+                    default:
+                        throw new PluginException("Invalid level " + level);
+                }
+            } else {
+                ss = new StringSharingPlugin(resFilter);
+                zip = new ZipPlugin(resFilter);
+            }
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
new file mode 100644
index 0000000..0271670
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * Exclude files plugin
+ */
+public final class ExcludeFilesPlugin implements TransformerPlugin {
+
+    public static final String NAME = "exclude-files";
+    private Predicate<String> predicate;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((file) -> {
+            if (!file.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+                file = predicate.test(file.getPath()) ? file : null;
+            }
+            return file;
+        }, out);
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.FILTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String value = config.get(NAME);
+            predicate = new ResourceFilter(Utils.listParser.apply(value), true);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
new file mode 100644
index 0000000..6d4737a
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludePlugin.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * Exclude resources plugin
+ */
+public final class ExcludePlugin implements TransformerPlugin {
+
+    public static final String NAME = "exclude-resources";
+    private Predicate<String> predicate;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((resource) -> {
+            if (resource.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
+                resource = predicate.test(resource.getPath()) ? resource : null;
+            }
+            return resource;
+        }, out);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.FILTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String val = config.get(NAME);
+            predicate = new ResourceFilter(Utils.listParser.apply(val), true);
+        } catch (IOException ex) {
+            throw new PluginException(ex);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
new file mode 100644
index 0000000..185906d
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.internal.Utils;
+import jdk.tools.jlink.plugin.PluginException;
+
+/**
+ *
+ * Exclude VM plugin
+ */
+public final class ExcludeVMPlugin implements TransformerPlugin {
+
+    private static final class JvmComparator implements Comparator<Jvm> {
+
+        @Override
+        public int compare(Jvm o1, Jvm o2) {
+            return o1.getEfficience() - o2.getEfficience();
+        }
+    }
+
+    private enum Jvm {
+        // The efficience order server - client - minimal.
+        SERVER("server", 3), CLIENT("client", 2), MINIMAL("minimal", 1);
+        private final String name;
+        private final int efficience;
+
+        Jvm(String name, int efficience) {
+            this.name = name;
+            this.efficience = efficience;
+        }
+
+        private String getName() {
+            return name;
+        }
+
+        private int getEfficience() {
+            return efficience;
+        }
+    }
+
+    private static final String JVM_CFG = "jvm.cfg";
+
+    public static final String NAME = "vm";
+    private static final String ALL = "all";
+    private static final String CLIENT = "client";
+    private static final String SERVER = "server";
+    private static final String MINIMAL = "minimal";
+
+    private Predicate<String> predicate;
+    private Jvm target;
+    private boolean keepAll;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * VM paths:
+     * /java.base/native/{architecture}/{server|client|minimal}/{shared lib}
+     * e.g.: /java.base/native/amd64/server/libjvm.so
+     * /java.base/native/server/libjvm.dylib
+     */
+    private List<Pool.ModuleData> getVMs(Pool in) {
+        String jvmlib = jvmlib();
+        List<Pool.ModuleData> ret = in.getModule("java.base").getContent().stream().filter((t) -> {
+            return t.getPath().endsWith("/" + jvmlib);
+        }).collect(Collectors.toList());
+        return ret;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        String jvmlib = jvmlib();
+        TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
+        TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
+        if (!keepAll) {
+            // First retrieve all available VM names and removed VM
+            List<Pool.ModuleData> jvms = getVMs(in);
+            for (Jvm jvm : Jvm.values()) {
+                for (Pool.ModuleData md : jvms) {
+                    if (md.getPath().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
+                        existing.add(jvm);
+                        if (isRemoved(md)) {
+                            removed.add(jvm);
+                        }
+                    }
+                }
+            }
+        }
+        // Check that target exists
+        if (!keepAll) {
+            if (!existing.contains(target)) {
+                throw new PluginException("Selected VM " + target.getName() + " doesn't exist.");
+            }
+        }
+
+        // Rewrite the jvm.cfg file.
+        in.visit((file) -> {
+            if (!keepAll) {
+                if (file.getType().equals(ModuleDataType.NATIVE_LIB)) {
+                    if (file.getPath().endsWith(JVM_CFG)) {
+                        try {
+                            file = handleJvmCfgFile(file, existing, removed);
+                        } catch (IOException ex) {
+                            throw new UncheckedIOException(ex);
+                        }
+                    }
+                }
+                file = isRemoved(file) ? null : file;
+            }
+            return file;
+        }, out);
+
+    }
+
+    private boolean isRemoved(Pool.ModuleData file) {
+        return !predicate.test(file.getPath());
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.FILTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String value = config.get(NAME);
+            String exclude = "";
+            switch (value) {
+                case ALL: {
+                    // no filter.
+                    keepAll = true;
+                    break;
+                }
+                case CLIENT: {
+                    target = Jvm.CLIENT;
+                    exclude = "/java.base/native*server/*,/java.base/native*minimal/*";
+                    break;
+                }
+                case SERVER: {
+                    target = Jvm.SERVER;
+                    exclude = "/java.base/native*client/*,/java.base/native*minimal/*";
+                    break;
+                }
+                case MINIMAL: {
+                    target = Jvm.MINIMAL;
+                    exclude = "/java.base/native*server/*,/java.base/native*client/*";
+                    break;
+                }
+                default: {
+                    throw new PluginException("Unknown option " + value);
+                }
+            }
+            predicate = new ResourceFilter(Utils.listParser.apply(exclude), true);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    private Pool.ModuleData handleJvmCfgFile(Pool.ModuleData orig,
+            TreeSet<Jvm> existing,
+            TreeSet<Jvm> removed) throws IOException {
+        if (keepAll) {
+            return orig;
+        }
+        StringBuilder builder = new StringBuilder();
+        // Keep comments
+        try (BufferedReader reader
+                = new BufferedReader(new InputStreamReader(orig.stream(),
+                        StandardCharsets.UTF_8))) {
+            reader.lines().forEach((s) -> {
+                if (s.startsWith("#")) {
+                    builder.append(s).append("\n");
+                }
+            });
+        }
+        TreeSet<Jvm> remaining = new TreeSet<>(new JvmComparator());
+        // Add entry in jvm.cfg file from the more efficient to less efficient.
+        for (Jvm platform : existing) {
+            if (!removed.contains(platform)) {
+                remaining.add(platform);
+                builder.append("-").append(platform.getName()).append(" KNOWN\n");
+            }
+        }
+
+        // removed JVM are aliased to the most efficient remaining JVM (last one).
+        // The order in the file is from most to less efficient platform
+        for (Jvm platform : removed.descendingSet()) {
+            builder.append("-").append(platform.getName()).
+                    append(" ALIASED_TO -").
+                    append(remaining.last().getName()).append("\n");
+        }
+
+        byte[] content = builder.toString().getBytes(StandardCharsets.UTF_8);
+
+        return Pool.newImageFile(orig.getModule(),
+                orig.getPath(),
+                orig.getType(),
+                new ByteArrayInputStream(content), content.length);
+    }
+
+    private static String jvmlib() {
+        String lib = "libjvm.so";
+        if (isWindows()) {
+            lib = "jvm.dll";
+        } else if (isMac()) {
+            lib = "libjvm.dylib";
+        }
+        return lib;
+    }
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").startsWith("Windows");
+    }
+
+    private static boolean isMac() {
+        return System.getProperty("os.name").startsWith("Mac OS");
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
new file mode 100644
index 0000000..7a51d6c
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+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.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * Copy files to image from various locations.
+ */
+public class FileCopierPlugin implements TransformerPlugin {
+
+    public static final String NAME = "copy-files";
+
+    private static final class CopiedFile {
+
+        Path source;
+        Path target;
+    }
+    public static final String FAKE_MODULE = "$jlink-file-copier";
+
+    private final List<CopiedFile> files = new ArrayList<>();
+
+    /**
+     * Symbolic link to another path.
+     */
+    public static abstract class SymImageFile extends Pool.ModuleData {
+
+        private final String targetPath;
+
+        public SymImageFile(String targetPath, String module, String path,
+                Pool.ModuleDataType type, InputStream stream, long size) {
+            super(module, path, type, stream, size);
+            this.targetPath = targetPath;
+        }
+
+        public String getTargetPath() {
+            return targetPath;
+        }
+    }
+
+    private static final class SymImageFileImpl extends SymImageFile {
+
+        public SymImageFileImpl(String targetPath, Path file, String module,
+                String path, ModuleDataType type) {
+            super(targetPath, module, path, type, newStream(file), length(file));
+        }
+    }
+
+    private static long length(Path file) {
+        try {
+            return Files.size(file);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    private static InputStream newStream(Path file) {
+        try {
+            return Files.newInputStream(file);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    private static final class DirectoryCopy implements FileVisitor<Path> {
+
+        private final Path source;
+        private final Pool pool;
+        private final String targetDir;
+        private final List<SymImageFile> symlinks = new ArrayList<>();
+
+        DirectoryCopy(Path source, Pool pool, String targetDir) {
+            this.source = source;
+            this.pool = pool;
+            this.targetDir = targetDir;
+        }
+
+        @Override
+        public FileVisitResult preVisitDirectory(Path dir,
+                BasicFileAttributes attrs) throws IOException {
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path file,
+                BasicFileAttributes attrs) throws IOException {
+            Objects.requireNonNull(file);
+            Objects.requireNonNull(attrs);
+            String path = targetDir + "/" + source.relativize(file);
+            if (attrs.isSymbolicLink()) {
+                Path symTarget = Files.readSymbolicLink(file);
+                if (!Files.exists(symTarget)) {
+                    // relative to file parent?
+                    Path parent = file.getParent();
+                    if (parent != null) {
+                        symTarget = parent.resolve(symTarget);
+                    }
+                }
+                if (!Files.exists(symTarget)) {
+                    System.err.println("WARNING: Skipping sym link, target "
+                            + Files.readSymbolicLink(file) + "not found");
+                    return FileVisitResult.CONTINUE;
+                }
+                SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(),
+                        file, path, Objects.requireNonNull(file.getFileName()).toString(),
+                        Pool.ModuleDataType.OTHER);
+                symlinks.add(impl);
+            } else {
+                addFile(pool, file, path);
+            }
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+                throws IOException {
+            if (exc != null) {
+                throw exc;
+            }
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFileFailed(Path file, IOException exc)
+                throws IOException {
+            throw exc;
+        }
+    }
+
+    private static void addFile(Pool pool, Path file, String path)
+            throws IOException {
+        Objects.requireNonNull(pool);
+        Objects.requireNonNull(file);
+        Objects.requireNonNull(path);
+        ModuleData impl = Pool.newImageFile(FAKE_MODULE,
+                "/" + FAKE_MODULE + "/other/" + path,
+                Pool.ModuleDataType.OTHER, newStream(file), length(file));
+        try {
+            pool.add(impl);
+        } catch (Exception ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.TRANSFORMER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        String val = config.get(NAME);
+        String[] argument = Utils.listParser.apply(val);
+        if (argument == null || argument.length == 0) {
+            throw new RuntimeException("Invalid argument for " + NAME);
+        }
+
+        String javahome = System.getProperty("java.home");
+        for (String a : argument) {
+            int i = a.indexOf("=");
+            CopiedFile cf = new CopiedFile();
+            if (i == -1) {
+                Path file = Paths.get(a);
+                if (file.isAbsolute()) {
+                    cf.source = file;
+                    // The target is the image root directory.
+                    cf.target = file.getFileName();
+                } else {
+                    file = new File(javahome, a).toPath();
+                    cf.source = file;
+                    cf.target = Paths.get(a);
+                }
+            } else {
+                String target = a.substring(i + 1);
+                String f = a.substring(0, i);
+                Path file = Paths.get(f);
+                if (file.isAbsolute()) {
+                    cf.source = file;
+                } else {
+                    cf.source = new File(javahome,
+                            file.toFile().getPath()).toPath();
+                }
+                cf.target = Paths.get(target);
+            }
+            if (!Files.exists(cf.source)) {
+                System.err.println("Skipping file " + cf.source
+                        + ", it doesn't exist");
+            } else {
+                files.add(cf);
+            }
+        }
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((file) -> {
+            return file;
+        }, out);
+
+        // Add new files.
+        try {
+            for (CopiedFile file : files) {
+                if (Files.isRegularFile(file.source)) {
+                    addFile(out, file.source, file.target.toString());
+                } else if (Files.isDirectory(file.source)) {
+                    DirectoryCopy dc = new DirectoryCopy(file.source,
+                            out, file.target.toString());
+                    Files.walkFileTree(file.source, dc);
+                    // Add symlinks after actual content
+                    for (SymImageFile imf : dc.symlinks) {
+                        try {
+                            out.add(imf);
+                        } catch (Exception ex) {
+                            throw new PluginException(ex);
+                        }
+                    }
+                }
+            }
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
new file mode 100644
index 0000000..c901f05
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.IllformedLocaleException;
+import java.util.Locale;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.ResourcePrevisitor;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ * Plugin to explicitly specify the locale data included in jdk.localedata
+ * module. This plugin provides a jlink command line option "--include-locales"
+ * with an argument. The argument is a list of BCP 47 language tags separated
+ * by a comma. E.g.,
+ *
+ *  "jlink --include-locales en,ja,*-IN"
+ *
+ * This option will include locale data for all available English and Japanese
+ * languages, and ones for the country of India. All other locale data are
+ * filtered out on the image creation.
+ *
+ * Here are a few assumptions:
+ *
+ *  0. All locale data in java.base are unconditionally included.
+ *  1. All the selective locale data are in jdk.localedata module
+ *  2. Their package names are constructed by appending ".ext" to
+ *     the corresponding ones in java.base module.
+ *  3. Available locales string in LocaleDataMetaInfo class should
+ *     start with at least one white space character, e.g., " ar ar-EG ..."
+ *                                                           ^
+ */
+public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePrevisitor {
+
+    public static final String NAME = "include-locales";
+    private static final String MODULENAME = "jdk.localedata";
+    private static final Set<String> LOCALEDATA_PACKAGES = Set.of(
+        "sun.text.resources.cldr.ext",
+        "sun.text.resources.ext",
+        "sun.util.resources.cldr.ext",
+        "sun.util.resources.cldr.provider",
+        "sun.util.resources.ext",
+        "sun.util.resources.provider");
+    private static final String METAINFONAME = "LocaleDataMetaInfo";
+    private static final String META_FILES =
+        "*module-info.class," +
+        "*LocaleDataProvider*," +
+        "*" + METAINFONAME + "*,";
+    private static final String INCLUDE_LOCALE_FILES =
+        "*sun/text/resources/ext/[^\\/]+_%%.class," +
+        "*sun/util/resources/ext/[^\\/]+_%%.class," +
+        "*sun/text/resources/cldr/ext/[^\\/]+_%%.class," +
+        "*sun/util/resources/cldr/ext/[^\\/]+_%%.class,";
+    private Predicate<String> predicate;
+    private List<Locale.LanguageRange> priorityList;
+    private List<Locale> available;
+    private List<String> filtered;
+
+    // Special COMPAT provider locales
+    private static final String jaJPJPTag = "ja-JP-JP";
+    private static final String noNONYTag = "no-NO-NY";
+    private static final String thTHTHTag = "th-TH-TH";
+    private static final Locale jaJPJP = new Locale("ja", "JP", "JP");
+    private static final Locale noNONY = new Locale("no", "NO", "NY");
+    private static final Locale thTHTH = new Locale("th", "TH", "TH");
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((resource) -> {
+            if (resource.getModule().equals(MODULENAME)) {
+                String path = resource.getPath();
+                resource = predicate.test(path) ? resource: null;
+                if (resource != null) {
+                    byte[] bytes = resource.getBytes();
+                    ClassReader cr = new ClassReader(bytes);
+                    if (Arrays.stream(cr.getInterfaces())
+                        .anyMatch(i -> i.contains(METAINFONAME)) &&
+                        stripUnsupportedLocales(bytes, cr)) {
+                        resource = new Pool.ModuleData(MODULENAME, path,
+                            resource.getType(),
+                            new ByteArrayInputStream(bytes), bytes.length);
+                    }
+                }
+            }
+            return resource;
+        }, out);
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.FILTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        priorityList = Arrays.stream(config.get(NAME).split(","))
+            .map(Locale.LanguageRange::new)
+            .collect(Collectors.toList());
+    }
+
+    @Override
+    public void previsit(Pool resources, StringTable strings) {
+        final Pattern p = Pattern.compile(".*((Data_)|(Names_))(?<tag>.*)\\.class");
+        Pool.Module module = resources.getModule(MODULENAME);
+
+        // jdk.localedata module validation
+        Set<String> packages = module.getAllPackages();
+        if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
+            throw new PluginException("Missing locale data packages in jdk.localedata:\n\t" +
+                LOCALEDATA_PACKAGES.stream()
+                    .filter(pn -> !packages.contains(pn))
+                    .collect(Collectors.joining(",\n\t")));
+        }
+
+        available = Stream.concat(module.getContent().stream()
+                                    .map(md -> p.matcher(md.getPath()))
+                                    .filter(m -> m.matches())
+                                    .map(m -> m.group("tag").replaceAll("_", "-")),
+                                Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag)))
+            .distinct()
+            .sorted()
+            .map(IncludeLocalesPlugin::tagToLocale)
+            .collect(Collectors.toList());
+
+        filtered = filterLocales(available);
+
+        try {
+            String value = META_FILES + filtered.stream()
+                .map(s -> includeLocaleFilePatterns(s))
+                .collect(Collectors.joining(","));
+            predicate = new ResourceFilter(Utils.listParser.apply(value), false);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    private String includeLocaleFilePatterns(String tag) {
+        String pTag = tag.replaceAll("-", "_");
+        String files = "";
+        int lastDelimiter = tag.length();
+        String isoSpecial = pTag.matches("^(he|yi|id).*") ?
+                            pTag.replaceFirst("he", "iw")
+                                .replaceFirst("yi", "ji")
+                                .replaceFirst("id", "in") : "";
+
+        // Add tag patterns including parents
+        while (true) {
+            pTag = pTag.substring(0, lastDelimiter);
+            files += INCLUDE_LOCALE_FILES.replaceAll("%%", pTag);
+
+            if (!isoSpecial.isEmpty()) {
+                isoSpecial = isoSpecial.substring(0, lastDelimiter);
+                files += INCLUDE_LOCALE_FILES.replaceAll("%%", isoSpecial);
+            }
+
+            lastDelimiter = pTag.lastIndexOf('_');
+            if (lastDelimiter == -1) {
+                break;
+            }
+        }
+
+        final String lang = pTag;
+
+        // Add possible special locales of the COMPAT provider
+        files += Set.of(jaJPJPTag, noNONYTag, thTHTHTag).stream()
+            .filter(stag -> lang.equals(stag.substring(0,2)))
+            .map(t -> INCLUDE_LOCALE_FILES.replaceAll("%%", t.replaceAll("-", "_")))
+            .collect(Collectors.joining(","));
+
+        // Add possible UN.M49 files (unconditional for now) for each language
+        files += INCLUDE_LOCALE_FILES.replaceAll("%%", lang + "_[0-9]{3}");
+        if (!isoSpecial.isEmpty()) {
+            files += INCLUDE_LOCALE_FILES.replaceAll("%%", isoSpecial + "_[0-9]{3}");
+        }
+
+        // Add Thai BreakIterator related files
+        if (lang.equals("th")) {
+            files += "*sun/text/resources/thai_dict," +
+                     "*sun/text/resources/[^\\/]+_th,";
+        }
+
+        // Add Taiwan resource bundles for Hong Kong
+        if (tag.startsWith("zh-HK")) {
+            files += INCLUDE_LOCALE_FILES.replaceAll("%%", "zh_TW");
+        }
+
+        return files;
+    }
+
+    private boolean stripUnsupportedLocales(byte[] bytes, ClassReader cr) {
+        char[] buf = new char[cr.getMaxStringLength()];
+        boolean[] modified = new boolean[1];
+
+        IntStream.range(1, cr.getItemCount())
+            .map(item -> cr.getItem(item))
+            .forEach(itemIndex -> {
+                if (bytes[itemIndex - 1] == 1 &&         // UTF-8
+                    bytes[itemIndex + 2] == (byte)' ') { // fast check for leading space
+                    int length = cr.readUnsignedShort(itemIndex);
+                    byte[] b = new byte[length];
+                    System.arraycopy(bytes, itemIndex + 2, b, 0, length);
+                    if (filterOutUnsupportedTags(b)) {
+                        // copy back
+                        System.arraycopy(b, 0, bytes, itemIndex + 2, length);
+                        modified[0] = true;
+                    }
+                }
+            });
+
+        return modified[0];
+    }
+
+    private boolean filterOutUnsupportedTags(byte[] b) {
+        List<Locale> locales;
+
+        try {
+            locales = Arrays.asList(new String(b).split(" ")).stream()
+                .filter(tag -> !tag.isEmpty())
+                .map(IncludeLocalesPlugin::tagToLocale)
+                .collect(Collectors.toList());
+        } catch (IllformedLocaleException ile) {
+            // Seems not an available locales string literal.
+            return false;
+        }
+
+        byte[] filteredBytes = filterLocales(locales).stream()
+            .collect(Collectors.joining(" "))
+            .getBytes();
+        System.arraycopy(filteredBytes, 0, b, 0, filteredBytes.length);
+        Arrays.fill(b, filteredBytes.length, b.length, (byte)' ');
+        return true;
+    }
+
+    private List<String> filterLocales(List<Locale> locales) {
+        List<String> ret =
+            Locale.filter(priorityList, locales, Locale.FilteringMode.EXTENDED_FILTERING).stream()
+                .map(loc ->
+                    // Locale.filter() does not preserve the case, which is
+                    // significant for "variant" equality. Retrieve the original
+                    // locales from the pre-filtered list.
+                    locales.stream()
+                        .filter(l -> l.toString().equalsIgnoreCase(loc.toString()))
+                        .findAny()
+                        .orElse(Locale.ROOT)
+                        .toLanguageTag())
+                .collect(Collectors.toList());
+
+        // no-NO-NY.toLanguageTag() returns "nn-NO", so specially handle it here
+        if (ret.contains("no-NO")) {
+            ret.add(noNONYTag);
+        }
+
+        return ret;
+    }
+
+    private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder();
+    private static Locale tagToLocale(String tag) {
+        // ISO3166 compatibility
+        tag = tag.replaceFirst("^iw", "he").replaceFirst("^ji", "yi").replaceFirst("^in", "id");
+
+        switch (tag) {
+            case jaJPJPTag:
+                return jaJPJP;
+            case noNONYTag:
+                return noNONY;
+            case thTHTHTag:
+                return thTHTH;
+            default:
+                LOCALE_BUILDER.clear();
+                LOCALE_BUILDER.setLanguageTag(tag);
+                return LOCALE_BUILDER.build();
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java
new file mode 100644
index 0000000..bd0a9a7
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.optim.ForNameFolding;
+import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
+import jdk.tools.jlink.plugin.PluginException;
+
+/**
+ *
+ * Optimize Classes following various strategies. Strategies are implementation
+ * of <code>ClassOptimizer</code> and <code>MethodOptimizer</code>.
+ */
+public final class OptimizationPlugin extends AsmPlugin {
+
+    public static final String NAME = "class-optim";
+    public static final String LOG  = "log";
+    public static final String ALL = "all";
+    public static final String FORNAME_REMOVAL = "forName-folding";
+
+    /**
+     * Default resolver. A resolver that retrieve types that are in an
+     * accessible package, are public or are located in the same package as the
+     * caller.
+     */
+    private static final class DefaultTypeResolver implements TypeResolver {
+
+        private final Set<String> packages;
+        private final AsmPools pools;
+
+        DefaultTypeResolver(AsmPools pools, AsmModulePool modulePool) {
+            Objects.requireNonNull(pools);
+            Objects.requireNonNull(modulePool);
+            this.pools = pools;
+            packages = pools.getGlobalPool().getAccessiblePackages(modulePool.getModuleName());
+        }
+
+        @Override
+        public ClassReader resolve(ClassNode cn, MethodNode mn, String type) {
+            int classIndex = cn.name.lastIndexOf("/");
+            String callerPkg = classIndex == -1 ? ""
+                    : cn.name.substring(0, classIndex);
+            int typeClassIndex = type.lastIndexOf("/");
+            String pkg = typeClassIndex == - 1 ? ""
+                    : type.substring(0, typeClassIndex);
+            ClassReader reader = null;
+            if (packages.contains(pkg) || pkg.equals(callerPkg)) {
+                ClassReader r = pools.getGlobalPool().getClassReader(type);
+                if (r != null) {
+                    // if not private
+                    if ((r.getAccess() & Opcodes.ACC_PRIVATE)
+                            != Opcodes.ACC_PRIVATE) {
+                        // public
+                        if (((r.getAccess() & Opcodes.ACC_PUBLIC)
+                                == Opcodes.ACC_PUBLIC)) {
+                            reader = r;
+                        } else if (pkg.equals(callerPkg)) {
+                            reader = r;
+                        }
+                    }
+                }
+            }
+            return reader;
+        }
+    }
+
+    public interface Optimizer {
+
+        void close() throws IOException;
+    }
+
+    public interface ClassOptimizer extends Optimizer {
+
+        boolean optimize(Consumer<String> logger, AsmPools pools,
+                AsmModulePool modulePool,
+                ClassNode cn) throws Exception;
+    }
+
+    public interface MethodOptimizer extends Optimizer {
+
+        boolean optimize(Consumer<String> logger, AsmPools pools,
+                AsmModulePool modulePool,
+                ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception;
+    }
+
+    private List<Optimizer> optimizers = new ArrayList<>();
+
+    private OutputStream stream;
+    private int numMethods;
+
+    private void log(String content) {
+        if (stream != null) {
+            try {
+                content = content + "\n";
+                stream.write(content.getBytes(StandardCharsets.UTF_8));
+            } catch (IOException ex) {
+                System.err.println(ex);
+            }
+        }
+    }
+
+    private void close() throws IOException {
+        log("Num analyzed methods " + numMethods);
+
+        for (Optimizer optimizer : optimizers) {
+            try {
+                optimizer.close();
+            } catch (IOException ex) {
+                System.err.println("Error closing optimizer " + ex);
+            }
+        }
+        if (stream != null) {
+            stream.close();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(AsmPools pools) {
+        try {
+            for (AsmModulePool p : pools.getModulePools()) {
+                DefaultTypeResolver resolver = new DefaultTypeResolver(pools, p);
+                p.visitClassReaders((reader) -> {
+                    ClassWriter w = null;
+                    try {
+                        w = optimize(pools, p, reader, resolver);
+                    } catch (IOException ex) {
+                        throw new PluginException("Problem optimizing "
+                                + reader.getClassName(), ex);
+                    }
+                    return w;
+                });
+            }
+        } finally {
+            try {
+                close();
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+    }
+
+    private ClassWriter optimize(AsmPools pools, AsmModulePool modulePool,
+            ClassReader reader, TypeResolver resolver)
+            throws IOException {
+        ClassNode cn = new ClassNode();
+        ClassWriter writer = null;
+        if ((reader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
+            reader.accept(cn, ClassReader.EXPAND_FRAMES);
+            boolean optimized = false;
+            for (Optimizer optimizer : optimizers) {
+                if (optimizer instanceof ClassOptimizer) {
+                    try {
+                        boolean optim = ((ClassOptimizer) optimizer).
+                                optimize(this::log, pools, modulePool, cn);
+                        if (optim) {
+                            optimized = true;
+                        }
+                    } catch (Throwable ex) {
+                        throw new PluginException("Exception optimizing "
+                                + reader.getClassName(), ex);
+                    }
+                } else {
+                    MethodOptimizer moptimizer = (MethodOptimizer) optimizer;
+                    for (MethodNode m : cn.methods) {
+                        if ((m.access & Opcodes.ACC_ABSTRACT) == 0
+                                && (m.access & Opcodes.ACC_NATIVE) == 0) {
+                            numMethods += 1;
+                            try {
+                                boolean optim = moptimizer.
+                                        optimize(this::log, pools, modulePool, cn,
+                                                m, resolver);
+                                if (optim) {
+                                    optimized = true;
+                                }
+                            } catch (Throwable ex) {
+                                throw new PluginException("Exception optimizing "
+                                        + reader.getClassName() + "." + m.name, ex);
+                            }
+
+                        }
+                    }
+                }
+            }
+
+            if (optimized) {
+                writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+                try {
+                    // add a validation layer in between to check for class vallidity
+                    CheckClassAdapter ca = new CheckClassAdapter(writer);
+                    cn.accept(ca);
+                } catch (Exception ex) {
+                    throw new PluginException("Exception optimizing class " + cn.name, ex);
+                }
+            }
+        }
+        return writer;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        String strategies = config.get(NAME);
+        String[] arr = strategies.split(",");
+        for (String s : arr) {
+            if (s.equals(ALL)) {
+                optimizers.clear();
+                optimizers.add(new ForNameFolding());
+                break;
+            } else if (s.equals(FORNAME_REMOVAL)) {
+                optimizers.add(new ForNameFolding());
+            } else {
+                throw new PluginException("Unknown optimization");
+            }
+        }
+        String f = config.get(LOG);
+        if (f != null) {
+            try {
+                stream = new FileOutputStream(f);
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.TRANSFORMER);
+        return Collections.unmodifiableSet(set);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/PluginsResourceBundle.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/PluginsResourceBundle.java
new file mode 100644
index 0000000..64e9d1e
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/PluginsResourceBundle.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public final class PluginsResourceBundle {
+
+    static final String DESCRIPTION = "description";
+    static final String ARGUMENT = "argument";
+    private static final ResourceBundle pluginsBundle;
+
+    static {
+        Locale locale = Locale.getDefault();
+        try {
+            pluginsBundle = ResourceBundle.getBundle("jdk.tools.jlink."
+                    + "resources.plugins", locale);
+        } catch (MissingResourceException e) {
+            throw new InternalError("Cannot find jlink resource bundle for "
+                    + "locale " + locale);
+        }
+    }
+
+    private PluginsResourceBundle() {
+    }
+
+    public static String getArgument(String name, Object... args) {
+        return getMessage(name + "." + ARGUMENT, args);
+    }
+
+    public static String getDescription(String name) {
+        return getMessage(name + "." + DESCRIPTION, name);
+    }
+
+    public static String getOption(String name, String option) {
+        return getMessage(name + "." + option);
+    }
+
+    public static String getMessage(String key, Object... args) throws MissingResourceException {
+        String val = pluginsBundle.getString(key);
+        return MessageFormat.format(val, args);
+    }
+}
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
new file mode 100644
index 0000000..bbc7428
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.lang.module.ModuleDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Properties;
+
+import jdk.tools.jlink.internal.Utils;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.PluginContext;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+
+/**
+ * This plugin adds/deletes information for 'release' file.
+ */
+public final class ReleaseInfoPlugin implements PostProcessorPlugin {
+    // option name
+    public static final String NAME = "release-info";
+    public static final String KEYS = "keys";
+
+    @Override
+    public Set<PluginType> getType() {
+        return Collections.singleton(CATEGORY.PROCESSOR);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public Set<STATE> getState() {
+        return EnumSet.of(STATE.FUNCTIONAL);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+        return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config, PluginContext ctx) {
+        Properties release = ctx != null? ctx.getReleaseProperties() : null;
+        if (release != null) {
+            String operation = config.get(NAME);
+            switch (operation) {
+                case "add": {
+                    // leave it to open-ended! source, java_version, java_full_version
+                    // can be passed via this option like:
+                    //
+                    //     --release-info add:build_type=fastdebug,source=openjdk,java_version=9
+                    // and put whatever value that was passed in command line.
+
+                    config.keySet().stream().
+                        filter(s -> !NAME.equals(s)).
+                        forEach(s -> release.put(s, config.get(s)));
+                }
+                break;
+
+                case "del": {
+                    // --release-info del:keys=openjdk,java_version
+                    String[] keys = Utils.listParser.apply(config.get(KEYS));
+                    for (String k : keys) {
+                        release.remove(k);
+                    }
+                }
+                break;
+
+                default: {
+                    // --release-info <file>
+                    try (FileInputStream fis = new FileInputStream(operation)) {
+                        release.load(fis);
+                    } catch (IOException exp) {
+                        throw new RuntimeException(exp);
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    @Override
+    public List<String> process(ExecutableImage image) {
+        // Nothing to do! Release info copied already during configure!
+        return Collections.emptyList();
+    }
+}
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
new file mode 100644
index 0000000..10c9d32
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * Filter in or out a resource
+ */
+public class ResourceFilter implements Predicate<String> {
+
+    private final Pattern inPatterns;
+    private final Pattern outPatterns;
+
+    static final String NEG = "^";
+
+    public ResourceFilter(String[] patterns) throws IOException {
+        this(patterns, false);
+    }
+
+    public ResourceFilter(String[] patterns, boolean negateAll) throws IOException {
+
+        // Get the patterns from a file
+        if (patterns != null && patterns.length == 1) {
+            String filePath = patterns[0];
+            File f = new File(filePath);
+            if (f.exists()) {
+                List<String> pats;
+                try (FileInputStream fis = new FileInputStream(f);
+                        InputStreamReader ins = new InputStreamReader(fis,
+                                StandardCharsets.UTF_8);
+                        BufferedReader reader = new BufferedReader(ins)) {
+                    pats = reader.lines().collect(Collectors.toList());
+                }
+                patterns = new String[pats.size()];
+                pats.toArray(patterns);
+            }
+        }
+
+        if (patterns != null && negateAll) {
+            String[] excluded = new String[patterns.length];
+            for (int i = 0; i < patterns.length; i++) {
+                excluded[i] = ResourceFilter.NEG + patterns[i];
+            }
+            patterns = excluded;
+        }
+
+        StringBuilder inPatternsBuilder = new StringBuilder();
+        StringBuilder outPatternsBuilder = new StringBuilder();
+        if (patterns != null) {
+            for (int i = 0; i < patterns.length; i++) {
+                String p = patterns[i];
+                p = p.replaceAll(" ", "");
+                StringBuilder builder = p.startsWith(NEG)
+                        ? outPatternsBuilder : inPatternsBuilder;
+                String pat = p.startsWith(NEG) ? p.substring(NEG.length()) : p;
+                builder.append(escape(pat));
+                if (i < patterns.length - 1) {
+                    builder.append("|");
+                }
+            }
+        }
+        this.inPatterns = inPatternsBuilder.length() == 0 ? null
+                : Pattern.compile(inPatternsBuilder.toString());
+        this.outPatterns = outPatternsBuilder.length() == 0 ? null
+                : Pattern.compile(outPatternsBuilder.toString());
+    }
+
+    public static String escape(String s) {
+        s = s.replaceAll(" ", "");
+        s = s.replaceAll("\\$", Matcher.quoteReplacement("\\$"));
+        s = s.replaceAll("\\.", Matcher.quoteReplacement("\\."));
+        s = s.replaceAll("\\*", ".+");
+        return s;
+    }
+
+    private boolean accept(String path) {
+        if (outPatterns != null) {
+            Matcher mout = outPatterns.matcher(path);
+            if (mout.matches()) {
+                //System.out.println("Excluding file " + resource.getPath());
+                return false;
+            }
+        }
+        boolean accepted = false;
+        // If the inPatterns is null, means that all resources are accepted.
+        if (inPatterns == null) {
+            accepted = true;
+        } else {
+            Matcher m = inPatterns.matcher(path);
+            if (m.matches()) {
+                //System.out.println("Including file " + resource.getPath());
+                accepted = true;
+            }
+        }
+        return accepted;
+    }
+
+    @Override
+    public boolean test(String path) {
+        return accept(path);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SortResourcesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SortResourcesPlugin.java
new file mode 100644
index 0000000..388bfae
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SortResourcesPlugin.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * Sort Resources plugin
+ */
+public final class SortResourcesPlugin implements TransformerPlugin {
+
+    public static final String NAME = "sort-resources";
+    private final List<Pattern> filters = new ArrayList<>();
+    private List<String> orderedPaths;
+    private boolean isFile;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    static class SortWrapper {
+
+        private final ModuleData resource;
+        private final int ordinal;
+
+        SortWrapper(ModuleData resource, int ordinal) {
+            this.resource = resource;
+            this.ordinal = ordinal;
+        }
+
+        ModuleData getResource() {
+            return resource;
+        }
+
+        String getPath() {
+            return resource.getPath();
+        }
+
+        int getOrdinal() {
+            return ordinal;
+        }
+    }
+
+    private int getPatternOrdinal(String path) {
+        int ordinal = -1;
+        for (int i = 0; i < filters.size(); i++) {
+            Matcher m = filters.get(i).matcher(path);
+            if (m.matches()) {
+                ordinal = i;
+                break;
+            }
+        }
+        return ordinal;
+    }
+
+    private int getFileOrdinal(String path) {
+        return orderedPaths.indexOf(path);
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.getContent().stream()
+                .filter(w -> w.getType().equals(ModuleDataType.CLASS_OR_RESOURCE))
+                .map((r) -> new SortWrapper(r, isFile
+                        ? getFileOrdinal(r.getPath())
+                        : getPatternOrdinal(r.getPath())))
+                .sorted((sw1, sw2) -> {
+                    int ordinal1 = sw1.getOrdinal();
+                    int ordinal2 = sw2.getOrdinal();
+
+                    if (ordinal1 >= 0) {
+                        if (ordinal2 >= 0) {
+                            return ordinal1 - ordinal2;
+                        } else {
+                            return -1;
+                        }
+                    } else if (ordinal2 >= 0) {
+                        return 1;
+                    }
+
+                    return sw1.getPath().compareTo(sw2.getPath());
+                }).forEach((sw) -> {
+            try {
+                out.add(sw.getResource());
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        });
+        in.getContent().stream()
+                .filter(m -> !m.getType().equals(ModuleDataType.CLASS_OR_RESOURCE))
+                .forEach((m) -> {
+                    try {
+                        out.add(m);
+                    } catch (Exception ex) {
+                        throw new RuntimeException(ex);
+                    }
+                });
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.SORTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        String val = config.get(NAME);
+        try {
+            String[] patterns = Utils.listParser.apply(val);
+            boolean isf = false;
+            List<String> paths = null;
+            if (patterns != null) {
+                if (patterns.length == 1) {
+                    String filePath = patterns[0];
+                    File f = new File(filePath);
+                    if (f.exists()) {
+                        isf = true;
+                        try (FileInputStream fis = new FileInputStream(f);
+                                InputStreamReader ins
+                                = new InputStreamReader(fis, StandardCharsets.UTF_8);
+                                BufferedReader reader = new BufferedReader(ins)) {
+                            paths = reader.lines().collect(Collectors.toList());
+                        }
+                    }
+                }
+                if (!isf) {
+                    for (String p : patterns) {
+                        p = p.replaceAll(" ", "");
+                        Pattern pattern = Pattern.compile(ResourceFilter.escape(p));
+                        filters.add(pattern);
+                    }
+                }
+            }
+            orderedPaths = paths;
+            isFile = isf;
+        } catch (IOException ex) {
+            throw new PluginException(ex);
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
new file mode 100644
index 0000000..a4aa8f9
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import com.sun.tools.classfile.Annotation;
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Field;
+import com.sun.tools.classfile.LocalVariableTable_attribute;
+import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
+import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
+import com.sun.tools.classfile.Signature_attribute;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import jdk.internal.jimage.decompressor.CompressIndexes;
+import jdk.internal.jimage.decompressor.SignatureParser;
+import jdk.internal.jimage.decompressor.StringSharingDecompressor;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.internal.ResourcePrevisitor;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * A Plugin that stores the image classes constant pool UTF_8 entries into the
+ * Image StringsTable.
+ */
+public class StringSharingPlugin implements TransformerPlugin, ResourcePrevisitor {
+
+    public static final String NAME = "compact-cp";
+
+    private static final int[] SIZES;
+
+    static {
+        SIZES = StringSharingDecompressor.getSizes();
+    }
+
+    private static final class CompactCPHelper {
+
+        private static final class DescriptorsScanner {
+
+            private final ClassFile cf;
+
+            private DescriptorsScanner(ClassFile cf) {
+                this.cf = cf;
+            }
+
+            private Set<Integer> scan() throws Exception {
+                Set<Integer> utf8Descriptors = new HashSet<>();
+                scanConstantPool(utf8Descriptors);
+
+                scanFields(utf8Descriptors);
+
+                scanMethods(utf8Descriptors);
+
+                scanAttributes(cf.attributes, utf8Descriptors);
+
+                return utf8Descriptors;
+            }
+
+            private void scanAttributes(Attributes attributes,
+                    Set<Integer> utf8Descriptors) throws Exception {
+                for (Attribute a : attributes) {
+                    if (a instanceof Signature_attribute) {
+                        Signature_attribute sig = (Signature_attribute) a;
+                        utf8Descriptors.add(sig.signature_index);
+                    } else if (a instanceof RuntimeVisibleAnnotations_attribute) {
+                        RuntimeVisibleAnnotations_attribute an
+                                = (RuntimeVisibleAnnotations_attribute) a;
+                        for (Annotation annotation : an.annotations) {
+                            scanAnnotation(annotation, utf8Descriptors);
+                        }
+                    } else if (a instanceof RuntimeInvisibleAnnotations_attribute) {
+                        RuntimeInvisibleAnnotations_attribute an
+                                = (RuntimeInvisibleAnnotations_attribute) a;
+                        for (Annotation annotation : an.annotations) {
+                            scanAnnotation(annotation, utf8Descriptors);
+                        }
+                    } else if (a instanceof RuntimeParameterAnnotations_attribute) {
+                        RuntimeParameterAnnotations_attribute rap
+                                = (RuntimeParameterAnnotations_attribute) a;
+                        for (Annotation[] arr : rap.parameter_annotations) {
+                            for (Annotation an : arr) {
+                                scanAnnotation(an, utf8Descriptors);
+                            }
+                        }
+                    } else if (a instanceof LocalVariableTable_attribute) {
+                        LocalVariableTable_attribute lvt
+                                = (LocalVariableTable_attribute) a;
+                        for (LocalVariableTable_attribute.Entry entry
+                                : lvt.local_variable_table) {
+                            utf8Descriptors.add(entry.descriptor_index);
+                        }
+                    } else if (a instanceof LocalVariableTypeTable_attribute) {
+                        LocalVariableTypeTable_attribute lvt
+                                = (LocalVariableTypeTable_attribute) a;
+                        for (LocalVariableTypeTable_attribute.Entry entry
+                                : lvt.local_variable_table) {
+                            utf8Descriptors.add(entry.signature_index);
+                        }
+                    }
+                }
+            }
+
+            private void scanAnnotation(Annotation annotation,
+                    Set<Integer> utf8Descriptors) throws Exception {
+                utf8Descriptors.add(annotation.type_index);
+                for (Annotation.element_value_pair evp : annotation.element_value_pairs) {
+                    utf8Descriptors.add(evp.element_name_index);
+                    scanElementValue(evp.value, utf8Descriptors);
+                }
+            }
+
+            private void scanElementValue(Annotation.element_value value,
+                    Set<Integer> utf8Descriptors) throws Exception {
+                if (value instanceof Annotation.Enum_element_value) {
+                    Annotation.Enum_element_value eev
+                            = (Annotation.Enum_element_value) value;
+                    utf8Descriptors.add(eev.type_name_index);
+                }
+                if (value instanceof Annotation.Class_element_value) {
+                    Annotation.Class_element_value eev
+                            = (Annotation.Class_element_value) value;
+                    utf8Descriptors.add(eev.class_info_index);
+                }
+                if (value instanceof Annotation.Annotation_element_value) {
+                    Annotation.Annotation_element_value aev
+                            = (Annotation.Annotation_element_value) value;
+                    scanAnnotation(aev.annotation_value, utf8Descriptors);
+                }
+                if (value instanceof Annotation.Array_element_value) {
+                    Annotation.Array_element_value aev
+                            = (Annotation.Array_element_value) value;
+                    for (Annotation.element_value v : aev.values) {
+                        scanElementValue(v, utf8Descriptors);
+                    }
+                }
+            }
+
+            private void scanFields(Set<Integer> utf8Descriptors)
+                    throws Exception {
+                for (Field field : cf.fields) {
+                    int descriptorIndex = field.descriptor.index;
+                    utf8Descriptors.add(descriptorIndex);
+                    scanAttributes(field.attributes, utf8Descriptors);
+                }
+
+            }
+
+            private void scanMethods(Set<Integer> utf8Descriptors)
+                    throws Exception {
+                for (Method m : cf.methods) {
+                    int descriptorIndex = m.descriptor.index;
+                    utf8Descriptors.add(descriptorIndex);
+                    scanAttributes(m.attributes, utf8Descriptors);
+                }
+            }
+
+            private void scanConstantPool(Set<Integer> utf8Descriptors)
+                    throws Exception {
+                for (int i = 1; i < cf.constant_pool.size(); i++) {
+                    try {
+                        ConstantPool.CPInfo info = cf.constant_pool.get(i);
+                        if (info instanceof ConstantPool.CONSTANT_NameAndType_info) {
+                            ConstantPool.CONSTANT_NameAndType_info nameAndType
+                                    = (ConstantPool.CONSTANT_NameAndType_info) info;
+                            utf8Descriptors.add(nameAndType.type_index);
+                        }
+                        if (info instanceof ConstantPool.CONSTANT_MethodType_info) {
+                            ConstantPool.CONSTANT_MethodType_info mt
+                                    = (ConstantPool.CONSTANT_MethodType_info) info;
+                            utf8Descriptors.add(mt.descriptor_index);
+                        }
+
+                        if (info instanceof ConstantPool.CONSTANT_Double_info
+                                || info instanceof ConstantPool.CONSTANT_Long_info) {
+                            i++;
+                        }
+                    } catch (ConstantPool.InvalidIndex ex) {
+                        throw new IOException(ex);
+                    }
+                }
+            }
+        }
+
+        public byte[] transform(ModuleData resource, Pool out,
+                StringTable strings) throws IOException, Exception {
+            byte[] content = resource.getBytes();
+            ClassFile cf;
+            try (InputStream stream = new ByteArrayInputStream(content)) {
+                cf = ClassFile.read(stream);
+            } catch (ConstantPoolException ex) {
+                throw new IOException("Compressor EX " + ex + " for "
+                        + resource.getPath() + " content.length " + content.length, ex);
+            }
+            DescriptorsScanner scanner = new DescriptorsScanner(cf);
+            return optimize(resource, out, strings, scanner.scan(), content);
+        }
+
+        @SuppressWarnings("fallthrough")
+        private byte[] optimize(ModuleData resource, Pool resources,
+                StringTable strings,
+                Set<Integer> descriptorIndexes, byte[] content) throws Exception {
+            DataInputStream stream = new DataInputStream(new ByteArrayInputStream(content));
+            ByteArrayOutputStream outStream = new ByteArrayOutputStream(content.length);
+            DataOutputStream out = new DataOutputStream(outStream);
+            byte[] header = new byte[8]; //magic/4, minor/2, major/2
+            stream.readFully(header);
+            out.write(header);
+            int count = stream.readUnsignedShort();
+            out.writeShort(count);
+            for (int i = 1; i < count; i++) {
+                int tag = stream.readUnsignedByte();
+                byte[] arr;
+                switch (tag) {
+                    case ConstantPool.CONSTANT_Utf8: {
+                        String original = stream.readUTF();
+                        // 2 cases, a Descriptor or a simple String
+                        if (descriptorIndexes.contains(i)) {
+                            SignatureParser.ParseResult parseResult
+                                    = SignatureParser.parseSignatureDescriptor(original);
+                            List<Integer> indexes
+                                    = parseResult.types.stream().map((type) -> {
+                                        return strings.addString(type);
+                                    }).collect(Collectors.toList());
+                            if (!indexes.isEmpty()) {
+                                out.write(StringSharingDecompressor.EXTERNALIZED_STRING_DESCRIPTOR);
+                                int sigIndex = strings.addString(parseResult.formatted);
+                                byte[] compressed
+                                        = CompressIndexes.compress(sigIndex);
+                                out.write(compressed, 0, compressed.length);
+
+                                writeDescriptorReference(out, indexes);
+                                continue;
+                            }
+                        }
+                        // Put all strings in strings table.
+                        writeUTF8Reference(out, strings.addString(original));
+
+                        break;
+                    }
+
+                    case ConstantPool.CONSTANT_Long:
+                    case ConstantPool.CONSTANT_Double: {
+                        i++;
+                    }
+                    default: {
+                        out.write(tag);
+                        int size = SIZES[tag];
+                        arr = new byte[size];
+                        stream.readFully(arr);
+                        out.write(arr);
+                    }
+                }
+            }
+            out.write(content, content.length - stream.available(),
+                    stream.available());
+            out.flush();
+
+            return outStream.toByteArray();
+        }
+
+        private void writeDescriptorReference(DataOutputStream out,
+                List<Integer> indexes) throws IOException {
+            List<byte[]> buffers = new ArrayList<>();
+            int l = 0;
+            for (Integer index : indexes) {
+                byte[] buffer = CompressIndexes.compress(index);
+                l += buffer.length;
+                buffers.add(buffer);
+            }
+            ByteBuffer bb = ByteBuffer.allocate(l);
+            buffers.stream().forEach((buf) -> {
+                bb.put(buf);
+            });
+            byte[] compressed_indices = bb.array();
+            byte[] compressed_size = CompressIndexes.
+                    compress(compressed_indices.length);
+            out.write(compressed_size, 0, compressed_size.length);
+            out.write(compressed_indices, 0, compressed_indices.length);
+        }
+
+        private void writeUTF8Reference(DataOutputStream out, int index)
+                throws IOException {
+            out.write(StringSharingDecompressor.EXTERNALIZED_STRING);
+            byte[] compressed = CompressIndexes.compress(index);
+            out.write(compressed, 0, compressed.length);
+        }
+    }
+
+    private Predicate<String> predicate;
+
+    public StringSharingPlugin() throws IOException {
+        this(new String[0]);
+    }
+
+    StringSharingPlugin(String[] patterns) throws IOException {
+        this(new ResourceFilter(patterns));
+    }
+
+    StringSharingPlugin(Predicate<String> predicate) {
+        this.predicate = predicate;
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.COMPRESSOR);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public void visit(Pool in, Pool result) {
+        CompactCPHelper visit = new CompactCPHelper();
+        in.visit((resource) -> {
+            ModuleData res = resource;
+            if (predicate.test(resource.getPath()) && resource.getPath().endsWith(".class")) {
+                byte[] compressed = null;
+                try {
+                    compressed = visit.transform(resource, result, ((PoolImpl) in).getStringTable());
+                } catch (Exception ex) {
+                    throw new PluginException(ex);
+                }
+                res = PoolImpl.newCompressedResource(resource,
+                        ByteBuffer.wrap(compressed), getName(), null,
+                        ((PoolImpl) in).getStringTable(), in.getByteOrder());
+            }
+            return res;
+        }, result);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return true;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String val = config.get(NAME);
+            predicate = new ResourceFilter(Utils.listParser.apply(val));
+        } catch (IOException ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+    @Override
+    public void previsit(Pool resources, StringTable strings) {
+        CompactCPHelper preVisit = new CompactCPHelper();
+        for (ModuleData resource : resources.getContent()) {
+            if (resource.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)
+                    && resource.getPath().endsWith(".class") && predicate.test(resource.getPath())) {
+                try {
+                    preVisit.transform(resource, null, strings);
+                } catch (Exception ex) {
+                    throw new PluginException(ex);
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
new file mode 100644
index 0000000..ae92795
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ *
+ * Strip debug attributes plugin
+ */
+public final class StripDebugPlugin implements TransformerPlugin {
+    private static final String[] PATTERNS = {"*.diz"};
+    public static final String NAME = "strip-debug";
+    private final Predicate<String> predicate;
+    public StripDebugPlugin() {
+        try {
+            predicate = new ResourceFilter(PATTERNS);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.TRANSFORMER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        //remove *.diz files as well as debug attributes.
+        in.visit((resource) -> {
+            ModuleData res = resource;
+            if (resource.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)) {
+                String path = resource.getPath();
+                if (path.endsWith(".class")) {
+                    if (path.endsWith("module-info.class")) {
+                        // XXX. Do we have debug info? Is Asm ready for module-info?
+                    } else {
+                        ClassReader reader = new ClassReader(resource.getBytes());
+                        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+                        reader.accept(writer, ClassReader.SKIP_DEBUG);
+                        byte[] content = writer.toByteArray();
+                        res = Pool.newResource(path, new ByteArrayInputStream(content), content.length);
+                    }
+                }
+            } else if (predicate.test(res.getPath())) {
+                res = null;
+            }
+            return res;
+        }, out);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
new file mode 100644
index 0000000..dc64582
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ *
+ * Strip Native Commands plugin
+ */
+public final class StripNativeCommandsPlugin implements TransformerPlugin {
+
+    public static final String NAME = "strip-native-commands";
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.FILTER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((file) -> {
+            return file.getType() == Pool.ModuleDataType.NATIVE_CMD ? null : file;
+        }, out);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+}
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
new file mode 100644
index 0000000..edf6475
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleDescriptor.*;
+import java.lang.module.ModuleDescriptor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import jdk.internal.module.Checks;
+import jdk.internal.module.ModuleInfoExtender;
+import jdk.internal.module.SystemModules;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ * Jlink plugin to reconstitute module descriptors for installed modules.
+ * It will extend module-info.class with ConcealedPackages attribute,
+ * if not present. It also determines the number of packages of
+ * the boot layer at link time.
+ *
+ * This plugin will override jdk.internal.module.SystemModules class
+ *
+ * @see java.lang.module.SystemModuleFinder
+ * @see SystemModules
+ */
+public final class SystemModuleDescriptorPlugin implements TransformerPlugin {
+    // 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 boolean enabled;
+
+    public SystemModuleDescriptorPlugin() {
+        this.enabled = true;
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        return Collections.singleton(CATEGORY.TRANSFORMER);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return DESCRIPTION;
+    }
+
+    @Override
+    public Set<STATE> getState() {
+        return enabled ? EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL)
+                       : EnumSet.of(STATE.DISABLED);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        if (config.containsKey(NAME)) {
+            enabled = false;
+        }
+    }
+
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        if (!enabled) {
+            throw new PluginException(NAME + " was set");
+        }
+
+        Builder builder = new Builder();
+
+        // generate the byte code to create ModuleDescriptors
+        // skip parsing module-info.class and skip name check
+        for (Pool.Module module : in.getModules()) {
+            Pool.ModuleData data = module.get("module-info.class");
+            if (data == null) {
+                // automatic module not supported yet
+                throw new PluginException("module-info.class not found for " + module.getName() + " module");
+            }
+            assert module.getName().equals(data.getModule());
+            try {
+                ByteArrayInputStream bain = new ByteArrayInputStream(data.getBytes());
+                ModuleDescriptor md = ModuleDescriptor.read(bain);
+                validateNames(md);
+
+                Builder.ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages());
+                if (md.conceals().isEmpty() &&
+                        (md.exports().size() + md.conceals().size()) != module.getAllPackages().size()) {
+                    // add ConcealedPackages attribute if not exist
+                    bain.reset();
+                    ModuleInfoRewriter minfoWriter = new ModuleInfoRewriter(bain, mbuilder.conceals());
+                    // replace with the overridden version
+                    data = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(),
+                                               minfoWriter.stream(), minfoWriter.size());
+                }
+                out.add(data);
+            } catch (IOException e) {
+                throw new PluginException(e);
+            }
+
+        }
+
+        // Generate the new class
+        ClassWriter cwriter = builder.build();
+        for (Pool.ModuleData data : in.getContent()) {
+            if (data.getPath().endsWith("module-info.class"))
+                continue;
+
+            if (builder.isOverriddenClass(data.getPath())) {
+                byte[] bytes = cwriter.toByteArray();
+                Pool.ModuleData ndata = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(),
+                                                            new ByteArrayInputStream(bytes), bytes.length);
+                out.add(ndata);
+            } else {
+                out.add(data);
+            }
+        }
+    }
+
+    /*
+     * Add ConcealedPackages attribute
+     */
+    class ModuleInfoRewriter extends ByteArrayOutputStream {
+        final ModuleInfoExtender extender;
+        ModuleInfoRewriter(InputStream in, Set<String> conceals) throws IOException {
+            this.extender = ModuleInfoExtender.newExtender(in);
+            // Add ConcealedPackages attribute
+            this.extender.conceals(conceals);
+            this.extender.write(this);
+        }
+
+        InputStream stream() {
+            return new ByteArrayInputStream(buf);
+        }
+    }
+
+    void validateNames(ModuleDescriptor md) {
+        Checks.requireModuleName(md.name());
+        for (Requires req : md.requires()) {
+            Checks.requireModuleName(req.name());
+        }
+        for (Exports e : md.exports()) {
+            Checks.requirePackageName(e.source());
+            if (e.isQualified())
+               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);
+            Checks.requireServiceTypeName(provides.service());
+            provides.providers().forEach(Checks::requireServiceProviderName);
+        }
+        for (String service : md.uses()) {
+            Checks.requireServiceTypeName(service);
+        }
+        for (String pn : md.conceals()) {
+            Checks.requirePackageName(pn);
+        }
+    }
+
+    /*
+     * Returns the initial capacity for a new Set or Map of the given size
+     * to avoid resizing.
+     */
+    static final int initialCapacity(int size) {
+        if (size == 0) {
+            return 0;
+        } else {
+            // Adjust to try and get size/capacity as close to the
+            // HashSet/HashMap default load factor without going over.
+            return (int)(Math.ceil((double)size / 0.75));
+        }
+    }
+
+    /**
+     * Builder of a new jdk.internal.module.SystemModules class
+     * to reconstitute ModuleDescriptor of the installed modules.
+     */
+    static class Builder {
+        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;";
+
+        // static variables in SystemModules class
+        private static final String MODULE_NAMES = "MODULE_NAMES";
+        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 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<>();
+
+        // 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<>();
+
+        public Builder() {
+            this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS+ClassWriter.COMPUTE_FRAMES);
+        }
+
+        /*
+         * static initializer initializing the static fields
+         *
+         * static Map<String, ModuleDescriptor> map = new HashMap<>();
+         */
+        private void clinit(int numModules, int numPackages) {
+            cw.visit(Opcodes.V1_8, ACC_PUBLIC+ACC_FINAL+ACC_SUPER, CLASSNAME,
+                    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 int PACKAGES_IN_BOOT_LAYER;
+            cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, PACKAGE_COUNT,
+                    "I", null, numPackages)
+                    .visitEnd();
+
+            this.mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V",
+                    null, null);
+            mv.visitCode();
+
+            // create the MODULE_NAMES array
+            pushInt(numModules);
+            mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+
+            int index = 0;
+            for (ModuleDescriptorBuilder builder : builders) {
+                mv.visitInsn(DUP);       // arrayref
+                pushInt(index++);
+                mv.visitLdcInsn(builder.md.name());      // value
+                mv.visitInsn(AASTORE);
+            }
+
+            mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULE_NAMES,
+                    "[Ljava/lang/String;");
+
+            mv.visitInsn(RETURN);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
+
+        }
+
+        /*
+         * 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.
+         */
+        public ModuleDescriptorBuilder module(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();
+                }
+            }
+
+            // provides
+            for (ModuleDescriptor.Provides p : md.provides().values()) {
+                stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s))
+                          .increment();
+            }
+
+            // uses
+            stringSets.computeIfAbsent(md.uses(), s -> new StringSetBuilder(s))
+                      .increment();
+            return builder;
+        }
+
+        /*
+         * Generate bytecode for SystemModules
+         */
+        public ClassWriter build() {
+            int numModules = builders.size();
+            int numPackages = 0;
+            for (ModuleDescriptorBuilder builder : builders) {
+                numPackages += builder.md.packages().size();
+            }
+
+            this.clinit(numModules, numPackages);
+            this.mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
+                                     "modules", "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
+                                     "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE, null);
+            mv.visitCode();
+            pushInt(numModules);
+            mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor");
+            mv.visitVarInsn(ASTORE, MD_VAR);
+
+            for (ModuleDescriptorBuilder builder : builders) {
+                builder.build();
+            }
+            mv.visitVarInsn(ALOAD, MD_VAR);
+            mv.visitInsn(ARETURN);
+            mv.visitMaxs(0, 0);
+            mv.visitEnd();
+            return cw;
+        }
+
+        public boolean isOverriddenClass(String path) {
+            return path.equals("/java.base/" + CLASSNAME + ".class");
+        }
+
+        void pushInt(int num) {
+            if (num <= 5) {
+                mv.visitInsn(ICONST_0 + num);
+            } else if (num < Byte.MAX_VALUE) {
+                mv.visitIntInsn(BIPUSH, num);
+            } else if (num < Short.MAX_VALUE) {
+                mv.visitIntInsn(SIPUSH, num);
+            } else {
+                throw new IllegalArgumentException("exceed limit: " + num);
+            }
+        }
+
+        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 STRING_SIG = "(Ljava/lang/String;)" + BUILDER_TYPE;
+            static final String STRING_STRING_SIG =
+                "(Ljava/lang/String;Ljava/lang/String;)" + BUILDER_TYPE;
+
+            final ModuleDescriptor md;
+            final Set<String> packages;
+
+            ModuleDescriptorBuilder(ModuleDescriptor md, Set<String> packages) {
+                this.md = md;
+                this.packages = packages;
+            }
+
+            void newBuilder(String name, int reqs, int exports, int provides,
+                            int conceals, 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(conceals));
+                pushInt(initialCapacity(packages));
+                mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "<init>", "(Ljava/lang/String;IIIII)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 oes not have ConcealedPackages attribute
+             */
+            Set<String> conceals() {
+                Set<String> conceals = md.conceals();
+                if (md.conceals().isEmpty() &&
+                        (md.exports().size() + md.conceals().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(),
+                           conceals().size(),
+                           conceals().size() + md.exports().size());
+
+                // 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());
+                    }
+                }
+
+                // exports
+                for (ModuleDescriptor.Exports e : md.exports()) {
+                    if (e.isQualified()) {
+                        exports(e.source(), e.targets());
+                    } else {
+                        exports(e.source());
+                    }
+                }
+
+                // uses
+                uses(md.uses());
+
+                // provides
+                for (ModuleDescriptor.Provides p : md.provides().values()) {
+                    provides(p.service(), p.providers());
+                }
+
+                // concealed packages
+                for (String pn : conceals()) {
+                    conceals(pn);
+                }
+
+                if (md.version().isPresent()) {
+                    version(md.version().get());
+                }
+
+                if (md.mainClass().isPresent()) {
+                    mainClass(md.mainClass().get());
+                }
+
+                putModuleDescriptor();
+            }
+
+            /*
+             * Put ModuleDescriptor into the modules array
+             */
+            void putModuleDescriptor() {
+                mv.visitVarInsn(ALOAD, MD_VAR);
+                pushInt(nextModulesIndex++);
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                    "build", "()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)
+             *
+             * 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;";
+                }
+                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);
+            }
+
+            /*
+             * Invoke Builder.exports(String pn)
+             */
+            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);
+            }
+
+            /*
+             * Invoke Builder.exports(String pn, Set<String> targets)
+             *
+             * Set<String> targets = new HashSet<>();
+             * targets.add(t);
+             * :
+             * :
+             * Builder.exports(pn, targets);
+             */
+            void exports(String pn, Set<String> targets) {
+                int varIndex = stringSets.get(targets).build();
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(pn);
+                mv.visitVarInsn(ALOAD, varIndex);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "exports", STRING_SET_SIG, false);
+                mv.visitInsn(POP);
+            }
+
+            /*
+             * Invokes Builder.uses(Set<String> uses)
+             */
+            void uses(Set<String> uses) {
+                int varIndex = stringSets.get(uses).build();
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitVarInsn(ALOAD, varIndex);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                        "uses", SET_SIG, false);
+                mv.visitInsn(POP);
+            }
+
+            /*
+             * Invoke Builder.provides(String service, Set<String> providers)
+             *
+             * Set<String> providers = new HashSet<>();
+             * providers.add(impl);
+             * :
+             * :
+             * Builder.exports(service, providers);
+             */
+            void provides(String service, Set<String> providers) {
+                int varIndex = stringSets.get(providers).build();
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(service);
+                mv.visitVarInsn(ALOAD, varIndex);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "provides", STRING_SET_SIG, false);
+                mv.visitInsn(POP);
+            }
+
+            /*
+             * Invoke Builder.conceals(String pn)
+             */
+            void conceals(String pn) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(pn);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "conceals", STRING_SIG, false);
+                mv.visitInsn(POP);
+            }
+
+            /*
+             * Invoke Builder.mainClass(String cn)
+             */
+            void mainClass(String cn) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(cn);
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "mainClass", STRING_SIG, false);
+                mv.visitInsn(POP);
+            }
+
+            /*
+             * Invoke Builder.version(Version v);
+             */
+            void version(ModuleDescriptor.Version v) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(v.toString());
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "version", STRING_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.
+         */
+        class StringSetBuilder {
+            final Set<String> names;
+            int refCount;
+            int localVarIndex;
+            StringSetBuilder(Set<String> names) {
+                this.names = names;
+            }
+
+            void increment() {
+                refCount++;
+            }
+
+            /*
+             * Build bytecode for the Set<String> 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() {
+                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++;
+                    if (index < MAX_LOCAL_VARS) {
+                        localVarIndex = index;
+                    } else {
+                        // overflow: disable optimization and keep localVarIndex = 0
+                        index = STRING_SET_VAR;
+                    }
+
+                    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 {
+                        mv.visitTypeInsn(NEW, "java/util/HashSet");
+                        mv.visitInsn(DUP);
+                        pushInt(initialCapacity(names.size()));
+                        mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet",
+                                "<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);
+                        }
+                    }
+                }
+                return index;
+            }
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
new file mode 100644
index 0000000..df66e30
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ZipPlugin.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.zip.Deflater;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.Utils;
+
+/**
+ *
+ * ZIP Compression plugin
+ */
+public final class ZipPlugin implements TransformerPlugin {
+
+    public static final String NAME = "zip";
+    private Predicate<String> predicate;
+
+    public ZipPlugin() {
+
+    }
+
+    ZipPlugin(String[] patterns) throws IOException {
+        this(new ResourceFilter(patterns));
+    }
+
+    ZipPlugin(Predicate<String> predicate) {
+        this.predicate = predicate;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.COMPRESSOR);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return false;
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+        return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+        try {
+            String val = config.get(NAME);
+            predicate = new ResourceFilter(Utils.listParser.apply(val));
+        } catch (IOException ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+    static byte[] compress(byte[] bytesIn) {
+        Deflater deflater = new Deflater();
+        deflater.setInput(bytesIn);
+        ByteArrayOutputStream stream = new ByteArrayOutputStream(bytesIn.length);
+        byte[] buffer = new byte[1024];
+
+        deflater.finish();
+        while (!deflater.finished()) {
+            int count = deflater.deflate(buffer);
+            stream.write(buffer, 0, count);
+        }
+
+        try {
+            stream.close();
+        } catch (IOException ex) {
+            return bytesIn;
+        }
+
+        byte[] bytesOut = stream.toByteArray();
+        deflater.end();
+
+        return bytesOut;
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit((resource) -> {
+            ModuleData res = resource;
+            if (resource.getType().equals(ModuleDataType.CLASS_OR_RESOURCE)
+                    && predicate.test(resource.getPath())) {
+                byte[] compressed;
+                compressed = compress(resource.getBytes());
+                res = PoolImpl.newCompressedResource(resource,
+                        ByteBuffer.wrap(compressed), getName(), null,
+                        ((PoolImpl) in).getStringTable(), in.getByteOrder());
+            }
+            return res;
+        }, out);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java
new file mode 100644
index 0000000..b3dbc37
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.util.Set;
+
+/**
+ * A pool containing all class and resource files.
+ */
+public interface AsmGlobalPool extends AsmPool {
+
+    /**
+     * Associate a package to a module, useful when adding new classes in new
+     * packages. WARNING: In order to properly handle new package and/or new
+     * module, module-info class must be added and/or updated.
+     *
+     * @param pkg The new package, following java binary syntax (/-separated
+     * path name).
+     * @param module An existing or new module.
+     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
+     * exist for this package.
+     */
+    public void addPackageModuleMapping(String pkg, String module);
+
+    /**
+     * Return the set of accessible packages for a given module.
+     *
+     * @param module The module from which packages are accessible.
+     * @return Set of packages or null if the module is not found.
+     */
+    public Set<String> getAccessiblePackages(String module);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java
new file mode 100644
index 0000000..ddd20b5
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.lang.module.ModuleDescriptor;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+
+/**
+ * A pool for a given module
+ */
+public interface AsmModulePool extends AsmPool {
+
+    /**
+     * Associate a package to this module, useful when adding new classes in new
+     * packages. WARNING: In order to properly handle new package and/or new
+     * module, module-info class must be added and/or updated.
+     *
+     * @param pkg The new package, following java binary syntax (/-separated
+     * path name).
+     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
+     * exist for this package.
+     */
+    public void addPackage(String pkg);
+
+    /**
+     * The module name of this pool.
+     * @return The module name;
+     */
+    public String getModuleName();
+
+    /**
+     * Lookup the class in this pool and the required pools. NB: static module
+     * readability can be different at execution time.
+     *
+     * @param binaryName The class to lookup.
+     * @return The reader or null if not found
+     * @throws jdk.tools.jlink.plugins.PluginException
+     */
+    public ClassReader getClassReaderInDependencies(String binaryName);
+
+    /**
+     * Lookup the class in the exported packages of this module. "public
+     * requires" modules are looked up. NB: static module readability can be
+     * different at execution time.
+     *
+     * @param callerModule Name of calling module.
+     * @param binaryName The class to lookup.
+     * @return The reader or null if not found
+     * @throws jdk.tools.jlink.plugins.PluginException
+     */
+    public ClassReader getExportedClassReader(String callerModule,
+            String binaryName);
+
+    /**
+     * The module descriptor.
+     *
+     * @return The module descriptor;
+     */
+    public ModuleDescriptor getDescriptor();
+
+    /**
+     * Retrieve the internal and exported packages.
+     *
+     * @return
+     */
+    public Set<String> getAllPackages();
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java
new file mode 100644
index 0000000..9902959
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.util.Objects;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.internal.PoolImpl;
+
+/**
+ * Extend this class to develop your own plugin in order to transform jimage
+ * resources.
+ *
+ */
+public abstract class AsmPlugin implements TransformerPlugin {
+
+    public AsmPlugin() {
+    }
+
+    @Override
+    public void visit(Pool allContent, Pool outResources) {
+        Objects.requireNonNull(allContent);
+        Objects.requireNonNull(outResources);
+        PoolImpl resources = new PoolImpl(allContent.getByteOrder());
+        for(ModuleData md : allContent.getContent()) {
+            if(md.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) {
+                resources.add(md);
+            } else {
+                outResources.add(md);
+            }
+        }
+        AsmPools pools = new AsmPools(resources);
+        visit(pools);
+        pools.fillOutputResources(outResources);
+    }
+
+    /**
+     * This is the method to implement in order to
+     * apply Asm transformation to jimage contained classes.
+     * @param pools The pool of Asm classes and other resource files.
+     * @param strings To add a string to the jimage strings table.
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public abstract void visit(AsmPools pools);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java
new file mode 100644
index 0000000..9184bb8
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.List;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.tools.jlink.plugin.Pool;
+
+/**
+ * A pool of ClassReader and other resource files.
+ * This class allows to transform and sort classes and resource files.
+ * <p>
+ * Classes in the class pool are named following java binary name specification.
+ * For example, java.lang.Object class is named java/lang/Object
+ * <p>
+ * Module information has been stripped out from class and other resource files
+ * (.properties, binary files, ...).</p>
+ */
+public interface AsmPool {
+
+    /**
+     * A resource that is not a class file.
+     * <p>
+     * The path of a resource is a /-separated path name that identifies the
+     * resource. For example com.foo.bar.Bundle.properties resource name is
+     * com/foo/bar/Bundle.properties </p>
+     * <p>
+     */
+    public class ResourceFile {
+
+        private final String path;
+        private final byte[] content;
+
+        public ResourceFile(String path, byte[] content) {
+            this.path = path;
+            this.content = content;
+        }
+
+        public String getPath() {
+            return path;
+        }
+
+        public byte[] getContent() {
+            return content;
+        }
+    }
+
+    /**
+     * To visit each Class contained in the pool
+     */
+    public interface ClassReaderVisitor {
+
+        /**
+         * Called for each ClassReader located in the pool.
+         *
+         * @param reader A class reader.
+         * @return A writer or null if the class has not been transformed.
+         */
+        public ClassWriter visit(ClassReader reader);
+    }
+
+    /**
+     * To visit each Resource contained in the pool
+     */
+    public interface ResourceFileVisitor {
+
+        /**
+         * Called for each Resource file located in the pool.
+         *
+         * @param reader A resource file.
+         * @return A resource file or null if the resource has not been
+         * transformed.
+         */
+        public ResourceFile visit(ResourceFile reader);
+    }
+
+    /**
+     * Contains the transformed classes. When the jimage file is generated,
+     * transformed classes take precedence on unmodified ones.
+     */
+    public interface WritableClassPool {
+
+        /**
+         * Add a class to the pool, if a class already exists, it is replaced.
+         *
+         * @param writer The class writer.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public void addClass(ClassWriter writer);
+
+        /**
+         * The class will be not added to the jimage file.
+         *
+         * @param className The class name to forget.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public void forgetClass(String className);
+
+        /**
+         * Get a transformed class.
+         *
+         * @param binaryName The java class binary name
+         * @return The ClassReader or null if the class is not found.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public ClassReader getClassReader(String binaryName);
+
+        /**
+         * Get a transformed class.
+         *
+         * @param res A class resource.
+         * @return The ClassReader or null if the class is not found.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public ClassReader getClassReader(Pool.ModuleData res);
+
+        /**
+         * Returns all the classes contained in the writable pool.
+         *
+         * @return The collection of classes.
+         */
+        public Collection<Pool.ModuleData> getClasses();
+    }
+
+    /**
+     * Contains the transformed resources. When the jimage file is generated,
+     * transformed resources take precedence on unmodified ones.
+     */
+    public interface WritableResourcePool {
+
+        /**
+         * Add a resource, if the resource exists, it is replaced.
+         *
+         * @param resFile The resource file to add.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public void addResourceFile(ResourceFile resFile);
+
+        /**
+         * The resource will be not added to the jimage file.
+         *
+         * @param resourceName
+         * @throws jdk.tools.jlink.plugin.PluginException If the resource to
+         * forget doesn't exist or is null.
+         */
+        public void forgetResourceFile(String resourceName);
+
+        /**
+         * Get a transformed resource.
+         *
+         * @param name The java resource name
+         * @return The Resource or null if the resource is not found.
+         */
+        public ResourceFile getResourceFile(String name);
+
+        /**
+         * Get a transformed resource.
+         *
+         * @param res The java resource
+         * @return The Resource or null if the resource is not found.
+         */
+        public ResourceFile getResourceFile(Pool.ModuleData res);
+
+        /**
+         * Returns all the resources contained in the writable pool.
+         *
+         * @return The array of resources.
+         */
+        public Collection<Pool.ModuleData> getResourceFiles();
+    }
+
+    /**
+     * To order the classes and resources within a jimage file.
+     */
+    public interface Sorter {
+
+        /**
+         * @param resources The resources will be added to the jimage following
+         * the order of this ResourcePool.
+         * @return The resource paths ordered in the way to use for storage in the jimage.
+         * @throws jdk.tools.jlink.plugin.PluginException
+         */
+        public List<String> sort(Pool resources);
+    }
+
+    /**
+     * The writable pool used to store transformed resources.
+     *
+     * @return The writable pool.
+     */
+    public WritableClassPool getTransformedClasses();
+
+    /**
+     * The writable pool used to store transformed resource files.
+     *
+     * @return The writable pool.
+     */
+    public WritableResourcePool getTransformedResourceFiles();
+
+    /**
+     * Set a sorter instance to sort all files. If no sorter is set, then input
+     * Resources will be added in the order they have been received followed by
+     * newly added resources.
+     *
+     * @param sorter
+     */
+    public void setSorter(Sorter sorter);
+
+    /**
+     * Returns the classes contained in the pool.
+     *
+     * @return The classes.
+     */
+    public Collection<Pool.ModuleData> getClasses();
+
+    /**
+     * Returns the resources contained in the pool. Resources are all the file
+     * that are not classes (eg: properties file, binary files, ...)
+     *
+     * @return The array of resource files.
+     */
+    public Collection<Pool.ModuleData> getResourceFiles();
+
+    /**
+     * Retrieves a resource based on the binary name. This name doesn't contain
+     * the module name.
+     * <b>NB:</b> When dealing with resources that have the same name in various
+     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
+     * referenced from this <code>AsmClassPool</code>.
+     *
+     * @param binaryName Name of a Java resource or null if the resource doesn't
+     * exist.
+     * @return
+     */
+    public ResourceFile getResourceFile(String binaryName);
+
+    /**
+     * Retrieves a resource for the passed resource.
+     *
+     * @param res The resource
+     * @return The resource file or null if it doesn't exist.
+     */
+    public ResourceFile getResourceFile(Pool.ModuleData res);
+
+    /**
+     * Retrieve a ClassReader from the pool.
+     *
+     * @param binaryName Class binary name
+     * @return A reader or null if the class is unknown
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public ClassReader getClassReader(String binaryName);
+
+    /**
+     * Retrieve a ClassReader from the pool.
+     *
+     * @param res A resource.
+     * @return A reader or null if the class is unknown
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public ClassReader getClassReader(Pool.ModuleData res);
+
+    /**
+     * To visit the set of ClassReaders.
+     *
+     * @param visitor The visitor.
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public void visitClassReaders(ClassReaderVisitor visitor);
+
+    /**
+     * To visit the set of ClassReaders.
+     *
+     * @param visitor The visitor.
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public void visitResourceFiles(ResourceFileVisitor visitor);
+
+    /**
+     * Returns the pool of all the resources (transformed and unmodified).
+     * The input resources are replaced by the transformed ones.
+     * If a sorter has been set, it is used to sort the returned resources.
+     *
+     * @param output The pool used to fill the jimage.
+     * @throws jdk.tools.jlink.plugin.PluginException
+     */
+    public void fillOutputResources(Pool output);
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
new file mode 100644
index 0000000..cb838d1
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.tools.jlink.internal.ImageFileCreator;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+/**
+ * A pool of ClassReader and other resource files. This class allows to
+ * transform and sort classes and resource files.
+ * <p>
+ * Classes in the class pool are named following java binary name specification.
+ * For example, java.lang.Object class is named java/lang/Object
+ * <p>
+ * Module information has been stripped out from class and other resource files
+ * (.properties, binary files, ...).</p>
+ */
+final class AsmPoolImpl implements AsmModulePool {
+
+    /**
+     * Contains the transformed classes. When the jimage file is generated,
+     * transformed classes take precedence on unmodified ones.
+     */
+    public final class WritableClassPoolImpl implements WritableClassPool {
+
+        private WritableClassPoolImpl() {
+        }
+
+        /**
+         * Add a class to the pool, if a class already exists, it is replaced.
+         *
+         * @param writer The class writer.
+         * @throws java.io.IOException
+         */
+        @Override
+        public void addClass(ClassWriter writer) {
+            Objects.requireNonNull(writer);
+            // Retrieve the className
+            ClassReader reader = newClassReader(writer.toByteArray());
+            String className = reader.getClassName();
+            String path;
+            if (className.endsWith("module-info")) {
+                // remove the module name contained in the class name
+                className = className.substring(className.indexOf("/") + 1);
+                path = "/" + moduleName + "/" + className;
+            } else {
+                path = toClassNamePath(className);
+            }
+
+            byte[] content = writer.toByteArray();
+            ModuleData res = Pool.newResource(path,
+                    new ByteArrayInputStream(content), content.length);
+            transformedClasses.put(className, res);
+        }
+
+        /**
+         * The class will be not added to the jimage file.
+         *
+         * @param className The class name to forget.
+         */
+        @Override
+        public void forgetClass(String className) {
+            Objects.requireNonNull(className);
+            // do we have a resource?
+            ModuleData res = transformedClasses.get(className);
+            if (res == null) {
+                res = inputClasses.get(className);
+                if (res == null) {
+                    throw new PluginException("Unknown class " + className);
+                }
+            }
+            String path = toClassNamePath(className);
+            forgetResources.add(path);
+            // Just in case it has been added.
+            transformedClasses.remove(className);
+        }
+
+        /**
+         * Get a transformed class.
+         *
+         * @param binaryName The java class binary name
+         * @return The ClassReader or null if the class is not found.
+         */
+        @Override
+        public ClassReader getClassReader(String binaryName) {
+            Objects.requireNonNull(binaryName);
+            ModuleData res = transformedClasses.get(binaryName);
+            ClassReader reader = null;
+            if (res != null) {
+                reader = getClassReader(res);
+            }
+            return reader;
+        }
+
+        /**
+         * Returns all the classes contained in the writable pool.
+         *
+         * @return The array of transformed classes.
+         */
+        @Override
+        public Collection<ModuleData> getClasses() {
+            List<ModuleData> classes = new ArrayList<>();
+            for (Entry<String, ModuleData> entry : transformedClasses.entrySet()) {
+                classes.add(entry.getValue());
+            }
+            return classes;
+        }
+
+        @Override
+        public ClassReader getClassReader(ModuleData res) {
+            return newClassReader(res.getBytes());
+        }
+    }
+
+    /**
+     * Contains the transformed resources. When the jimage file is generated,
+     * transformed resources take precedence on unmodified ones.
+     */
+    public final class WritableResourcePoolImpl implements WritableResourcePool {
+
+        private WritableResourcePoolImpl() {
+        }
+
+        /**
+         * Add a resource, if the resource exists, it is replaced.
+         *
+         * @param resFile The resource file to add.
+         */
+        @Override
+        public void addResourceFile(ResourceFile resFile) {
+            Objects.requireNonNull(resFile);
+            String path = toResourceNamePath(resFile.getPath());
+            ModuleData res = Pool.newResource(path, resFile.getContent());
+            transformedResources.put(resFile.getPath(), res);
+        }
+
+        /**
+         * The resource will be not added to the jimage file.
+         *
+         * @param resourceName
+         * @throws java.io.IOException
+         */
+        @Override
+        public void forgetResourceFile(String resourceName) {
+            Objects.requireNonNull(resourceName);
+            String path = toResourceNamePath(resourceName);
+            // do we have a resource?
+            ModuleData res = transformedResources.get(resourceName);
+            if (res == null) {
+                res = inputResources.get(resourceName);
+                if (res == null) {
+                    throw new PluginException("Unknown resource " + resourceName);
+                }
+            }
+            forgetResources.add(path);
+            // Just in case it has been added.
+            transformedResources.remove(resourceName);
+        }
+
+        /**
+         * Get a transformed resource.
+         *
+         * @param name The java resource name
+         * @return The Resource or null if the resource is not found.
+         */
+        @Override
+        public ResourceFile getResourceFile(String name) {
+            Objects.requireNonNull(name);
+            ModuleData res = transformedResources.get(name);
+            ResourceFile resFile = null;
+            if (res != null) {
+                resFile = getResourceFile(res);
+            }
+            return resFile;
+        }
+
+        /**
+         * Returns all the resources contained in the writable pool.
+         *
+         * @return The array of transformed classes.
+         */
+        @Override
+        public Collection<ModuleData> getResourceFiles() {
+            List<ModuleData> resources = new ArrayList<>();
+            for (Entry<String, ModuleData> entry : transformedResources.entrySet()) {
+                resources.add(entry.getValue());
+            }
+            return resources;
+        }
+
+        @Override
+        public ResourceFile getResourceFile(ModuleData res) {
+            return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
+                    res.getBytes());
+        }
+    }
+
+    private final Pool jimageResources;
+    private final Map<String, ModuleData> inputClasses;
+    private final Map<String, ModuleData> inputResources;
+    private final Map<String, String> inputClassPackageMapping;
+    private final Map<String, String> inputOtherPackageMapping;
+
+    private final WritableClassPool transClassesPool
+            = new WritableClassPoolImpl();
+    private final WritableResourcePool transResourcesPool
+            = new WritableResourcePoolImpl();
+
+    private Sorter sorter;
+
+    private final Map<String, ModuleData> transformedClasses
+            =            new LinkedHashMap<>();
+    private final Map<String, ModuleData> transformedResources
+            =            new LinkedHashMap<>();
+    private final List<String> forgetResources = new ArrayList<>();
+    private final Map<String, String> newPackageMapping = new HashMap<>();
+
+    private final String moduleName;
+
+    private final ModuleDescriptor descriptor;
+    private final AsmPools pools;
+
+    /**
+     * A new Asm pool.
+     *
+     * @param inputResources The raw resources to build the pool from.
+     * @param moduleName The name of a module.
+     * @param pools The resource pools.
+     * @param descriptor The module descriptor.
+     */
+    AsmPoolImpl(Pool inputResources, String moduleName,
+            AsmPools pools,
+            ModuleDescriptor descriptor) {
+        Objects.requireNonNull(inputResources);
+        Objects.requireNonNull(moduleName);
+        Objects.requireNonNull(pools);
+        Objects.requireNonNull(descriptor);
+        this.jimageResources = inputResources;
+        this.moduleName = moduleName;
+        this.pools = pools;
+        this.descriptor = descriptor;
+        Map<String, ModuleData> classes = new LinkedHashMap<>();
+        Map<String, ModuleData> resources = new LinkedHashMap<>();
+        Map<String, String> packageClassToModule = new HashMap<>();
+        Map<String, String> packageOtherToModule = new HashMap<>();
+        for (ModuleData res : inputResources.getContent()) {
+            if (res.getPath().endsWith(".class")) {
+                classes.put(toJavaBinaryClassName(res.getPath()), res);
+            } else {
+                resources.put(toJavaBinaryResourceName(res.getPath()), res);
+            }
+            String[] split = ImageFileCreator.splitPath(res.getPath());
+            if (ImageFileCreator.isClassPackage(res.getPath())) {
+                packageClassToModule.put(split[1], res.getModule());
+            } else {
+                // Keep a map of other resources
+                // Same resource names such as META-INF/* should be handled with full path name.
+                if (!split[1].isEmpty()) {
+                    packageOtherToModule.put(split[1], res.getModule());
+                }
+            }
+        }
+        this.inputClasses = Collections.unmodifiableMap(classes);
+        this.inputResources = Collections.unmodifiableMap(resources);
+
+        this.inputClassPackageMapping = Collections.unmodifiableMap(packageClassToModule);
+        this.inputOtherPackageMapping = Collections.unmodifiableMap(packageOtherToModule);
+    }
+
+    @Override
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    /**
+     * The writable pool used to store transformed resources.
+     *
+     * @return The writable pool.
+     */
+    @Override
+    public WritableClassPool getTransformedClasses() {
+        return transClassesPool;
+    }
+
+    /**
+     * The writable pool used to store transformed resource files.
+     *
+     * @return The writable pool.
+     */
+    @Override
+    public WritableResourcePool getTransformedResourceFiles() {
+        return transResourcesPool;
+    }
+
+    /**
+     * Set a sorter instance to sort all files. If no sorter is set, then input
+     * Resources will be added in the order they have been received followed by
+     * newly added resources.
+     *
+     * @param sorter
+     */
+    @Override
+    public void setSorter(Sorter sorter) {
+        this.sorter = sorter;
+    }
+
+    /**
+     * Returns the classes contained in the pool.
+     *
+     * @return The array of classes.
+     */
+    @Override
+    public Collection<ModuleData> getClasses() {
+        return inputClasses.values();
+    }
+
+    /**
+     * Returns the resources contained in the pool. Resources are all the file
+     * that are not classes (eg: properties file, binary files, ...)
+     *
+     * @return The array of classes.
+     */
+    @Override
+    public Collection<ModuleData> getResourceFiles() {
+        return inputResources.values();
+    }
+
+    /**
+     * Retrieves a resource based on the binary name. This name doesn't contain
+     * the module name.
+     * <b>NB:</b> When dealing with resources that have the same name in various
+     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
+     * referenced from this <code>AsmClassPool</code>.
+     *
+     * @param binaryName Name of a Java resource or null if the resource doesn't
+     * exist.
+     * @return
+     */
+    @Override
+    public ResourceFile getResourceFile(String binaryName) {
+        Objects.requireNonNull(binaryName);
+        ModuleData res = inputResources.get(binaryName);
+        ResourceFile resFile = null;
+        if (res != null) {
+            resFile = getResourceFile(res);
+        }
+        return resFile;
+    }
+
+    /**
+     * Retrieve a ClassReader from the pool.
+     *
+     * @param binaryName Class binary name
+     * @return A reader or null if the class is unknown
+     */
+    @Override
+    public ClassReader getClassReader(String binaryName) {
+        Objects.requireNonNull(binaryName);
+        ModuleData res = inputClasses.get(binaryName);
+        ClassReader reader = null;
+        if (res != null) {
+            reader = getClassReader(res);
+        }
+        return reader;
+    }
+
+    @Override
+    public ResourceFile getResourceFile(ModuleData res) {
+        return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
+                res.getBytes());
+    }
+
+    @Override
+    public ClassReader getClassReader(ModuleData res) {
+        return newClassReader(res.getBytes());
+    }
+
+    /**
+     * Lookup the class in this pool and the required pools. NB: static module
+     * readability can be different at execution time.
+     *
+     * @param binaryName The class to lookup.
+     * @return The reader or null if not found
+     */
+    @Override
+    public ClassReader getClassReaderInDependencies(String binaryName) {
+        Objects.requireNonNull(binaryName);
+        ClassReader reader = getClassReader(binaryName);
+        if (reader == null) {
+            for (Requires requires : descriptor.requires()) {
+                AsmModulePool pool = pools.getModulePool(requires.name());
+                reader = pool.getExportedClassReader(moduleName, binaryName);
+                if (reader != null) {
+                    break;
+                }
+            }
+        }
+        return reader;
+    }
+
+    /**
+     * Lookup the class in the exported packages of this module. "public
+     * requires" modules are looked up. NB: static module readability can be
+     * different at execution time.
+     *
+     * @param callerModule Name of calling module.
+     * @param binaryName The class to lookup.
+     * @return The reader or null if not found
+     */
+    @Override
+    public ClassReader getExportedClassReader(String callerModule, String binaryName) {
+        Objects.requireNonNull(callerModule);
+        Objects.requireNonNull(binaryName);
+        boolean exported = false;
+        ClassReader clazz = null;
+        for (Exports e : descriptor.exports()) {
+            String pkg = e.source();
+            Set<String> targets = e.targets();
+            System.out.println("PKG " + pkg);
+            if (targets.isEmpty() || targets.contains(callerModule)) {
+                if (binaryName.startsWith(pkg)) {
+                    String className = binaryName.substring(pkg.length());
+                    System.out.println("CLASS " + className);
+                    exported = !className.contains(".");
+                }
+                if (exported) {
+                    break;
+                }
+            }
+        }
+        // public requires (re-export)
+        if (!exported) {
+            for (Requires requires : descriptor.requires()) {
+                if (requires.modifiers().contains(Modifier.PUBLIC)) {
+                    AsmModulePool pool = pools.getModulePool(requires.name());
+                    clazz = pool.getExportedClassReader(moduleName, binaryName);
+                    if (clazz != null) {
+                        break;
+                    }
+                }
+            }
+        } else {
+            clazz = getClassReader(binaryName);
+        }
+        return clazz;
+
+    }
+
+    @Override
+    public ModuleDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    /**
+     * To visit the set of ClassReaders.
+     *
+     * @param visitor The visitor.
+     */
+    @Override
+    public void visitClassReaders(ClassReaderVisitor visitor) {
+        Objects.requireNonNull(visitor);
+        for (ModuleData res : getClasses()) {
+            ClassReader reader = newClassReader(res.getBytes());
+            ClassWriter writer = visitor.visit(reader);
+            if (writer != null) {
+
+                getTransformedClasses().addClass(writer);
+            }
+        }
+    }
+
+    /**
+     * To visit the set of ClassReaders.
+     *
+     * @param visitor The visitor.
+     */
+    @Override
+    public void visitResourceFiles(ResourceFileVisitor visitor) {
+        Objects.requireNonNull(visitor);
+        for (ModuleData resource : getResourceFiles()) {
+            ResourceFile resFile
+                    = new ResourceFile(toJavaBinaryResourceName(resource.getPath()),
+                            resource.getBytes());
+            ResourceFile res = visitor.visit(resFile);
+            if (res != null) {
+                getTransformedResourceFiles().addResourceFile(res);
+            }
+        }
+    }
+
+    /**
+     * Returns the pool of all the resources (transformed and unmodified). The
+     * input resources are replaced by the transformed ones. If a sorter has
+     * been set, it is used to sort the returned resources.     *
+     */
+    @Override
+    public void fillOutputResources(Pool outputResources) {
+        List<String> added = new ArrayList<>();
+        // If the sorter is null, use the input order.
+        // New resources are added at the end
+        // First input classes that have not been removed
+        Pool output = new PoolImpl(outputResources.getByteOrder(),
+                ((PoolImpl)outputResources).getStringTable());
+        for (ModuleData inResource : jimageResources.getContent()) {
+            if (!forgetResources.contains(inResource.getPath())) {
+                ModuleData resource = inResource;
+                // Do we have a transformed class with the same name?
+                ModuleData res = transformedResources.
+                        get(toJavaBinaryResourceName(inResource.getPath()));
+                if (res != null) {
+                    resource = res;
+                } else {
+                    res = transformedClasses.
+                            get(toJavaBinaryClassName(inResource.getPath()));
+                    if (res != null) {
+                        resource = res;
+                    }
+                }
+                output.add(resource);
+                added.add(resource.getPath());
+            }
+        }
+        // Then new resources
+        for (Map.Entry<String, ModuleData> entry : transformedResources.entrySet()) {
+            ModuleData resource = entry.getValue();
+            if (!forgetResources.contains(resource.getPath())) {
+                if (!added.contains(resource.getPath())) {
+                    output.add(resource);
+                }
+            }
+        }
+        // And new classes
+        for (Map.Entry<String, ModuleData> entry : transformedClasses.entrySet()) {
+            ModuleData resource = entry.getValue();
+            if (!forgetResources.contains(resource.getPath())) {
+                if (!added.contains(resource.getPath())) {
+                    output.add(resource);
+                }
+            }
+        }
+
+        AsmPools.sort(outputResources, output, sorter);
+    }
+
+    /**
+     * Associate a package to this module, useful when adding new classes in new
+     * packages. WARNING: In order to properly handle new package and/or new
+     * module, module-info class must be added and/or updated.
+     *
+     * @param pkg The new package, following java binary syntax (/-separated
+     * path name).
+     * @throws PluginException If a mapping already exist for this package.
+     */
+    @Override
+    public void addPackage(String pkg) {
+        Objects.requireNonNull(pkg);
+        Objects.requireNonNull(moduleName);
+        pkg = pkg.replaceAll("/", ".");
+        String mod = newPackageMapping.get(pkg);
+        if (mod != null) {
+            throw new PluginException(mod + " module already contains package " + pkg);
+        }
+        newPackageMapping.put(pkg, moduleName);
+    }
+
+    @Override
+    public Set<String> getAllPackages() {
+        ModuleDescriptor desc = getDescriptor();
+        Set<String> packages = new HashSet<>();
+        for (String p : desc.conceals()) {
+            packages.add(p.replaceAll("\\.", "/"));
+        }
+        for (String p : newPackageMapping.keySet()) {
+            packages.add(p.replaceAll("\\.", "/"));
+        }
+        for (Exports ex : desc.exports()) {
+            packages.add(ex.source().replaceAll("\\.", "/"));
+        }
+        return packages;
+    }
+
+    private static ClassReader newClassReader(byte[] bytes) {
+        try {
+            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+            ClassReader reader = new ClassReader(stream);
+            return reader;
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    private static String toJavaBinaryClassName(String path) {
+        if (path.endsWith("module-info.class")) {
+            path = removeClassExtension(path);
+        } else {
+            path = removeModuleName(path);
+            path = removeClassExtension(path);
+        }
+        return path;
+    }
+
+    private static String toJavaBinaryResourceName(String path) {
+        if (!path.endsWith("module-info.class")) {
+            path = removeModuleName(path);
+        }
+        return path;
+    }
+
+    private static String removeClassExtension(String path) {
+        return path.substring(0, path.length() - ".class".length());
+    }
+
+    private static String removeModuleName(String path) {
+        path = path.substring(1);
+        return path.substring(path.indexOf("/") + 1, path.length());
+    }
+
+    private String toClassNamePath(String className) {
+        return toResourceNamePath(className) + ".class";
+    }
+
+    /**
+     * Entry point to manage resource<->module association.
+     */
+    private String toResourceNamePath(String resourceName) {
+        if (!resourceName.startsWith("/")) {
+            resourceName = "/" + resourceName;
+        }
+        String pkg = toPackage(resourceName);
+        String module = inputClassPackageMapping.get(pkg);
+        if (module == null) {
+            module = newPackageMapping.get(pkg);
+            if (module == null) {
+                module = inputOtherPackageMapping.get(pkg);
+                if (module == null) {
+                    throw new PluginException("No module for package" + pkg);
+                }
+            }
+        }
+        return "/" + module + resourceName;
+    }
+
+    private static String toPackage(String path) {
+        if (path.startsWith("/")) {
+            path = path.substring(1);
+        }
+        int i = path.lastIndexOf("/");
+        if (i == -1) {
+            // Default package...
+            return "";
+        }
+        return path.substring(0, i).replaceAll("/", ".");
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java
new file mode 100644
index 0000000..bbb2d54
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.asm;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Requires;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.PUBLIC;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.Sorter;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+/**
+ * A container for pools of ClassReader and other resource files. A pool of all
+ * the resources or a pool for a given module can be retrieved
+ */
+public final class AsmPools {
+
+    /**
+     * Sort the order in which the modules will be stored in the jimage file.
+     */
+    public interface ModuleSorter {
+
+        /**
+         * Sort the list of modules.
+         *
+         * @param modules The list of module names. The module will be stored in
+         * the jimage following this order.
+         * @return A list of module names that expresses the order in which the
+         * modules are stored in the jimage.
+         */
+        public List<String> sort(List<String> modules);
+    }
+
+    private class AsmGlobalPoolImpl implements AsmGlobalPool {
+
+        private Sorter sorter = null;
+
+        private class GlobalWritableClassPool implements WritableClassPool {
+
+            @Override
+            public void addClass(ClassWriter writer) {
+                visitFirstNonFailingPool((AsmModulePool pool) -> {
+                    pool.getTransformedClasses().addClass(writer);
+                });
+            }
+
+            @Override
+            public void forgetClass(String className) {
+                visitFirstNonFailingPool((AsmModulePool pool) -> {
+                    pool.getTransformedClasses().forgetClass(className);
+                });
+            }
+
+            @Override
+            public ClassReader getClassReader(String binaryName) {
+                return visitPools((AsmModulePool pool) -> {
+                    return pool.getTransformedClasses().getClassReader(binaryName);
+                });
+            }
+
+            @Override
+            public Collection<Pool.ModuleData> getClasses() {
+                List<Pool.ModuleData> all = new ArrayList<>();
+                visitAllPools((AsmModulePool pool) -> {
+                    for (Pool.ModuleData rf : pool.getTransformedClasses().getClasses()) {
+                        all.add(rf);
+                    }
+                });
+                return all;
+            }
+
+            @Override
+            public ClassReader getClassReader(Pool.ModuleData res) {
+                return visitPools((AsmModulePool pool) -> {
+                    return pool.getTransformedClasses().getClassReader(res);
+                });
+            }
+
+        }
+
+        private class GlobalWritableResourcePool implements WritableResourcePool {
+
+            @Override
+            public void addResourceFile(ResourceFile resFile) {
+                visitFirstNonFailingPool((AsmModulePool pool) -> {
+                    pool.getTransformedResourceFiles().addResourceFile(resFile);
+                });
+            }
+
+            @Override
+            public void forgetResourceFile(String resourceName) {
+                visitFirstNonFailingPool((AsmModulePool pool) -> {
+                    pool.getTransformedResourceFiles().forgetResourceFile(resourceName);
+                });
+            }
+
+            @Override
+            public ResourceFile getResourceFile(String name) {
+                return visitPools((AsmModulePool pool) -> {
+                    return pool.getTransformedResourceFiles().getResourceFile(name);
+                });
+            }
+
+            @Override
+            public Collection<Pool.ModuleData> getResourceFiles() {
+                List<Pool.ModuleData> all = new ArrayList<>();
+                visitAllPools((AsmModulePool pool) -> {
+                    for (Pool.ModuleData rf : pool.getTransformedResourceFiles().getResourceFiles()) {
+                        all.add(rf);
+                    }
+                });
+                return all;
+            }
+
+            @Override
+            public ResourceFile getResourceFile(Pool.ModuleData res) {
+                return visitPools((AsmModulePool pool) -> {
+                    return pool.getTransformedResourceFiles().getResourceFile(res);
+                });
+            }
+
+        }
+
+        @Override
+        public AsmPool.WritableClassPool getTransformedClasses() {
+            return new GlobalWritableClassPool();
+        }
+
+        @Override
+        public AsmPool.WritableResourcePool getTransformedResourceFiles() {
+            return new GlobalWritableResourcePool();
+        }
+
+        @Override
+        public void setSorter(AsmPool.Sorter sorter) {
+            this.sorter = sorter;
+        }
+
+        @Override
+        public Collection<Pool.ModuleData> getClasses() {
+            List<Pool.ModuleData> all = new ArrayList<>();
+            visitAllPools((AsmModulePool pool) -> {
+                for (Pool.ModuleData rf : pool.getClasses()) {
+                    all.add(rf);
+                }
+            });
+            return all;
+        }
+
+        @Override
+        public Collection<Pool.ModuleData> getResourceFiles() {
+            List<Pool.ModuleData> all = new ArrayList<>();
+            visitAllPools((AsmModulePool pool) -> {
+                for (Pool.ModuleData rf : pool.getResourceFiles()) {
+                    all.add(rf);
+                }
+            });
+            return all;
+        }
+
+        @Override
+        public AsmPool.ResourceFile getResourceFile(String binaryName) {
+            return visitPools((AsmModulePool pool) -> {
+                return pool.getResourceFile(binaryName);
+            });
+        }
+
+        @Override
+        public ClassReader getClassReader(String binaryName) {
+            return visitPoolsEx((AsmModulePool pool) -> {
+                return pool.getClassReader(binaryName);
+            });
+        }
+
+        @Override
+        public ResourceFile getResourceFile(Pool.ModuleData res) {
+            return visitPools((AsmModulePool pool) -> {
+                return pool.getResourceFile(res);
+            });
+        }
+
+        @Override
+        public ClassReader getClassReader(Pool.ModuleData res) {
+            return visitPoolsEx((AsmModulePool pool) -> {
+                return pool.getClassReader(res);
+            });
+        }
+
+        @Override
+        public void visitClassReaders(AsmPool.ClassReaderVisitor visitor) {
+            visitAllPoolsEx((AsmModulePool pool) -> {
+                pool.visitClassReaders(visitor);
+            });
+        }
+
+        @Override
+        public void visitResourceFiles(AsmPool.ResourceFileVisitor visitor) {
+            visitAllPoolsEx((AsmModulePool pool) -> {
+                pool.visitResourceFiles(visitor);
+            });
+        }
+
+        @Override
+        public void fillOutputResources(Pool outputResources) {
+            AsmPools.this.fillOutputResources(outputResources);
+        }
+
+        @Override
+        public void addPackageModuleMapping(String pkg, String module) {
+            AsmModulePool p = pools.get(module);
+            if (p == null) {
+                throw new PluginException("Unknown module " + module);
+            }
+            p.addPackage(pkg);
+        }
+
+        @Override
+        public Set<String> getAccessiblePackages(String module) {
+            AsmModulePool p = pools.get(module);
+            if (p == null) {
+                return null;
+            }
+            ModuleDescriptor desc = p.getDescriptor();
+            Set<String> packages = new HashSet<>();
+            packages.addAll(p.getAllPackages());
+
+            // Retrieve direct dependencies and indirect ones (public)
+            Set<String> modules = new HashSet<>();
+            for (Requires req : desc.requires()) {
+                modules.add(req.name());
+                addAllRequirePublicModules(req.name(), modules);
+            }
+            // Add exported packages of readable modules
+            for (String readable : modules) {
+                AsmModulePool mp = pools.get(readable);
+                if (mp != null) {
+                    for (Exports e : mp.getDescriptor().exports()) {
+                        // exported to all or to the targeted module
+                        if (e.targets().isEmpty() || e.targets().contains(module)) {
+                            packages.add(e.source().replaceAll("\\.", "/"));
+                        }
+                    }
+
+                }
+            }
+            return packages;
+        }
+
+        private void addAllRequirePublicModules(String module, Set<String> modules) {
+            AsmModulePool p = pools.get(module);
+            if (p != null) {
+                for (Requires req : p.getDescriptor().requires()) {
+                    if (req.modifiers().contains(PUBLIC)) {
+                        modules.add(req.name());
+                        addAllRequirePublicModules(req.name(), modules);
+                    }
+                }
+            }
+        }
+
+    }
+
+    private interface VoidPoolVisitor {
+
+        void visit(AsmModulePool pool);
+    }
+
+    private interface VoidPoolVisitorEx {
+
+        void visit(AsmModulePool pool);
+    }
+
+    private interface RetPoolVisitor<P> {
+
+        P visit(AsmModulePool pool);
+    }
+
+    private final Map<String, AsmModulePool> pools = new LinkedHashMap<>();
+    private final AsmModulePool[] poolsArray;
+    private final AsmGlobalPoolImpl global;
+
+    private ModuleSorter moduleSorter;
+
+    /**
+     * A new Asm pools.
+     *
+     * @param inputResources The raw resources to build the pool from.
+     */
+    public AsmPools(Pool inputResources) {
+        Objects.requireNonNull(inputResources);
+        Map<String, Pool> resPools = new LinkedHashMap<>();
+        Map<String, ModuleDescriptor> descriptors = new HashMap<>();
+        for (Pool.ModuleData res : inputResources.getContent()) {
+            Pool p = resPools.get(res.getModule());
+            if (p == null) {
+                p = new PoolImpl(inputResources.getByteOrder(),
+                        ((PoolImpl)inputResources).getStringTable());
+                resPools.put(res.getModule(), p);
+            }
+            if (res.getPath().endsWith("module-info.class")) {
+                ByteBuffer bb = ByteBuffer.wrap(res.getBytes());
+                ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
+                descriptors.put(res.getModule(), descriptor);
+            }
+            p.add(res);
+        }
+        poolsArray = new AsmModulePool[resPools.size()];
+        int i = 0;
+
+        for (Entry<String, Pool> entry : resPools.entrySet()) {
+            ModuleDescriptor descriptor = descriptors.get(entry.getKey());
+            if (descriptor == null) {
+                throw new PluginException("module-info.class not found for " + entry.getKey() + " module");
+            }
+            AsmModulePool p = new AsmPoolImpl(entry.getValue(),
+                    entry.getKey(), this, descriptor);
+            pools.put(entry.getKey(), p);
+            poolsArray[i] = p;
+            i += 1;
+        }
+        global = new AsmGlobalPoolImpl();
+    }
+
+    /**
+     * The pool containing all classes and other resources.
+     *
+     * @return The global pool
+     */
+    public AsmGlobalPool getGlobalPool() {
+        return global;
+    }
+
+    /**
+     * A pool for a given module
+     *
+     * @param name The module name
+     * @return The pool that contains content of the passed module or null if
+     * the module doesn't exist.
+     */
+    public AsmModulePool getModulePool(String name) {
+        Objects.requireNonNull(name);
+        return pools.get(name);
+    }
+
+    /**
+     * The array of module pools.
+     * @return The module pool array.
+     */
+    public AsmModulePool[] getModulePools() {
+        return poolsArray.clone();
+    }
+
+    /**
+     * Set a module sorter. Sorter is used when computing the output resources.
+     *
+     * @param moduleSorter The module sorter
+     */
+    public void setModuleSorter(ModuleSorter moduleSorter) {
+        Objects.requireNonNull(moduleSorter);
+        this.moduleSorter = moduleSorter;
+    }
+
+    /**
+     * Returns the pool of all the resources (transformed and unmodified). The
+     * input resources are replaced by the transformed ones. If a sorter has
+     * been set, it is used to sort in modules.
+     *
+     * @param outputResources The pool used to fill the jimage.
+     */
+    public void fillOutputResources(Pool outputResources) {
+        // First sort modules
+        List<String> modules = new ArrayList<>();
+        for (String k : pools.keySet()) {
+            modules.add(k);
+        }
+        if (moduleSorter != null) {
+            modules = moduleSorter.sort(modules);
+        }
+        Pool output = new PoolImpl(outputResources.getByteOrder(),
+                ((PoolImpl)outputResources).getStringTable());
+        for (String mn : modules) {
+            AsmPool pool = pools.get(mn);
+            pool.fillOutputResources(output);
+        }
+        sort(outputResources, output, global.sorter);
+    }
+
+    static void sort(Pool outputResources,
+            Pool transientOutput, Sorter sorter) {
+        if (sorter != null) {
+            List<String> order = sorter.sort(transientOutput);
+            for (String s : order) {
+                outputResources.add(transientOutput.get(s));
+            }
+        } else {
+            for (ModuleData res : transientOutput.getContent()) {
+                outputResources.add(res);
+            }
+        }
+    }
+
+    private void visitFirstNonFailingPool(VoidPoolVisitorEx pv) {
+        boolean found = false;
+        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
+            try {
+                pv.visit(entry.getValue());
+                found = true;
+                break;
+            } catch (Exception ex) {
+                // XXX OK, try  another one.
+            }
+        }
+        if (!found) {
+            throw new PluginException("No module found");
+        }
+    }
+
+    private void visitAllPools(VoidPoolVisitor pv) {
+        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
+            pv.visit(entry.getValue());
+        }
+    }
+
+    private void visitAllPoolsEx(VoidPoolVisitorEx pv) {
+        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
+            pv.visit(entry.getValue());
+        }
+    }
+
+    private <P> P visitPoolsEx(RetPoolVisitor<P> pv) {
+        P p = null;
+        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
+            try {
+                p = pv.visit(entry.getValue());
+                if (p != null) {
+                    break;
+                }
+            } catch (Exception ex) {
+                // XXX OK, try  another one.
+            }
+        }
+        return p;
+    }
+
+    private <P> P visitPools(RetPoolVisitor<P> pv) {
+        P p = null;
+        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
+            try {
+                p = pv.visit(entry.getValue());
+                if (p != null) {
+                    break;
+                }
+            } catch (Exception ex) {
+                // XXX OK, try  another one.
+            }
+        }
+        return p;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java
new file mode 100644
index 0000000..977e044
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.optim;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TreeSet;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer;
+import jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException;
+import jdk.internal.org.objectweb.asm.tree.analysis.BasicInterpreter;
+import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue;
+
+/**
+ * Split Java method onto a control flow.
+ *
+ */
+public final class ControlFlow {
+
+    /**
+     * A block of control
+     */
+    public static final class Block implements Comparable<Block> {
+
+        private final InstructionNode firstInstruction;
+        private final List<InstructionNode> instr = new ArrayList<>();
+        private final List<Block> reachable = new ArrayList<>();
+        private final List<Block> exceptionHandlers = new ArrayList<>();
+        private boolean isExceptionHandler;
+
+        private Block(InstructionNode firstInstruction) {
+            this.firstInstruction = firstInstruction;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof Block)) {
+                return false;
+            }
+            Block b = (Block) other;
+            return firstInstruction.equals(b.firstInstruction);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 79 * hash + Objects.hashCode(this.firstInstruction);
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            for (InstructionNode in : instr) {
+                builder.append(in).append(" ");
+            }
+            builder.append(" reachables: ");
+            for (Block r : reachable) {
+                builder.append(r.getFirstInstruction()).append(" ");
+            }
+            builder.append(" exception handlers: ");
+            for (Block r : exceptionHandlers) {
+                builder.append(r.getFirstInstruction()).append(" ");
+            }
+
+            return "block[" + getFirstInstruction() + "],ex:"
+                    + isExceptionHandler + ",  " + builder.toString();
+        }
+
+        /**
+         * @return the firstInstruction
+         */
+        public InstructionNode getFirstInstruction() {
+            return firstInstruction;
+        }
+
+        /**
+         * @return the instr
+         */
+        public List<InstructionNode> getInstructions() {
+            return Collections.unmodifiableList(instr);
+        }
+
+        /**
+         * @return the reachable
+         */
+        public List<Block> getReachableBlocks() {
+            return Collections.unmodifiableList(reachable);
+        }
+
+        /**
+         * @return the exceptionHandlers
+         */
+        public List<Block> getExceptionHandlerBlocks() {
+            return Collections.unmodifiableList(exceptionHandlers);
+        }
+
+        @Override
+        public int compareTo(Block t) {
+            return this.firstInstruction.index - t.firstInstruction.index;
+        }
+
+        public boolean isExceptionHandler() {
+            return isExceptionHandler;
+        }
+
+    }
+
+    private class ClosureBuilder {
+
+        private final Block root;
+
+        private ClosureBuilder(Block root) {
+            Objects.requireNonNull(root);
+            this.root = root;
+        }
+
+        private Set<Block> build() {
+            Set<Block> allReachable = new TreeSet<>();
+            addAll(root, allReachable);
+            // filter out the reachable from outside this graph
+            Iterator<Block> it = allReachable.iterator();
+            Set<Block> toExclude = new HashSet<>();
+            while (it.hasNext()) {
+                Block b = it.next();
+                for (Block ref : blocks) {
+                    if (!allReachable.contains(ref) && ref.reachable.contains(b)) {
+                        addAll(b, toExclude);
+                        break;
+                    }
+                }
+            }
+            //System.err.println("TO EXCLUDE:\n " + toExclude);
+            allReachable.removeAll(toExclude);
+            //System.err.println("CLOSURE:\n " + allReachable);
+            return Collections.unmodifiableSet(allReachable);
+        }
+
+        // Compute the set of blocks reachable from the current block
+        private void addAll(Block current, Set<Block> closure) {
+            Objects.requireNonNull(current);
+            closure.add(current);
+            for (Block ex : current.exceptionHandlers) {
+                Objects.requireNonNull(ex);
+                if (!closure.contains(ex)) {
+                    addAll(ex, closure);
+                }
+            }
+            for (Block r : current.reachable) {
+                Objects.requireNonNull(r);
+                if (!closure.contains(r)) {
+                    addAll(r, closure);
+                }
+            }
+
+        }
+    }
+
+    /**
+     * An instruction
+     */
+    public static final class InstructionNode {
+
+        private final int index;
+        private final List<InstructionNode> next = new ArrayList<>();
+        private final AbstractInsnNode instr;
+
+        private InstructionNode(int index, AbstractInsnNode instr) {
+            this.index = index;
+            this.instr = instr;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof InstructionNode)) {
+                return false;
+            }
+            final InstructionNode other = (InstructionNode) obj;
+            return this.getIndex() == other.getIndex();
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 3;
+            hash = 89 * hash + this.getIndex();
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            return getIndex() + "(" + (getInstr().getOpcode() == - 1 ? -1
+                    : Integer.toHexString(getInstr().getOpcode())) + ")";
+        }
+
+        /**
+         * @return the index
+         */
+        public int getIndex() {
+            return index;
+        }
+
+        /**
+         * @return the instr
+         */
+        public AbstractInsnNode getInstr() {
+            return instr;
+        }
+
+    }
+
+    private final Map<Integer, Block> allBlocks;
+    private final List<Block> blocks = new ArrayList<>();
+
+    private ControlFlow(Map<Integer, Block> allBlocks) {
+        this.allBlocks = allBlocks;
+        for (Block b : allBlocks.values()) {
+            blocks.add(b);
+        }
+        Collections.sort(blocks);
+    }
+
+    public List<Block> getBlocks() {
+
+        return Collections.unmodifiableList(blocks);
+    }
+
+    public Block getBlock(int firstInstr) {
+        return allBlocks.get(firstInstr);
+    }
+
+    public static ControlFlow createControlFlow(String owner,
+            MethodNode method) throws Exception {
+
+        BlockBuilder bb = new BlockBuilder(owner, method);
+        return bb.build();
+    }
+
+    /**
+     * Return the set of blocks that are only reachable from this block For
+     * example, if b is an Exception handler, returns all the blocks reachable
+     * only from this handler
+     *
+     * @param b
+     * @return
+     */
+    public Set<Block> getClosure(Block b) {
+        return new ClosureBuilder(b).build();
+    }
+
+    private static final class BlockBuilder {
+
+        private InstructionNode root;
+        private final Map<Integer, InstructionNode> instructions = new HashMap<>();
+        private final Map<Integer, List<Integer>> handlers = new HashMap<>();
+        private final Map<Integer, Block> allBlocks = new HashMap<>();
+
+        private final String owner;
+        private final MethodNode method;
+
+        private BlockBuilder(String owner, MethodNode method) {
+            this.owner = owner;
+            this.method = method;
+        }
+
+        private void analyze() throws AnalyzerException {
+            Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(new BasicInterpreter()) {
+
+                @Override
+                protected boolean newControlFlowExceptionEdge(int insn,
+                        int successor) {
+                    List<Integer> lst = handlers.get(successor);
+                    if (lst == null) {
+                        lst = new ArrayList<>();
+                        handlers.put(successor, lst);
+                    }
+                    lst.add(insn);
+                    return true;
+                }
+
+                @Override
+                protected void newControlFlowEdge(int from,
+                        int to) {
+                    if (root == null) {
+                        root = new InstructionNode(from, method.instructions.get(from));
+                        instructions.put(from, root);
+                    }
+                    InstructionNode fromNode = instructions.get(from);
+                    if (fromNode == null) {
+                        fromNode = new InstructionNode(from, method.instructions.get(from));
+                        instructions.put(from, fromNode);
+                    }
+                    InstructionNode toNode = instructions.get(to);
+                    if (toNode == null) {
+                        toNode = new InstructionNode(to, method.instructions.get(to));
+                        instructions.put(to, toNode);
+                    }
+                    if (!fromNode.next.contains(toNode)) {
+                        fromNode.next.add(toNode);
+                    }
+
+                }
+            };
+            analyzer.analyze(owner, method);
+        }
+
+        private Block newBlock(InstructionNode firstInstruction) {
+            Objects.requireNonNull(firstInstruction);
+            Block b = new Block(firstInstruction);
+            allBlocks.put(firstInstruction.getIndex(), b);
+            return b;
+        }
+
+        private ControlFlow build() throws AnalyzerException {
+            analyze();
+            buildBlocks();
+            return new ControlFlow(allBlocks);
+        }
+
+        private void buildBlocks() {
+            List<Block> reachableBlocks = new ArrayList<>();
+            createBlocks(root, reachableBlocks);
+            List<Block> handlersBlocks = new ArrayList<>();
+            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
+                InstructionNode node = instructions.get(entry.getKey());
+                createBlocks(node, handlersBlocks);
+            }
+
+            // attach handler to try blocks
+            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
+                Block handlerBlock = allBlocks.get(entry.getKey());
+                handlerBlock.isExceptionHandler = true;
+                int startTry = entry.getValue().get(0);
+                Block tryBlock = allBlocks.get(startTry);
+                if (tryBlock == null) {
+                    // Need to find the block that contains the instruction and
+                    // make a new block
+                    Block split = null;
+                    for (Block b : allBlocks.values()) {
+                        Iterator<InstructionNode> it = b.instr.iterator();
+                        while (it.hasNext()) {
+                            InstructionNode in = it.next();
+                            if (split == null) {
+                                if (in.index == startTry) {
+                                    split = newBlock(in);
+                                    split.instr.add(in);
+                                    it.remove();
+                                }
+                            } else {
+                                split.instr.add(in);
+                                it.remove();
+                            }
+                        }
+                        if (split != null) {
+                            Iterator<Block> reachables = b.reachable.iterator();
+                            while (reachables.hasNext()) {
+                                Block r = reachables.next();
+                                split.reachable.add(r);
+                                reachables.remove();
+                            }
+                            b.reachable.add(split);
+                            break;
+                        }
+                    }
+                    if (split == null) {
+                        throw new RuntimeException("No try block for handler " + handlerBlock);
+                    }
+                    split.exceptionHandlers.add(handlerBlock);
+                } else {
+                    tryBlock.exceptionHandlers.add(handlerBlock);
+                }
+            }
+
+//            System.err.println("ALL BLOCKS FOUND");
+//            Iterator<Entry<Integer, Block>> blockIt0 = allBlocks.entrySet().iterator();
+//            while (blockIt0.hasNext()) {
+//                Block b = blockIt0.next().getValue();
+//                System.err.println(b);
+//            }
+            //compute real exception blocks, if an instruction is in another block, stop.
+            Iterator<Entry<Integer, Block>> blockIt = allBlocks.entrySet().iterator();
+            while (blockIt.hasNext()) {
+                Block b = blockIt.next().getValue();
+                Iterator<InstructionNode> in = b.instr.iterator();
+                boolean found = false;
+                while (in.hasNext()) {
+                    int i = in.next().getIndex();
+                    if (found) {
+                        in.remove();
+                    } else {
+                        if (startsWith(b, i, allBlocks.values())) {
+                            // Move it to reachable
+                            Block r = allBlocks.get(i);
+                            b.reachable.add(r);
+                            found = true;
+                            in.remove();
+                        } else {
+                        }
+                    }
+                }
+            }
+
+//            System.err.println("Reduced blocks");
+//            Iterator<Entry<Integer, Block>> blockIt1 = allBlocks.entrySet().iterator();
+//            while (blockIt1.hasNext()) {
+//                Block b = blockIt1.next().getValue();
+//                System.err.println(b);
+//            }
+        }
+
+        private boolean startsWith(Block block, int index, Collection<Block> reachableBlocks) {
+            for (Block b : reachableBlocks) {
+                if (b != block && !b.instr.isEmpty() && b.instr.get(0).getIndex() == index) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private static final class StackItem {
+
+            private final InstructionNode instr;
+            private final Block currentBlock;
+
+            private StackItem(InstructionNode instr, Block currentBlock) {
+                Objects.requireNonNull(instr);
+                Objects.requireNonNull(currentBlock);
+                this.instr = instr;
+                this.currentBlock = currentBlock;
+            }
+        }
+
+        /**
+         * This algorithm can't be recursive, possibly too much instructions in
+         * methods.
+         */
+        private void createBlocks(InstructionNode root, List<Block> blocks) {
+            final Stack<StackItem> stack = new Stack<>();
+            stack.push(new StackItem(root, newBlock(root)));
+            while (!stack.isEmpty()) {
+                final StackItem item = stack.pop();
+                final Block currentBlock = item.currentBlock;
+                final InstructionNode current = item.instr;
+                // loop
+                if (currentBlock.instr.contains(current)) {
+                    currentBlock.reachable.add(currentBlock);
+                    continue;
+                }
+                Block existing = allBlocks.get(current.index);
+                if (existing != null && existing != currentBlock) {
+                    currentBlock.reachable.add(existing);
+                    continue;
+                }
+                int previous = currentBlock.instr.size() > 0
+                        ? currentBlock.instr.get(currentBlock.instr.size() - 1).getIndex() : -1;
+                if (previous == -1 || current.getIndex() == previous + 1) {
+                    currentBlock.instr.add(current);
+                    if (current.next.isEmpty()) {
+                        blocks.add(currentBlock);
+                    } else {
+                        if (current.next.size() > 1) {
+                            blocks.add(currentBlock);
+                            for (InstructionNode n : current.next) {
+                                Block loop = allBlocks.get(n.index);
+                                if (loop == null) {
+                                    Block newBlock = newBlock(n);
+                                    currentBlock.reachable.add(newBlock);
+                                    stack.push(new StackItem(n, newBlock));
+                                } else { // loop
+                                    currentBlock.reachable.add(loop);
+                                }
+                            }
+                        } else {
+                            stack.push(new StackItem(current.next.get(0),
+                                    currentBlock));
+                        }
+                    }
+                } else { // to a new block...
+                    // Do nothing...
+                    blocks.add(currentBlock);
+                    Block newBlock = newBlock(current);
+                    currentBlock.reachable.add(newBlock);
+                    stack.push(new StackItem(current, newBlock));
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java
new file mode 100644
index 0000000..fcf12be
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.optim;
+
+import java.io.IOException;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Consumer;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.tools.jlink.internal.plugins.OptimizationPlugin.MethodOptimizer;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
+import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.Data;
+import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
+
+
+/**
+ * MethodOptimizer that removes Class.forName when possible.
+ * WARNING: This code is experimental.
+ * TODO: Need to check that the type is accessible prior to replace with a constant.
+ */
+public class ForNameFolding implements MethodOptimizer {
+
+    private int numNotReplaced;
+    private int numReplacement;
+    private int numRemovedHandlers;
+    private int instructionsRemoved;
+
+    private Consumer<String> logger;
+
+    @Override
+    public boolean optimize(Consumer<String> logger, AsmPools pools,
+            AsmModulePool modulePool,
+            ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception {
+        this.logger = logger;
+        Data data = ReflectionOptimizer.replaceWithClassConstant(cn, m, createResolver(resolver));
+        instructionsRemoved += data.removedInstructions();
+        numRemovedHandlers += data.removedHandlers().size();
+        for (Entry<String, Set<Block>> entry : data.removedHandlers().entrySet()) {
+            logRemoval(cn.name + "." + m.name + "removed block for " + entry.getKey()
+                    + " : " + entry.getValue());
+        }
+        return data.removedInstructions() > 0;
+    }
+
+    public TypeResolver createResolver(TypeResolver resolver) {
+        return (ClassNode cn, MethodNode mn, String type) -> {
+            ClassReader reader = resolver.resolve(cn, mn, type);
+            if (reader == null) {
+                logNotReplaced(type);
+            } else {
+                logReplaced(type);
+            }
+            return reader;
+        };
+    }
+
+    private void logReplaced(String type) {
+        numReplacement += 1;
+    }
+
+    private void logNotReplaced(String type) {
+        numNotReplaced += 1;
+        if (logger != null) {
+            logger.accept(type + " not resolved");
+        }
+    }
+
+    private void logRemoval(String content) {
+        numRemovedHandlers += 1;
+        if (logger != null) {
+            logger.accept(content);
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (logger != null) {
+            logger.accept("Class.forName Folding results:\n " + numReplacement
+                    + " removed reflection. " + numRemovedHandlers
+                    + " removed exception handlers."
+                    + numNotReplaced + " types unknown. "
+                    + instructionsRemoved + " instructions removed\n");
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java
new file mode 100644
index 0000000..690b884
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.optim;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.LabelNode;
+import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
+import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
+import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
+import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
+
+/**
+ * Implement the reflection optimization.
+ */
+public class ReflectionOptimizer {
+
+    public static class Data {
+
+        private int removedInstructions;
+        private final Map<String, Set<Block>> removedHandlers = new HashMap<>();
+
+        private Data() {
+        }
+
+        public int removedInstructions() {
+            return removedInstructions;
+        }
+
+        public Map<String, Set<Block>> removedHandlers() {
+            return Collections.unmodifiableMap(removedHandlers);
+        }
+    }
+
+    public interface TypeResolver {
+
+        public ClassReader resolve(ClassNode cn, MethodNode m, String type);
+    }
+
+    public static Data replaceWithClassConstant(ClassNode cn, MethodNode m,
+            TypeResolver cch)
+            throws Exception {
+        Iterator<AbstractInsnNode> it = m.instructions.iterator();
+        LdcInsnNode insNode = null;
+        Map<LdcInsnNode, LdcInsnNode> replacement = new IdentityHashMap<>();
+        Data data = new Data();
+        while (it.hasNext()) {
+            AbstractInsnNode n = it.next();
+            if (n instanceof LdcInsnNode) {
+                LdcInsnNode ldc = (LdcInsnNode) n;
+                if (ldc.cst instanceof String) {
+                    insNode = ldc;
+                }
+            } else {
+                if (n instanceof MethodInsnNode && insNode != null) {
+                    MethodInsnNode met = (MethodInsnNode) n;
+                    if (met.name.equals("forName")
+                            && met.owner.equals("java/lang/Class")
+                            && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+                        // Can we load the type?
+                        Type type = null;
+                        String binaryName = insNode.cst.toString().replaceAll("\\.", "/");
+                        String unaryClassName = binaryName;
+                        int arrayIndex = binaryName.lastIndexOf("[");
+                        if (arrayIndex >= 0) {
+                            int objIndex = unaryClassName.indexOf("L");
+                            if (objIndex >= 0) {
+                                unaryClassName = unaryClassName.substring(objIndex + 1);
+                                unaryClassName = unaryClassName.substring(0,
+                                        unaryClassName.length() - 1);
+                            } else {
+                                //primitive, this is just fine.
+                                type = Type.getObjectType(binaryName);
+                            }
+                        }
+                        if (type == null) {
+                            if (cch.resolve(cn, m, unaryClassName) != null) {
+                                type = Type.getObjectType(binaryName);
+                            }
+                        }
+                        if (type != null) {
+                            replacement.put(insNode, new LdcInsnNode(type));
+                            it.remove();
+                            data.removedInstructions += 1;
+                        }
+                    } else {
+                        insNode = null;
+                    }
+                    // Virtual node, not taken into account
+                } else if (!(n instanceof LabelNode) && !(n instanceof LineNumberNode)) {
+                    insNode = null;
+                }
+            }
+        }
+        for (Map.Entry<LdcInsnNode, LdcInsnNode> entry : replacement.entrySet()) {
+            m.instructions.set(entry.getKey(), entry.getValue());
+        }
+        if (!replacement.isEmpty()) {
+            String[] types = {"java/lang/ClassNotFoundException"};
+            data.removedInstructions += deleteExceptionHandlers(cch, data, cn, m, types);
+
+        }
+        return data;
+    }
+
+    private static int deleteExceptionHandlers(TypeResolver cch, Data data,
+            ClassNode cn, MethodNode m, String[] exTypes)
+            throws Exception {
+        int instructionsRemoved = 0;
+        for (String ex : exTypes) {
+            ControlFlow f = ControlFlow.createControlFlow(cn.name, m);
+            List<Integer> removed = new ArrayList<>();
+            Set<ControlFlow.Block> blocksToRemove = new TreeSet<>();
+            Iterator<TryCatchBlockNode> it = m.tryCatchBlocks.iterator();
+            List<TryCatchBlockNode> tcbToRemove = new ArrayList<>();
+            while (it.hasNext()) {
+                TryCatchBlockNode bn = it.next();
+                if (bn.type == null
+                        || !bn.type.equals(ex) // An empty block
+                        || tcbToRemove.contains(bn)) {
+                    continue;
+                }
+                // Check that the handler is still required
+                if (!Utils.canThrowCheckedException(cch, cn, m, bn)) {
+                    // try to suppress it.
+                    int block = m.instructions.indexOf(bn.handler);
+                    ControlFlow.Block blockHandler = f.getBlock(block);
+                    if (blockHandler == null) {
+                        if (removed.contains(block)) {
+                            continue;
+                        } else {
+                            throw new Exception(cn.name
+                                    + ", no block for handler " + block);
+                        }
+                    }
+                    tcbToRemove.add(bn);
+                    // Don't delete block if shared (eg: ClassNotFoundException | NoSuchMethodException |
+                    Iterator<TryCatchBlockNode> it2 = m.tryCatchBlocks.iterator();
+                    boolean cont = false;
+                    while (it2.hasNext()) {
+                        TryCatchBlockNode bn2 = it2.next();
+                        if (bn2 != bn) {
+                            if (bn2.start.equals(bn.start)) {
+                                cont = true;
+                            }
+                        }
+                    }
+                    if (cont) {
+                        continue;
+                    }
+                    // An handler is a root, blocks that are only reachable by it
+                    // can be removed.
+                    Set<ControlFlow.Block> blocks = f.getClosure(blockHandler);
+                    StringBuilder sb = new StringBuilder();
+                    for (ControlFlow.Block b : blocks) {
+                        sb.append(b).append("\n");
+                        removed.add(b.getFirstInstruction().getIndex());
+                        // Remove Exception handler if the associated block has been removed
+                        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
+                            if (tcb != bn) {
+                                // An exception handler removed as a side effect.
+                                if (b.isExceptionHandler()
+                                        && b.getFirstInstruction().getInstr() == tcb.handler) {
+                                    tcbToRemove.add(tcb);
+                                }
+                            }
+                        }
+                    }
+                    blocksToRemove.addAll(blocks);
+
+                    data.removedHandlers.put(ex, blocks);
+
+                }
+            }
+
+            m.tryCatchBlocks.removeAll(tcbToRemove);
+
+            if (!blocksToRemove.isEmpty()) {
+                for (ControlFlow.Block b : blocksToRemove) {
+                    for (ControlFlow.InstructionNode ins : b.getInstructions()) {
+                        if (ins.getInstr().getOpcode() > 0) {
+                            instructionsRemoved += 1;
+                        }
+                    }
+                }
+                Utils.suppressBlocks(m, blocksToRemove);
+            }
+        }
+        return instructionsRemoved;
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java
new file mode 100644
index 0000000..2e75127
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal.plugins.optim;
+
+import java.util.Iterator;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
+
+/**
+ * Optimization utility methods
+ */
+public class Utils {
+
+    public static boolean canThrowCheckedException(ReflectionOptimizer.TypeResolver cch,
+            ClassNode classNode, MethodNode m, TryCatchBlockNode bn) throws Exception {
+        int istart = m.instructions.indexOf(bn.start);
+        int iend = m.instructions.indexOf(bn.end);
+        for (int i = istart; i < iend - 1; i++) {
+            AbstractInsnNode instr = m.instructions.get(i);
+            if (instr instanceof MethodInsnNode) {
+                MethodInsnNode meth = (MethodInsnNode) instr;
+                ClassReader reader = cch.resolve(classNode, m, meth.owner);
+                if (reader != null) {
+                    ClassNode cn = new ClassNode();
+                    reader.accept(cn, ClassReader.EXPAND_FRAMES);
+                    for (MethodNode method : cn.methods) {
+                        if (method.name.equals(meth.name)) {
+                            for (String e : method.exceptions) {
+                                if (e.equals(bn.type)) {
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static void suppressBlocks(MethodNode m, Set<ControlFlow.Block> toRemove) throws Exception {
+        m.instructions.resetLabels();
+        Iterator<AbstractInsnNode> it = m.instructions.iterator();
+        while (it.hasNext()) {
+            AbstractInsnNode n = it.next();
+            Iterator<TryCatchBlockNode> handlers = m.tryCatchBlocks.iterator();
+            boolean cont = false;
+            // Do not delete instructions that are end of other try block.
+            while (handlers.hasNext()) {
+                TryCatchBlockNode handler = handlers.next();
+                if (handler.end == n) {
+                    cont = true;
+                }
+            }
+            if (cont) {
+                continue;
+            }
+
+            for (ControlFlow.Block b : toRemove) {
+                for (ControlFlow.InstructionNode ins : b.getInstructions()) {
+                    if (ins.getInstr() == n) {
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
new file mode 100644
index 0000000..d5e767c
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ExecutableImage.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * An executable runtime image. Instance of this class contains the information
+ * needed to create image processes.
+ */
+public abstract class ExecutableImage {
+
+    private final Path home;
+    private final List<String> args;
+    private final Set<String> modules;
+
+    protected ExecutableImage(Path home, Set<String> modules,
+            List<String> args) {
+        Objects.requireNonNull(home);
+        Objects.requireNonNull(args);
+        if (!Files.exists(home)) {
+            throw new IllegalArgumentException("Invalid image home");
+        }
+        this.home = home;
+        this.modules = Collections.unmodifiableSet(modules);
+        this.args = Collections.unmodifiableList(args);
+    }
+
+    /**
+     * Image home directory,
+     *
+     * @return The home directory.
+     */
+    public Path getHome() {
+        return home;
+    }
+
+    /**
+     * The names of the modules located in the image.
+     *
+     * @return The set of modules.
+     */
+    public Set<String> getModules() {
+        return modules;
+    }
+
+    /**
+     * The list of arguments required to execute the image.
+     *
+     * @return The list of arguments.
+     */
+    public List<String> getExecutionArgs() {
+        return args;
+    }
+
+    /**
+     * Store new arguments required to execute the image.
+     *
+     * @param args Additional arguments
+     */
+    public abstract void storeLaunchArgs(List<String> args);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
new file mode 100644
index 0000000..6027866
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
+
+/**
+ * Base interface that jlink plugins should implement.
+ */
+public interface Plugin {
+
+    /**
+     * Type of plugin.
+     */
+    public interface PluginType {
+
+        public String getName();
+    }
+
+    /**
+     * Order of categories:
+     * <ol>
+     * <li>FILTER: Filter in/out resources or files.</li>
+     * <li>TRANSFORMER: Transform resources or files(eg: refactoring, bytecode
+     * manipulation).</li>
+     * <li>MODULEINFO_TRANSFORMER: Transform only module-info.class</li>
+     * <li>SORTER: Sort resources within the resource container.</li>
+     * <li>COMPRESSOR: Compress resource within the resouce containers.</li>
+     * <li>VERIFIER: Does some image verification.</li>
+     * <li>PROCESSOR: Does some post processing on image.</li>
+     * <li>PACKAGER: Final processing</li>
+     * </ol>
+     */
+    public enum CATEGORY implements PluginType {
+        FILTER("FILTER"),
+        TRANSFORMER("TRANSFORMER"),
+        MODULEINFO_TRANSFORMER("MODULEINFO_TRANSFORMER"),
+        SORTER("SORTER"),
+        COMPRESSOR("COMPRESSOR"),
+        VERIFIER("VERIFIER"),
+        PROCESSOR("PROCESSOR"),
+        PACKAGER("PACKAGER");
+
+        private final String name;
+
+        CATEGORY(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+    }
+
+    /**
+     * Plugin state:
+     * <ul>
+     * <li>DISABLED: The plugin is not exposed in help and will be not called.</li>
+     * <li>AUTO_ENABLED: The plugin is enabled by default. It doesn't require its
+     * option to be present to be called.<li>
+     * <li>FUNCTIONAL: The plugin is properly configured and can operate.
+     * Non functional plugin must advertise their status in the
+     * {@link #getStateDescription() getStateDescription} method</li>
+     * </ul>
+     */
+    public enum STATE {
+        DISABLED,
+        AUTO_ENABLED,
+        FUNCTIONAL
+    }
+
+    /**
+     * The Plugin set of types.
+     * @return The set of types.
+     */
+    public default Set<PluginType> getType() {
+        return Collections.emptySet();
+    }
+
+    /**
+     * The Plugin set of states.
+     * @return The set of states.
+     */
+    public default Set<STATE> getState() {
+        return EnumSet.of(STATE.FUNCTIONAL);
+    }
+
+    /**
+     * The set of plugin names that must be located, within the stack of plugins,
+     * before this plugin.
+     * @return The set of names. By default this set is empty.
+     */
+    public default Set<String> isBefore() {
+        return Collections.emptySet();
+    }
+
+    /**
+     * The set of plugin names that must be located, within the stack of plugins,
+     * after this plugin.
+     * @return The set of names. By default this set is empty.
+     */
+    public default Set<String> isAfter() {
+        return Collections.emptySet();
+    }
+
+    /**
+     * The plugin name.
+     * @return The name.
+     */
+    public default String getName() {
+        return getClass().getName().replace('.', '-');
+    }
+
+    /**
+     * The plugin description.
+     * @return  The description.
+     */
+    public default String getDescription() {
+        return "";
+    }
+
+    /**
+     * The option that identifies this plugin. This may be null.
+     * "--" is prefixed to the String (when non-null) when invoking
+     * this plugin from jlink command line.
+     *
+     * @return The plugin option.
+     */
+    public default String getOption() {
+        return getName();
+    }
+
+    /**
+     * Has this plugin require one or more arguments?
+     * A plugin can have one or more optional arguments.
+     * <br>
+     * A plugin option with a single argument is specified as follows:
+     * <pre>
+     *     --plugin-option=arg_value
+     * </pre>
+     * If there are more than arguments, command line option looks like:
+     * <pre>
+     *     --plugin-option=arg_value:arg2=value2:arg3=value3...
+     *</pre>
+     *
+     * @return true if arguments are needed.
+     */
+    public default boolean hasArguments() {
+        return false;
+    }
+
+    /**
+     * The plugin argument(s) description.
+     * @return  The argument(s) description.
+     */
+    public default String getArgumentsDescription() {
+        return "";
+    }
+
+    /**
+     * Return a message indicating the status of the provider.
+     *
+     * @return A status description.
+     */
+    public default String getStateDescription() {
+        return getState().contains(STATE.FUNCTIONAL)
+                ? PluginsResourceBundle.getMessage("main.status.ok")
+                : PluginsResourceBundle.getMessage("main.status.not.ok");
+    }
+
+    /**
+     * Configure the plugin based on the passed configuration.
+     * This method is called prior to invoke the plugin.
+     *
+     * @param config The plugin configuration.
+     */
+    public default void configure(Map<String, String> config) {
+    }
+
+    /**
+     * Configure the plugin based on the passed configuration.
+     * This method is called prior to invoke the plugin.
+     *
+     * @param config The plugin configuration.
+     * @param ctx The plugin context
+     */
+    public default void configure(Map<String, String> config, PluginContext ctx) {
+        configure(config);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java
new file mode 100644
index 0000000..9e5a4a7
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginContext.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.util.Properties;
+
+/**
+ * Interface to plugin (container) context.
+ */
+public interface PluginContext {
+    /**
+     * Returns 'release' properties
+     */
+    public Properties getReleaseProperties();
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginException.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginException.java
new file mode 100644
index 0000000..c906b3a
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PluginException.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+/**
+ * An unchecked exception thrown by jlink plugin API for unrecoverable
+ * conditions.
+ */
+public final class PluginException extends RuntimeException {
+
+    private static final long serialVersionUID = 7117982019443100395L;
+
+    public PluginException() {
+
+    }
+
+    public PluginException(Throwable ex) {
+        super(ex);
+    }
+
+    public PluginException(String msg) {
+        super(msg);
+    }
+
+    public PluginException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java
new file mode 100644
index 0000000..3645f57
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import jdk.tools.jlink.internal.ImageFileCreator;
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+
+/**
+ * Pool of module data.
+ *
+ */
+public abstract class Pool {
+
+    /**
+     * Interface to visit the content of a Pool.
+     */
+    public interface Visitor {
+
+        /**
+         * Called for each visited ModuleData.
+         *
+         * @param content A ModuleData
+         * @return A ModuleData instance or null if the passed ModuleData is to
+         * be removed from the image.
+         * @throws PluginException
+         */
+        public ModuleData visit(ModuleData content);
+    }
+
+    /**
+     * Type of module data.
+     * <li>
+     * <ul>CLASS_OR_RESOURCE: A java class or resource file.</ul>
+     * <ul>CONFIG: A configuration file.</ul>
+     * <ul>NATIVE_CMD: A native process launcher.</ul>
+     * <ul>NATIVE_LIB: A native library.</ul>
+     * <ul>OTHER: Other kind of file.</ul>
+     * </li>
+     */
+    public static enum ModuleDataType {
+
+        CLASS_OR_RESOURCE,
+        CONFIG,
+        NATIVE_CMD,
+        NATIVE_LIB,
+        OTHER;
+    }
+
+    /**
+     * A module in the pool.
+     */
+    public interface Module {
+
+        /**
+         * The module name.
+         *
+         * @return The name.
+         */
+        public String getName();
+
+        /**
+         * Retrieves a ModuleData from a path (e.g:
+         * /mymodule/com.foo.bar/MyClass.class)
+         *
+         * @param path The piece of data path.
+         * @return A ModuleData or null if the path doesn't identify a
+         * ModuleData.
+         */
+        public ModuleData get(String path);
+
+        /**
+         * The module descriptor of this module.
+         *
+         * @return The module descriptor.
+         */
+        public ModuleDescriptor getDescriptor();
+
+        /**
+         * Add a ModuleData to this module.
+         *
+         * @param data The ModuleData to add.
+         */
+        public void add(ModuleData data);
+
+        /**
+         * Retrieves all the packages located in this module.
+         *
+         * @return The set of packages.
+         */
+        public Set<String> getAllPackages();
+
+        /**
+         * Retrieves the collection of ModuleData.
+         *
+         * @return The ModuleData collection.
+         */
+        public Collection<ModuleData> getContent();
+
+    }
+
+    private class ModuleImpl implements Module {
+
+        private final Map<String, ModuleData> moduleContent = new LinkedHashMap<>();
+        private ModuleDescriptor descriptor;
+        private final String name;
+
+        private ModuleImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public ModuleData get(String path) {
+            if (!path.startsWith("/")) {
+                path = "/" + path;
+            }
+            if (!path.startsWith("/" + name)) {
+                path = "/" + name + path;
+            }
+            return moduleContent.get(path);
+        }
+
+        @Override
+        public ModuleDescriptor getDescriptor() {
+            if (descriptor == null) {
+                String p = "/" + name + "/module-info.class";
+                ModuleData content = moduleContent.get(p);
+                if (content == null) {
+                    throw new PluginException("No module-info for " + name
+                            + " module");
+                }
+                ByteBuffer bb = ByteBuffer.wrap(content.getBytes());
+                descriptor = ModuleDescriptor.read(bb);
+            }
+            return descriptor;
+        }
+
+        @Override
+        public void add(ModuleData data) {
+            if (isReadOnly()) {
+                throw new PluginException("pool is readonly");
+            }
+            Objects.requireNonNull(data);
+            if (!data.getModule().equals(name)) {
+                throw new PluginException("Can't add resource " + data.getPath()
+                        + " to module " + name);
+            }
+            Pool.this.add(data);
+        }
+
+        @Override
+        public Set<String> getAllPackages() {
+            Set<String> pkgs = new HashSet<>();
+            moduleContent.values().stream().filter(m -> m.getType().
+                    equals(ModuleDataType.CLASS_OR_RESOURCE)).forEach((res) -> {
+                // Module metadata only contains packages with .class files
+                if (ImageFileCreator.isClassPackage(res.getPath())) {
+                    String[] split = ImageFileCreator.splitPath(res.getPath());
+                    String pkg = split[1];
+                    if (pkg != null && !pkg.isEmpty()) {
+                        pkgs.add(pkg);
+                    }
+                }
+            });
+            return pkgs;
+        }
+
+        @Override
+        public String toString() {
+            return getName();
+        }
+
+        @Override
+        public Collection<ModuleData> getContent() {
+            return Collections.unmodifiableCollection(moduleContent.values());
+        }
+    }
+
+    /**
+     * A ModuleData is the elementary unit of data inside an image. It is
+     * generally a file. e.g.: a java class file, a resource file, a shared
+     * library, ...
+     * <br>
+     * A ModuleData is identified by a path of the form:
+     * <ul>
+     * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+     * name}</li>
+     * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+     * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+     * </ul>
+     */
+    public static class ModuleData {
+
+        private final ModuleDataType type;
+        private final String path;
+        private final String module;
+        private final long length;
+        private final InputStream stream;
+        private byte[] buffer;
+
+        /**
+         * Create a new ModuleData.
+         *
+         * @param module The module name.
+         * @param path The data path identifier.
+         * @param type The data type.
+         * @param stream The data content stream.
+         * @param length The stream length.
+         */
+        public ModuleData(String module, String path, ModuleDataType type,
+                InputStream stream, long length) {
+            Objects.requireNonNull(module);
+            Objects.requireNonNull(path);
+            Objects.requireNonNull(type);
+            Objects.requireNonNull(stream);
+            this.path = path;
+            this.type = type;
+            this.module = module;
+            this.stream = stream;
+            this.length = length;
+        }
+
+        /**
+         * The ModuleData module name.
+         *
+         * @return The module name.
+         */
+        public final String getModule() {
+            return module;
+        }
+
+        /**
+         * The ModuleData path.
+         *
+         * @return The module path.
+         */
+        public final String getPath() {
+            return path;
+        }
+
+        /**
+         * The ModuleData type.
+         *
+         * @return The data type.
+         */
+        public final ModuleDataType getType() {
+            return type;
+        }
+
+        /**
+         * The ModuleData content as an array of byte.
+         *
+         * @return An Array of bytes.
+         */
+        public byte[] getBytes() {
+            if (buffer == null) {
+                try {
+                    buffer = stream.readAllBytes();
+                } catch (IOException ex) {
+                    throw new UncheckedIOException(ex);
+                }
+            }
+            return buffer;
+        }
+
+        /**
+         * The ModuleData content length.
+         *
+         * @return The length.
+         */
+        public long getLength() {
+            return length;
+        }
+
+        /**
+         * The ModuleData stream.
+         *
+         * @return The module data stream.
+         */
+        public InputStream stream() {
+            return stream;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 89 * hash + Objects.hashCode(this.path);
+            return hash;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof ModuleData)) {
+                return false;
+            }
+            ModuleData f = (ModuleData) other;
+            return f.path.equals(path);
+        }
+
+        @Override
+        public String toString() {
+            return getPath();
+        }
+    }
+
+    private final Map<String, ModuleData> resources = new LinkedHashMap<>();
+    private final Map<String, ModuleImpl> modules = new LinkedHashMap<>();
+    private final ModuleImpl fileCopierModule = new ModuleImpl(FileCopierPlugin.FAKE_MODULE);
+
+    private final ByteOrder order;
+
+    protected Pool() {
+        this(ByteOrder.nativeOrder());
+    }
+
+    protected Pool(ByteOrder order) {
+        Objects.requireNonNull(order);
+        this.order = order;
+    }
+
+    /**
+     * Read only state. No data can be added to a ReadOnly Pool.
+     *
+     * @return true if readonly false otherwise.
+     */
+    public abstract boolean isReadOnly();
+
+    /**
+     * Add a ModuleData.
+     *
+     * @param data The ModuleData to add.
+     */
+    public void add(ModuleData data) {
+        if (isReadOnly()) {
+            throw new PluginException("pool is readonly");
+        }
+        Objects.requireNonNull(data);
+        if (resources.get(data.getPath()) != null) {
+            throw new PluginException("Resource " + data.getPath()
+                    + " already present");
+        }
+        String modulename = data.getModule();
+        ModuleImpl m = modules.get(modulename);
+        // ## TODO: FileCopierPlugin should not add content to a module
+        // FAKE_MODULE is not really a module to be added in the image
+        if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
+            m = fileCopierModule;
+        }
+        if (m == null) {
+            m = new ModuleImpl(modulename);
+            modules.put(modulename, m);
+        }
+        resources.put(data.getPath(), data);
+        m.moduleContent.put(data.getPath(), data);
+    }
+
+    /**
+     * Retrieves the module for the provided name.
+     *
+     * @param name The module name
+     * @return the module or null if the module doesn't exist.
+     */
+    public Module getModule(String name) {
+        Objects.requireNonNull(name);
+        return modules.get(name);
+    }
+
+    /**
+     * The collection of modules contained in this pool.
+     *
+     * @return The collection of modules.
+     */
+    public Collection<Module> getModules() {
+        return Collections.unmodifiableCollection(modules.values());
+    }
+
+    /**
+     * Get all ModuleData contained in this pool instance.
+     *
+     * @return The collection of resources;
+     */
+    public Collection<ModuleData> getContent() {
+        return Collections.unmodifiableCollection(resources.values());
+    }
+
+    /**
+     * Get the ModuleData for the passed path.
+     *
+     * @param path A data path
+     * @return A ModuleData instance or null if the data is not found
+     */
+    public ModuleData get(String path) {
+        Objects.requireNonNull(path);
+        return resources.get(path);
+    }
+
+    /**
+     * Check if the pool contains this data.
+     *
+     * @param data The module data to check existence for.
+     * @return The module data or null if not found.
+     */
+    public boolean contains(ModuleData data) {
+        Objects.requireNonNull(data);
+        return get(data.getPath()) != null;
+    }
+
+    /**
+     * Check if the Pool contains some content.
+     *
+     * @return True, no content, false otherwise.
+     */
+    public boolean isEmpty() {
+        return resources.isEmpty();
+    }
+
+    /**
+     * Visit the pool.
+     *
+     * @param visitor The Visitor called for each ModuleData found in the pool.
+     * @param output The pool to be filled with Visitor returned ModuleData.
+     */
+    public void visit(Visitor visitor, Pool output) {
+        for (ModuleData resource : getContent()) {
+            ModuleData res = visitor.visit(resource);
+            if (res != null) {
+                output.add(res);
+            }
+        }
+    }
+
+    /**
+     * The ByteOrder currently in use when generating the jimage file.
+     *
+     * @return The ByteOrder.
+     */
+    public ByteOrder getByteOrder() {
+        return order;
+    }
+
+    /**
+     * Create a ModuleData located inside a jimage file. Such ModuleData has a
+     * ModuleDataType being equals to CLASS_OR_RESOURCE.
+     *
+     * @param path The complete resource path (contains the module radical).
+     * @param content The resource content.
+     * @param size The content size.
+     * @return A new ModuleData.
+     */
+    public static ModuleData newResource(String path, InputStream content, long size) {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(content);
+        String[] split = ImageFileCreator.splitPath(path);
+        String module = split[0];
+        return new ModuleData(module, path, ModuleDataType.CLASS_OR_RESOURCE, content, size);
+    }
+
+    /**
+     * Create a ModuleData for a file that will be located inside a jimage file.
+     *
+     * @param path The resource path.
+     * @param content The resource content.
+     * @return A new ModuleData.
+     */
+    public static ModuleData newResource(String path, byte[] content) {
+        return newResource(path, new ByteArrayInputStream(content),
+                content.length);
+    }
+
+    /**
+     * Create a ModuleData for a file that will be located outside a jimage
+     * file.
+     *
+     * @param module The module in which this files is located.
+     * @param path The file path locator (doesn't contain the module name).
+     * @param type The ModuleData type.
+     * @param content The file content.
+     * @param size The content size.
+     * @return A new ModuleData.
+     */
+    public static ModuleData newImageFile(String module, String path, ModuleDataType type,
+            InputStream content, long size) {
+        Objects.requireNonNull(path);
+        Objects.requireNonNull(content);
+        return new ModuleData(module, path, type, content, size);
+    }
+
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PostProcessorPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PostProcessorPlugin.java
new file mode 100644
index 0000000..7483a5e
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/PostProcessorPlugin.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+import java.util.List;
+
+/**
+ * Implement this interface to develop a PostProcessor plugin.
+ * PostProcessor plugins are called once the image has been generated and is executable.
+ **/
+public interface PostProcessorPlugin extends Plugin {
+
+    /**
+     * Post process an image.
+     *
+     * @param image The executable image.
+     * @return The list of arguments to add to launchers (if any).
+     */
+    public List<String> process(ExecutableImage image);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
new file mode 100644
index 0000000..4af4897
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/TransformerPlugin.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.plugin;
+
+
+/**
+ * Implement this interface to develop a Transformer plugin.
+ * TransformerPlugin are called during image creation. This kind of plugin aims to
+ * modify the content of the runtime image.
+ */
+public interface TransformerPlugin extends Plugin {
+    /**
+     * Visit the content of the modules that are composing the image.
+     *
+     * @param in Read only content.
+     * @param out The pool to fill with content. This pool must contain
+     * the result of the visit.
+     *
+     * @throws PluginException
+     */
+    public void visit(Pool in, Pool out);
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties
new file mode 100644
index 0000000..c97dc20
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties
@@ -0,0 +1,73 @@
+main.usage.summary=\
+Usage: {0} <options> --modulepath <modulepath> --addmods <mods> --output <path>\n\
+use --help for a list of possible options
+
+main.usage=\
+Usage: {0} <options> --modulepath <modulepath> --addmods <mods> --output <path>\n\
+Possible options include:
+
+error.prefix=Error:
+warn.prefix=Warning:
+
+main.opt.help=\
+\  --help                            Print this help message
+
+main.opt.version=\
+\  --version                         Version information
+
+main.opt.modulepath=\
+\  --modulepath <modulepath>         Module path
+
+main.opt.addmods=\
+\  --addmods <mod>[,<mod>...]        Root modules to resolve
+
+main.opt.limitmods=\
+\  --limitmods <mod>[,<mod>...]      Limit the universe of observable modules
+
+main.opt.output=\
+\  --output <path>                   Location of output path
+
+main.command.files=\
+\  @<filename>                       Read options from file
+
+main.opt.endian=\
+\  --endian <little|big>             Byte order of generated jimage (default:native)
+
+main.opt.genbom=\
+\  --genbom                          Generate a bom file containing jlink info
+
+main.opt.saveopts=\
+\  --saveopts <filename>             Save jlink options in the given file
+
+main.msg.bug=\
+An exception has occurred in jlink. \
+Please file a bug at the Java Bug Database (http://bugreport.java.com/bugreport/) \
+after checking the database for duplicates. \
+Include your program and the following diagnostic in your report.  Thank you.
+
+main.extended.help=\
+List of available plugins:
+
+err.unknown.byte.order:unknown byte order {0}
+err.output.must.be.specified:--output must be specified
+err.modulepath.must.be.specified:--modulepath must be specified
+err.mods.must.be.specified:no modules specified to {0}
+err.path.not.found=path not found: {0}
+err.path.not.valid=invalid path: {0}
+err.existing.image.must.exist=existing image doesn't exists or is not a directory
+err.existing.image.invalid=existing image is not valid
+err.file.not.found=cannot find file: {0}
+err.file.error=cannot access file: {0}
+err.dir.exists={0} already exists
+err.badpattern=bad pattern {0}
+err.unknown.option=unknown option: {0}
+err.missing.arg=no value given for {0}
+err.internal.error=internal error: {0} {1} {2}
+err.invalid.arg.for.option=invalid argument for option: {0}
+err.option.after.class=option must be specified before classes: {0}
+err.option.unsupported={0} not supported: {1}
+err.config.defaults=property {0} is missing from configuration
+err.config.defaults.value=wrong value in defaults property: {0}
+err.bom.generation=bom file generation failed: {0}
+warn.invalid.arg=Invalid classname or pathname not exist: {0}
+warn.split.package=package {0} defined in {1} {2}
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
new file mode 100644
index 0000000..b43e081
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties
@@ -0,0 +1,153 @@
+release-info.argument=<file>|add:<key1>=<value1>:<key2>=<value2>:...|del:<key list>
+
+release-info.description=\
+<file> option is to load release properties from the supplied file.\n\
+add: is to add properties to the 'release' file.\n\
+Any number of <key>=<value> pairs can be passed.\n\
+del: is to delete the list of keys in release file.
+
+class-optim.argument=<all|forName-folding>[:log=<log file>]
+
+class-optim.description=\
+Class optimization. Warning: This plugin is experimental.\n\
+An optional <log file> can be specified to log applied optimizations.
+
+compress.argument=<0|1|2>[:filter=<pattern>]
+
+compress.description=\
+Compress all resources in the output image.\n\
+Level 0: constant string sharing\n\
+Level 1: ZIP\n\
+Level 2: both.\n\
+An optional filter can be specified to list the pattern of files to be filtered.\n\
+Use ^ for negation. eg: *Exception.class,*Error.class,^/java.base/java/lang/*
+
+compact-cp.argument=<resource paths>
+
+compact-cp.description=Constant Pool strings sharing.\n\
+By default, all resources are compressed. You can express the set \n\
+of resources to compress or not compress (use ^ for negation).
+
+copy-files.argument=<List of <file path>=<image target> to copy to the image>.
+
+copy-files.description=\
+If files to copy are not absolute path, JDK home dir is used.\n\
+eg: jrt-fs.jar,LICENSE,/home/me/myfile.txt=somewehere/conf.txt
+
+exclude-files.argument=<files to exclude | files of excluded files>
+
+exclude-files.description=\
+Specify files to exclude. eg: *.diz, /java.base/native/client/*
+
+exclude-resources.argument=<resources to exclude | file of excluded resources>
+
+exclude-resources.description=\
+Specify resources to exclude. eg: *.jcov, */META-INF/*
+
+installed-modules.description=Fast loading of module descriptors (always enabled)
+
+onoff.argument=<on|off>
+
+sort-resources.argument=<paths in priority order | file with resource paths>
+
+sort-resources.description=\
+Sort resources. eg: */modules-info.class,/java-base/java/lang/*
+
+strip-debug.description=\
+Strip debug information from the output image
+
+strip-native-commands.description=\
+Exclude native commands (such as java/java.exe) from the image
+
+vm.argument=<client|server|minimal|all>
+
+vm.description=\
+Select the HotSpot VM in the output image.  Default is all
+ 
+zip.argument=[comma separated list of resource paths]
+
+zip.description=ZIP Compression
+
+include-locales.argument=<langtag>[,<langtag>]*
+
+include-locales.description=BCP 47 language tags separated by a comma, allowing locale matching\ndefined in RFC 4647. eg: en,ja,*-IN
+
+main.status.ok=Functional.
+
+main.status.not.ok= Not functional.
+
+plugin.plugins.header=\
+List of available plugin options:
+
+plugin.opt.list-plugins=\
+\  --list-plugins                    List available plugins
+
+plugin.opt.post-process-path=\
+\  --post-process-path <imagefile>   Post process an existing image
+
+plugin.opt.resources-last-sorter=\
+\  --resources-last-sorter <name>    The last plugin allowed to sort resources
+
+plugin.opt.plugins-modulepath=\
+\  --plugin-module-path <modulepath> Custom plugins module path
+
+plugin.opt.c=\
+\  -c, --compress=2                  Enable compression of resources (level 2)
+
+plugin.opt.G=\
+\  -G, --strip-debug                 Strip debug information
+
+main.plugin.name=\
+\Plugin Name
+
+main.plugin.class=\
+\Plugin Class
+
+main.plugin.module=\
+\Plugin Module
+
+main.plugin.category=\
+\Category
+
+main.plugin.description=\
+\Description
+
+main.plugin.post.processors=\
+Image Post Processors:
+
+main.plugin.argument=\
+\Argument
+
+main.plugin.range.from=\
+Range from
+
+main.plugin.range.to=\
+to
+
+main.plugin.option=\
+\Option
+
+main.plugin.no.value=\
+\<empty>
+
+main.plugin.state=\
+Functional state
+
+err.provider.not.functional=The provider {0} is not functional.
+
+err.plugin.mutiple.options=More than one plugin enabled by {0} option
+err.provider.additional.arg.error=Error in additional argument specification in {0} option: {1}
+
+err.no.plugins.path=No plugins path argument.
+
+err.dir.already.exits=directory already exists: {0} 
+
+err.invalid.index=invalid index for option {0}
+
+err.plugin.option.not.set=Option {0} must be set.
+
+warn.thirdparty.plugins=\
+Enabling third party plugins can lead to unusable generated image.
+
+warn.thirdparty.plugins.enabled=\
+You have enabled third party plugins.
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
new file mode 100644
index 0000000..2d13cda
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
@@ -0,0 +1,1174 @@
+/*
+ * 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 jdk.tools.jmod;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.lang.module.FindException;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import jdk.internal.joptsimple.BuiltinHelpFormatter;
+import jdk.internal.joptsimple.NonOptionArgumentSpec;
+import jdk.internal.joptsimple.OptionDescriptor;
+import jdk.internal.joptsimple.OptionException;
+import jdk.internal.joptsimple.OptionParser;
+import jdk.internal.joptsimple.OptionSet;
+import jdk.internal.joptsimple.OptionSpec;
+import jdk.internal.joptsimple.ValueConverter;
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.ConfigurableModuleFinder.Phase;
+import jdk.internal.module.Hasher;
+import jdk.internal.module.Hasher.DependencyHashes;
+import jdk.internal.module.ModuleInfoExtender;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+
+/**
+ * Implementation for the jmod tool.
+ */
+public class JmodTask {
+
+    static class CommandException extends RuntimeException {
+        private static final long serialVersionUID = 0L;
+        boolean showUsage;
+
+        CommandException(String key, Object... args) {
+            super(getMessageOrKey(key, args));
+        }
+
+        CommandException showUsage(boolean b) {
+            showUsage = b;
+            return this;
+        }
+
+        private static String getMessageOrKey(String key, Object... args) {
+            try {
+                return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
+            } catch (MissingResourceException e) {
+                return key;
+            }
+        }
+    }
+
+    static <T extends Throwable> void fail(Class<T> type,
+                                           String format,
+                                           Object... args) throws T {
+        String msg = new Formatter().format(format, args).toString();
+        try {
+            T t = type.getConstructor(String.class).newInstance(msg);
+            throw t;
+        } catch (InstantiationException |
+                 InvocationTargetException |
+                 NoSuchMethodException |
+                 IllegalAccessException e) {
+            throw new InternalError("Unable to create an instance of " + type, e);
+        }
+    }
+
+    private static final String PROGNAME = "jmod";
+    private static final String MODULE_INFO = "module-info.class";
+
+    private Options options;
+    private PrintStream out = System.out;
+    void setLog(PrintStream out) {
+        this.out = out;
+    }
+
+    /* Result codes. */
+    static final int EXIT_OK = 0, // Completed with no errors.
+                     EXIT_ERROR = 1, // Completed but reported errors.
+                     EXIT_CMDERR = 2, // Bad command-line arguments
+                     EXIT_SYSERR = 3, // System error or resource exhaustion.
+                     EXIT_ABNORMAL = 4;// terminated abnormally
+
+    enum Mode {
+        CREATE,
+        LIST,
+        DESCRIBE
+    };
+
+    static class Options {
+        Mode mode;
+        Path jmodFile;
+        boolean help;
+        boolean version;
+        List<Path> classpath;
+        List<Path> cmds;
+        List<Path> configs;
+        List<Path> libs;
+        ModuleFinder moduleFinder;
+        Version moduleVersion;
+        String mainClass;
+        String osName;
+        String osArch;
+        String osVersion;
+        Pattern dependenciesToHash;
+        List<PathMatcher> excludes;
+    }
+
+    public int run(String[] args) {
+
+        try {
+            handleOptions(args);
+            if (options == null) {
+                showUsageSummary();
+                return EXIT_CMDERR;
+            }
+            if (options.help) {
+                showHelp();
+                return EXIT_OK;
+            }
+            if (options.version) {
+                showVersion();
+                return EXIT_OK;
+            }
+
+            boolean ok;
+            switch (options.mode) {
+                case CREATE:
+                    ok = create();
+                    break;
+                case LIST:
+                    ok = list();
+                    break;
+                case DESCRIBE:
+                    ok = describe();
+                    break;
+                default:
+                    throw new AssertionError("Unknown mode: " + options.mode.name());
+            }
+
+            return ok ? EXIT_OK : EXIT_ERROR;
+        } catch (CommandException e) {
+            reportError(e.getMessage());
+            if (e.showUsage)
+                showUsageSummary();
+            return EXIT_CMDERR;
+        } catch (Exception x) {
+            reportError(x.getMessage());
+            x.printStackTrace();
+            return EXIT_ABNORMAL;
+        } finally {
+            out.flush();
+        }
+    }
+
+    private boolean list() throws IOException {
+        ZipFile zip = null;
+        try {
+            try {
+                zip = new ZipFile(options.jmodFile.toFile());
+            } catch (IOException x) {
+                throw new IOException("error opening jmod file", x);
+            }
+
+            // Trivially print the archive entries for now, pending a more complete implementation
+            zip.stream().forEach(e -> out.println(e.getName()));
+            return true;
+        } finally {
+            if (zip != null)
+                zip.close();
+        }
+    }
+
+    private Map<String, Path> modulesToPath(Set<ModuleDescriptor> modules) {
+        ModuleFinder finder = options.moduleFinder;
+
+        Map<String,Path> modPaths = new HashMap<>();
+        for (ModuleDescriptor m : modules) {
+            String name = m.name();
+
+            Optional<ModuleReference> omref = finder.find(name);
+            if (!omref.isPresent()) {
+                // this should not happen, module path bug?
+                fail(InternalError.class,
+                     "Selected module %s not on module path",
+                     name);
+            }
+
+            URI uri = omref.get().location().get();
+            modPaths.put(name, Paths.get(uri));
+
+        }
+        return modPaths;
+    }
+
+    private boolean describe() throws IOException {
+        ZipFile zip = null;
+        try {
+            try {
+                zip = new ZipFile(options.jmodFile.toFile());
+            } catch (IOException x) {
+                throw new IOException("error opening jmod file", x);
+            }
+
+            try (InputStream in = Files.newInputStream(options.jmodFile)) {
+                boolean found = printModuleDescriptor(in);
+                if (!found)
+                    throw new CommandException("err.module.descriptor.not.found");
+                return found;
+            }
+        } finally {
+            if (zip != null)
+                zip.close();
+        }
+    }
+
+    static <T> String toString(Set<T> set) {
+        if (set.isEmpty()) { return ""; }
+        return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
+                  .collect(joining(" "));
+    }
+
+    private boolean printModuleDescriptor(InputStream in)
+        throws IOException
+    {
+        final String mi = Section.CLASSES.jmodDir() + "/" + MODULE_INFO;
+        try (BufferedInputStream bis = new BufferedInputStream(in);
+             ZipInputStream zis = new ZipInputStream(bis)) {
+
+            ZipEntry e;
+            while ((e = zis.getNextEntry()) != null) {
+                if (e.getName().equals(mi)) {
+                    ModuleDescriptor md = ModuleDescriptor.read(zis);
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("\n").append(md.toNameAndVersion());
+
+                    List<Requires> requires = md.requires().stream().sorted().collect(toList());
+                    if (!requires.isEmpty()) {
+                        requires.forEach(r -> {
+                                sb.append("\n  requires ");
+                                if (!r.modifiers().isEmpty())
+                                  sb.append(toString(r.modifiers())).append(" ");
+                                sb.append(r.name());
+                            });
+                    }
+
+                    List<String> l = md.uses().stream().sorted().collect(toList());
+                    if (!l.isEmpty()) {
+                        l.forEach(sv -> sb.append("\n  uses ").append(sv));
+                    }
+
+                    List<ModuleDescriptor.Exports> exports = sortExports(md.exports());
+                    if (!exports.isEmpty()) {
+                        exports.forEach(ex -> sb.append("\n  exports ").append(ex));
+                    }
+
+                    l = md.conceals().stream().sorted().collect(toList());
+                    if (!l.isEmpty()) {
+                        l.forEach(p -> sb.append("\n  conceals ").append(p));
+                    }
+
+                    Map<String, ModuleDescriptor.Provides> provides = md.provides();
+                    if (!provides.isEmpty()) {
+                        provides.values().forEach(p ->
+                                sb.append("\n  provides ").append(p.service())
+                                  .append(" with ")
+                                  .append(toString(p.providers())));
+                    }
+
+                    Optional<String> mc = md.mainClass();
+                    if (mc.isPresent())
+                        sb.append("\n  main-class " + mc.get());
+
+
+
+                    Optional<String> osname = md.osName();
+                    if (osname.isPresent())
+                        sb.append("\n  operating-system-name " + osname.get());
+
+                    Optional<String> osarch = md.osArch();
+                    if (osarch.isPresent())
+                        sb.append("\n  operating-system-architecture " + osarch.get());
+
+                    Optional<String> osversion = md.osVersion();
+                    if (osversion.isPresent())
+                        sb.append("\n  operating-system-version " + osversion.get());
+
+                    try {
+                        Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
+                        m.setAccessible(true);
+                        @SuppressWarnings("unchecked")
+                        Optional<Hasher.DependencyHashes> optHashes =
+                                (Optional<Hasher.DependencyHashes>) m.invoke(md);
+
+                        if (optHashes.isPresent()) {
+                            Hasher.DependencyHashes hashes = optHashes.get();
+                            hashes.names().stream().forEach(mod ->
+                                    sb.append("\n  hashes ").append(mod).append(" ")
+                                      .append(hashes.algorithm()).append(" ")
+                                      .append(hashes.hashFor(mod)));
+                        }
+                    } catch (ReflectiveOperationException x) {
+                        throw new InternalError(x);
+                    }
+                    out.println(sb.toString());
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    static List<ModuleDescriptor.Exports> sortExports(Set<ModuleDescriptor.Exports> exports) {
+        Map<String,ModuleDescriptor.Exports> map =
+                exports.stream()
+                       .collect(toMap(ModuleDescriptor.Exports::source,
+                                      identity()));
+        List<String> sources = exports.stream()
+                                      .map(ModuleDescriptor.Exports::source)
+                                      .sorted()
+                                      .collect(toList());
+
+        List<ModuleDescriptor.Exports> l = new ArrayList<>();
+        sources.forEach(e -> l.add(map.get(e)));
+        return l;
+    }
+
+    private boolean create() throws IOException {
+        JmodFileWriter jmod = new JmodFileWriter();
+
+        // create jmod with temporary name to avoid it being examined
+        // when scanning the module path
+        Path target = options.jmodFile;
+        Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+        try {
+            try (OutputStream out = Files.newOutputStream(tempTarget)) {
+                jmod.write(out);
+            }
+            Files.move(tempTarget, target);
+        } catch (Exception e) {
+            if (Files.exists(tempTarget)) {
+                try {
+                    Files.delete(tempTarget);
+                } catch (IOException ioe) {
+                    e.addSuppressed(ioe);
+                }
+            }
+            throw e;
+        }
+        return true;
+    }
+
+    private class JmodFileWriter {
+        final ModuleFinder moduleFinder = options.moduleFinder;
+        final List<Path> cmds = options.cmds;
+        final List<Path> libs = options.libs;
+        final List<Path> configs = options.configs;
+        final List<Path> classpath = options.classpath;
+        final Version moduleVersion = options.moduleVersion;
+        final String mainClass = options.mainClass;
+        final String osName = options.osName;
+        final String osArch = options.osArch;
+        final String osVersion = options.osVersion;
+        final Pattern dependenciesToHash = options.dependenciesToHash;
+        final List<PathMatcher> excludes = options.excludes;
+
+        JmodFileWriter() { }
+
+        /**
+         * Writes the jmod to the given output stream.
+         */
+        void write(OutputStream out) throws IOException {
+            try (ZipOutputStream zos = new ZipOutputStream(out)) {
+
+                // module-info.class
+                writeModuleInfo(zos, findPackages(classpath));
+
+                // classes
+                processClasses(zos, classpath);
+
+                processSection(zos, Section.NATIVE_CMDS, cmds);
+                processSection(zos, Section.NATIVE_LIBS, libs);
+                processSection(zos, Section.CONFIG, configs);
+            }
+        }
+
+        /**
+         * Returns a supplier of an input stream to the module-info.class
+         * on the class path of directories and JAR files.
+         */
+        Supplier<InputStream> newModuleInfoSupplier() throws IOException {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            for (Path e: classpath) {
+                if (Files.isDirectory(e)) {
+                    Path mi = e.resolve(MODULE_INFO);
+                    if (Files.isRegularFile(mi)) {
+                        Files.copy(mi, baos);
+                        break;
+                    }
+                } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) {
+                    try (JarFile jf = new JarFile(e.toFile())) {
+                        ZipEntry entry = jf.getEntry(MODULE_INFO);
+                        if (entry != null) {
+                            jf.getInputStream(entry).transferTo(baos);
+                            break;
+                        }
+                    } catch (ZipException x) {
+                        // Skip. Do nothing. No packages will be added.
+                    }
+                }
+            }
+            if (baos.size() == 0) {
+                return null;
+            } else {
+                byte[] bytes = baos.toByteArray();
+                return () -> new ByteArrayInputStream(bytes);
+            }
+        }
+
+        /**
+         * Writes the updated module-info.class to the ZIP output stream.
+         *
+         * The updated module-info.class will have a ConcealedPackages attribute
+         * with the set of module-private/non-exported packages.
+         *
+         * If --module-version, --main-class, or other options were provided
+         * then the corresponding class file attributes are added to the
+         * module-info here.
+         */
+        void writeModuleInfo(ZipOutputStream zos, Set<String> packages)
+            throws IOException
+        {
+            Supplier<InputStream> miSupplier = newModuleInfoSupplier();
+            if (miSupplier == null) {
+                throw new IOException(MODULE_INFO + " not found");
+            }
+
+            ModuleDescriptor descriptor;
+            try (InputStream in = miSupplier.get()) {
+                descriptor = ModuleDescriptor.read(in);
+            }
+
+            // copy the module-info.class into the jmod with the additional
+            // attributes for the version, main class and other meta data
+            try (InputStream in = miSupplier.get()) {
+                ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
+
+                // Add (or replace) the ConcealedPackages 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);
+                }
+
+                // --main-class
+                if (mainClass != null)
+                    extender.mainClass(mainClass);
+
+                // --os-name, --os-arch, --os-version
+                if (osName != null || osArch != null || osVersion != null)
+                    extender.targetPlatform(osName, osArch, osVersion);
+
+                // --module-version
+                if (moduleVersion != null)
+                    extender.version(moduleVersion);
+
+                // --hash-dependencies
+                if (dependenciesToHash != null) {
+                    String name = descriptor.name();
+                    Set<Requires> dependences = descriptor.requires();
+                    extender.hashes(hashDependences(name, dependences));
+                }
+
+                // write the (possibly extended or modified) module-info.class
+                String e = Section.CLASSES.jmodDir() + "/" + MODULE_INFO;
+                ZipEntry ze = new ZipEntry(e);
+                zos.putNextEntry(ze);
+                extender.write(zos);
+                zos.closeEntry();
+            }
+        }
+
+        /**
+         * Examines the module dependences of the given module
+         * and computes the hash of any module that matches the
+         * pattern {@code dependenciesToHash}.
+         */
+        DependencyHashes hashDependences(String name, Set<Requires> moduleDependences)
+            throws IOException
+        {
+            Set<ModuleDescriptor> descriptors = new HashSet<>();
+            for (Requires md: moduleDependences) {
+                String dn = md.name();
+                if (dependenciesToHash.matcher(dn).find()) {
+                    try {
+                        Optional<ModuleReference> omref = moduleFinder.find(dn);
+                        if (!omref.isPresent()) {
+                            throw new RuntimeException("Hashing module " + name
+                                + " dependencies, unable to find module " + dn
+                                + " on module path");
+                        }
+                        descriptors.add(omref.get().descriptor());
+                    } catch (FindException x) {
+                        throw new IOException("error reading module path", x);
+                    }
+                }
+            }
+
+            Map<String, Path> map = modulesToPath(descriptors);
+            if (map.size() == 0) {
+                return null;
+            } else {
+                // use SHA-256 for now, easy to make this configurable if needed
+                return Hasher.generate(map, "SHA-256");
+            }
+        }
+
+        /**
+         * Returns the set of all packages on the given class path.
+         */
+        Set<String> findPackages(List<Path> classpath) {
+            Set<String> packages = new HashSet<>();
+            for (Path path : classpath) {
+                if (Files.isDirectory(path)) {
+                    packages.addAll(findPackages(path));
+                } else if (Files.isRegularFile(path) && path.toString().endsWith(".jar")) {
+                    try (JarFile jf = new JarFile(path.toString())) {
+                        packages.addAll(findPackages(jf));
+                    } catch (ZipException x) {
+                        // Skip. Do nothing. No packages will be added.
+                    } catch (IOException ioe) {
+                        throw new UncheckedIOException(ioe);
+                    }
+                }
+            }
+            return packages;
+        }
+
+        /**
+         * Returns the set of packages in the given directory tree.
+         */
+        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
+                        .distinct()
+                        .collect(Collectors.toSet());
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            }
+        }
+
+        /**
+         * Returns the set of packages in the given JAR file.
+         */
+        Set<String> findPackages(JarFile jf) {
+            return jf.stream()
+                     .filter(e -> e.getName().endsWith(".class"))
+                     .map(e -> toPackageName(e))
+                     .filter(pkg -> pkg.length() > 0)   // module-info
+                     .distinct()
+                     .collect(Collectors.toSet());
+        }
+
+        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)) {
+                IOException e = new IOException(name  + " in the unnamed package");
+                throw new UncheckedIOException(e);
+            }
+            return "";
+        }
+
+        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 "";
+        }
+
+        void processClasses(ZipOutputStream zos, List<Path> classpaths)
+            throws IOException
+        {
+            if (classpaths == null)
+                return;
+
+            for (Path p : classpaths) {
+                if (Files.isDirectory(p)) {
+                    processSection(zos, Section.CLASSES, p);
+                } else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) {
+                    try (JarFile jf = new JarFile(p.toFile())) {
+                        JarEntryConsumer jec = new JarEntryConsumer(zos, jf);
+                        jf.stream().filter(jec).forEach(jec);
+                    }
+                }
+            }
+        }
+
+        void processSection(ZipOutputStream zos, Section section, List<Path> paths)
+            throws IOException
+        {
+            if (paths == null)
+                return;
+
+            for (Path p : paths)
+                processSection(zos, section, p);
+        }
+
+        void processSection(ZipOutputStream zos, Section section, Path top)
+            throws IOException
+        {
+            final String prefix = section.jmodDir();
+
+            Files.walkFileTree(top, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                    throws IOException
+                {
+                    Path relPath = top.relativize(file);
+                    if (!relPath.toString().equals(MODULE_INFO)
+                            && !matches(relPath, excludes)) {
+                        try (InputStream in = Files.newInputStream(file)) {
+                            writeZipEntry(zos, in, prefix, relPath.toString());
+                        }
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        }
+
+        boolean matches(Path path, List<PathMatcher> matchers) {
+            if (matchers != null) {
+                for (PathMatcher pm : matchers) {
+                    if (pm.matches(path))
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        void writeZipEntry(ZipOutputStream zos, InputStream in, String prefix, String other)
+            throws IOException
+        {
+            String name = Paths.get(prefix, other).toString()
+                               .replace(File.separatorChar, '/');
+            ZipEntry ze = new ZipEntry(name);
+            zos.putNextEntry(ze);
+            in.transferTo(zos);
+            zos.closeEntry();
+        }
+
+        class JarEntryConsumer implements Consumer<JarEntry>, Predicate<JarEntry> {
+            final ZipOutputStream zos;
+            final JarFile jarfile;
+            JarEntryConsumer(ZipOutputStream zos, JarFile jarfile) {
+                this.zos = zos;
+                this.jarfile = jarfile;
+            }
+            @Override
+            public void accept(JarEntry je) {
+                try (InputStream in = jarfile.getInputStream(je)) {
+                    writeZipEntry(zos, in, Section.CLASSES.jmodDir(), je.getName());
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
+                }
+            }
+            @Override
+            public boolean test(JarEntry je) {
+                String name = je.getName();
+                // ## no support for excludes. Is it really needed?
+                return !name.endsWith(MODULE_INFO) && !je.isDirectory();
+            }
+        }
+    }
+
+    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; }
+    }
+
+    static class ClassPathConverter implements ValueConverter<Path> {
+        static final ValueConverter<Path> INSTANCE = new ClassPathConverter();
+
+        private static final Path CWD = Paths.get("");
+
+        @Override
+        public Path convert(String value) {
+            try {
+                Path path = CWD.resolve(value);
+                if (Files.notExists(path))
+                    throw new CommandException("err.path.not.found", path);
+                if (! (Files.isDirectory(path) ||
+                       (Files.isRegularFile(path) && path.toString().endsWith(".jar"))))
+                    throw new CommandException("err.invalid.class.path.entry", path);
+                return path;
+            } catch (InvalidPathException x) {
+                throw new CommandException("err.path.not.valid", value);
+            }
+        }
+
+        @Override  public Class<Path> valueType() { return Path.class; }
+
+        @Override  public String valuePattern() { return "path"; }
+    }
+
+    static class DirPathConverter implements ValueConverter<Path> {
+        static final ValueConverter<Path> INSTANCE = new DirPathConverter();
+
+        private static final Path CWD = Paths.get("");
+
+        @Override
+        public Path convert(String value) {
+            try {
+                Path path = CWD.resolve(value);
+                if (Files.notExists(path))
+                    throw new CommandException("err.path.not.found", path);
+                if (!Files.isDirectory(path))
+                    throw new CommandException("err.path.not.a.dir", path);
+                return path;
+            } catch (InvalidPathException x) {
+                throw new CommandException("err.path.not.valid", value);
+            }
+        }
+
+        @Override  public Class<Path> valueType() { return Path.class; }
+
+        @Override  public String valuePattern() { return "path"; }
+    }
+
+    static class ModuleVersionConverter implements ValueConverter<Version> {
+        @Override
+        public Version convert(String value) {
+            try {
+                return Version.parse(value);
+            } catch (IllegalArgumentException x) {
+                throw new CommandException("err.invalid.version", x.getMessage());
+            }
+        }
+
+        @Override public Class<Version> valueType() { return Version.class; }
+
+        @Override public String valuePattern() { return "module-version"; }
+    }
+
+    static class PatternConverter implements ValueConverter<Pattern> {
+        @Override
+        public Pattern convert(String value) {
+            try {
+                return Pattern.compile(value);
+            } catch (PatternSyntaxException e) {
+                throw new CommandException("err.bad.pattern", value);
+            }
+        }
+
+        @Override public Class<Pattern> valueType() { return Pattern.class; }
+
+        @Override public String valuePattern() { return "pattern"; }
+    }
+
+    static class GlobConverter implements ValueConverter<PathMatcher> {
+        @Override
+        public PathMatcher convert(String pattern) {
+            try {
+                return FileSystems.getDefault()
+                                  .getPathMatcher("glob:" + pattern);
+            } catch (PatternSyntaxException e) {
+                throw new CommandException("err.bad.pattern", pattern);
+            }
+        }
+
+        @Override public Class<PathMatcher> valueType() { return PathMatcher.class; }
+
+        @Override public String valuePattern() { return "pattern"; }
+    }
+
+    /* Support for @<file> in jmod help */
+    private static final String CMD_FILENAME = "@<filename>";
+
+    /**
+     * This formatter is adding the @filename option and does the required
+     * formatting.
+     */
+    private static final class JmodHelpFormatter extends BuiltinHelpFormatter {
+
+        private JmodHelpFormatter() { super(80, 2); }
+
+        @Override
+        public String format(Map<String, ? extends OptionDescriptor> options) {
+            Map<String, OptionDescriptor> all = new HashMap<>();
+            all.putAll(options);
+            all.put(CMD_FILENAME, new OptionDescriptor() {
+                @Override
+                public Collection<String> options() {
+                    List<String> ret = new ArrayList<>();
+                    ret.add(CMD_FILENAME);
+                    return ret;
+                }
+                @Override
+                public String description() { return getMessage("main.opt.cmdfile"); }
+                @Override
+                public List<?> defaultValues() { return Collections.emptyList(); }
+                @Override
+                public boolean isRequired() { return false; }
+                @Override
+                public boolean acceptsArguments() { return false; }
+                @Override
+                public boolean requiresArgument() { return false; }
+                @Override
+                public String argumentDescription() { return null; }
+                @Override
+                public String argumentTypeIndicator() { return null; }
+                @Override
+                public boolean representsNonOptions() { return false; }
+            });
+            String content = super.format(all);
+            StringBuilder builder = new StringBuilder();
+
+            builder.append("\n").append(" Main operation modes:\n  ");
+            builder.append(getMessage("main.opt.mode.create")).append("\n  ");
+            builder.append(getMessage("main.opt.mode.list")).append("\n  ");
+            builder.append(getMessage("main.opt.mode.describe")).append("\n\n");
+
+            String cmdfile = null;
+            String[] lines = content.split("\n");
+            for (String line : lines) {
+                if (line.startsWith("--@")) {
+                    cmdfile = line.replace("--" + CMD_FILENAME, CMD_FILENAME + "  ");
+                } else if (line.startsWith("Option") || line.startsWith("------")) {
+                    builder.append(" ").append(line).append("\n");
+                } else if (!line.matches("Non-option arguments")){
+                    builder.append("  ").append(line).append("\n");
+                }
+            }
+            if (cmdfile != null) {
+                builder.append("  ").append(cmdfile).append("\n");
+            }
+            return builder.toString();
+        }
+    }
+
+    private final OptionParser parser = new OptionParser();
+
+    private void handleOptions(String[] args) {
+        parser.formatHelpWith(new JmodHelpFormatter());
+
+        OptionSpec<Path> classPath
+                = parser.accepts("class-path", getMessage("main.opt.class-path"))
+                        .withRequiredArg()
+                        .withValuesSeparatedBy(File.pathSeparatorChar)
+                        .withValuesConvertedBy(ClassPathConverter.INSTANCE);
+
+        OptionSpec<Path> cmds
+                = parser.accepts("cmds", getMessage("main.opt.cmds"))
+                        .withRequiredArg()
+                        .withValuesSeparatedBy(File.pathSeparatorChar)
+                        .withValuesConvertedBy(DirPathConverter.INSTANCE);
+
+        OptionSpec<Path> config
+                = parser.accepts("config", getMessage("main.opt.config"))
+                        .withRequiredArg()
+                        .withValuesSeparatedBy(File.pathSeparatorChar)
+                        .withValuesConvertedBy(DirPathConverter.INSTANCE);
+
+        OptionSpec<PathMatcher> excludes
+                = parser.accepts("exclude", getMessage("main.opt.exclude"))
+                        .withRequiredArg()
+                        .withValuesConvertedBy(new GlobConverter());
+
+        OptionSpec<Pattern> hashDependencies
+                = parser.accepts("hash-dependencies", getMessage("main.opt.hash-dependencies"))
+                        .withRequiredArg()
+                        .withValuesConvertedBy(new PatternConverter());
+
+        OptionSpec<Void> help
+                = parser.accepts("help", getMessage("main.opt.help"))
+                        .forHelp();
+
+        OptionSpec<Path> libs
+                = parser.accepts("libs", getMessage("main.opt.libs"))
+                        .withRequiredArg()
+                        .withValuesSeparatedBy(File.pathSeparatorChar)
+                        .withValuesConvertedBy(DirPathConverter.INSTANCE);
+
+        OptionSpec<String> mainClass
+                = parser.accepts("main-class", getMessage("main.opt.main-class"))
+                        .withRequiredArg()
+                        .describedAs(getMessage("main.opt.main-class.arg"));
+
+        OptionSpec<Path> modulePath  // TODO: short version of --mp ??
+                = parser.acceptsAll(Arrays.asList("mp", "modulepath"),
+                                    getMessage("main.opt.modulepath"))
+                        .withRequiredArg()
+                        .withValuesSeparatedBy(File.pathSeparatorChar)
+                        .withValuesConvertedBy(DirPathConverter.INSTANCE);
+
+        OptionSpec<Version> moduleVersion
+                = parser.accepts("module-version", getMessage("main.opt.module-version"))
+                        .withRequiredArg()
+                        .withValuesConvertedBy(new ModuleVersionConverter());
+
+        OptionSpec<String> osName
+                = parser.accepts("os-name", getMessage("main.opt.os-name"))
+                        .withRequiredArg()
+                        .describedAs(getMessage("main.opt.os-name.arg"));
+
+        OptionSpec<String> osArch
+                = parser.accepts("os-arch", getMessage("main.opt.os-arch"))
+                        .withRequiredArg()
+                        .describedAs(getMessage("main.opt.os-arch.arg"));
+
+        OptionSpec<String> osVersion
+                = parser.accepts("os-version", getMessage("main.opt.os-version"))
+                        .withRequiredArg()
+                        .describedAs(getMessage("main.opt.os-version.arg"));
+
+        OptionSpec<Void> version
+                = parser.accepts("version", getMessage("main.opt.version"));
+
+        NonOptionArgumentSpec<String> nonOptions
+                = parser.nonOptions();
+
+        try {
+            OptionSet opts = parser.parse(args);
+
+            if (opts.has(help) || opts.has(version)) {
+                options = new Options();
+                options.help = opts.has(help);
+                options.version = opts.has(version);
+                return;  // informational message will be shown
+            }
+
+            List<String> words = opts.valuesOf(nonOptions);
+            if (words.isEmpty())
+                throw new CommandException("err.missing.mode").showUsage(true);
+            String verb = words.get(0);
+            options = new Options();
+            try {
+                options.mode = Enum.valueOf(Mode.class, verb.toUpperCase());
+            } catch (IllegalArgumentException e) {
+                throw new CommandException("err.invalid.mode", verb).showUsage(true);
+            }
+
+            if (opts.has(classPath))
+                options.classpath = opts.valuesOf(classPath);
+            if (opts.has(cmds))
+                options.cmds = opts.valuesOf(cmds);
+            if (opts.has(config))
+                options.configs = opts.valuesOf(config);
+            if (opts.has(excludes))
+                options.excludes = opts.valuesOf(excludes);
+            if (opts.has(libs))
+                options.libs = opts.valuesOf(libs);
+            if (opts.has(modulePath)) {
+                Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]);
+                options.moduleFinder = ModuleFinder.of(dirs);
+                if (options.moduleFinder instanceof ConfigurableModuleFinder)
+                    ((ConfigurableModuleFinder)options.moduleFinder).configurePhase(Phase.LINK_TIME);
+            }
+            if (opts.has(moduleVersion))
+                options.moduleVersion = opts.valueOf(moduleVersion);
+            if (opts.has(mainClass))
+                options.mainClass = opts.valueOf(mainClass);
+            if (opts.has(osName))
+                options.osName = opts.valueOf(osName);
+            if (opts.has(osArch))
+                options.osArch = opts.valueOf(osArch);
+            if (opts.has(osVersion))
+                options.osVersion = opts.valueOf(osVersion);
+            if (opts.has(hashDependencies)) {
+                options.dependenciesToHash = opts.valueOf(hashDependencies);
+                // if storing hashes of dependencies then the module path is required
+                if (options.moduleFinder == null)
+                    throw new CommandException("err.modulepath.must.be.specified").showUsage(true);
+            }
+
+            if (words.size() <= 1)
+                throw new CommandException("err.jmod.must.be.specified").showUsage(true);
+            Path path = Paths.get(words.get(1));
+            if (options.mode.equals(Mode.CREATE) && Files.exists(path))
+                throw new CommandException("err.file.already.exists", path);
+            else if ((options.mode.equals(Mode.LIST) ||
+                          options.mode.equals(Mode.DESCRIBE))
+                      && Files.notExists(path))
+                throw new CommandException("err.jmod.not.found", path);
+            options.jmodFile = path;
+
+            if (words.size() > 2)
+                throw new CommandException("err.unknown.option",
+                        words.subList(2, words.size())).showUsage(true);
+
+            if (options.mode.equals(Mode.CREATE) && options.classpath == null)
+                throw new CommandException("err.classpath.must.be.specified").showUsage(true);
+            if (options.mainClass != null && !isValidJavaIdentifier(options.mainClass))
+                throw new CommandException("err.invalid.main-class", options.mainClass);
+        } catch (OptionException e) {
+             throw new CommandException(e.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if, and only if, the given main class is a legal.
+     */
+    static boolean isValidJavaIdentifier(String mainClass) {
+        if (mainClass.length() == 0)
+            return false;
+
+        if (!Character.isJavaIdentifierStart(mainClass.charAt(0)))
+            return false;
+
+        int n = mainClass.length();
+        for (int i=1; i < n; i++) {
+            char c = mainClass.charAt(i);
+            if (!Character.isJavaIdentifierPart(c) && c != '.')
+                return false;
+        }
+        if (mainClass.charAt(n-1) == '.')
+            return false;
+
+        return true;
+    }
+
+    private void reportError(String message) {
+        out.println(getMessage("error.prefix") + " " + message);
+    }
+
+    private void warning(String key, Object... args) {
+        out.println(getMessage("warn.prefix") + " " + getMessage(key, args));
+    }
+
+    private void showUsageSummary() {
+        out.println(getMessage("main.usage.summary", PROGNAME));
+    }
+
+    private void showHelp() {
+        out.println(getMessage("main.usage", PROGNAME));
+        try {
+            parser.printHelpOn(out);
+        } catch (IOException x) {
+            throw new AssertionError(x);
+        }
+    }
+
+    private void showVersion() {
+        out.println(version());
+    }
+
+    private String version() {
+        return System.getProperty("java.version");
+    }
+
+    private static String getMessage(String key, Object... args) {
+        try {
+            return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
+        } catch (MissingResourceException e) {
+            throw new InternalError("Missing message: " + key);
+        }
+    }
+
+    private static class ResourceBundleHelper {
+        static final ResourceBundle bundle;
+
+        static {
+            Locale locale = Locale.getDefault();
+            try {
+                bundle = ResourceBundle.getBundle("jdk.tools.jmod.resources.jmod", locale);
+            } catch (MissingResourceException e) {
+                throw new InternalError("Cannot find jmod resource bundle for locale " + locale);
+            }
+        }
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java
new file mode 100644
index 0000000..227f994
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jmod;
+
+import java.io.*;
+
+public class Main {
+    public static void main(String... args) throws Exception {
+        JmodTask t = new JmodTask();
+        int rc = t.run(args);
+        System.exit(rc);
+    }
+
+    /**
+     * Entry point that does <i>not</i> call System.exit.
+     *
+     * @param args command line arguments
+     * @param out output stream
+     * @return an exit code. 0 means success, non-zero means an error occurred.
+     */
+    public static int run(String[] args, PrintStream out) {
+        JmodTask t = new JmodTask();
+        t.setLog(out);
+        return t.run(args);
+    }
+}
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties
new file mode 100644
index 0000000..98e0f6f
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties
@@ -0,0 +1,58 @@
+main.usage.summary=\
+Usage: {0} (create|list|describe) <OPTIONS> <jmod-file>\n\
+use --help for a list of possible options
+
+main.usage=\
+Usage: {0} (create|list|describe) <OPTIONS> <jmod-file>
+
+error.prefix=Error:
+warn.prefix=Warning:
+
+main.opt.mode.create=\
+\create    - Creates a new jmod archive
+main.opt.mode.list=\
+\list      - Prints the names of all the entries
+main.opt.mode.describe=\
+\describe  - Prints the module details
+
+main.opt.help=Print this usage message
+main.opt.version=Version information
+main.opt.class-path=Application jar files|dir containing classes
+main.opt.libs=Location of native libraries
+main.opt.cmds=Location of native commands
+main.opt.config=Location of user-editable config files
+main.opt.exclude=Exclude files, given as a PATTERN
+main.opt.module-version= Module version
+main.opt.modulepath=Module path
+main.opt.main-class=Main class
+main.opt.main-class.arg=class-name
+main.opt.os-name=Operating system name
+main.opt.os-name.arg=os-name
+main.opt.os-arch=Operating system architecture
+main.opt.os-arch.arg=os-arch
+main.opt.os-version=Operating system version
+main.opt.os-version.arg=os-version
+main.opt.hash-dependencies=Compute and record hashes of dependencies matched by the pattern
+main.opt.cmdfile=Read options from the specified file
+
+err.missing.mode=one of create, list, or describe must be specified
+err.invalid.mode=mode must be one of create, list, or describe: {0}
+err.classpath.must.be.specified=--class-path must be specified
+err.jmod.must.be.specified=jmod-file must be specified
+err.invalid.version=invalid module version {0}
+err.output.must.be.specified:--output must be specified
+err.mods.must.be.specified:--mods must be specified
+err.modulepath.must.be.specified:--module-path must be specified when hashing dependencies
+err.invalid.main-class:invalid main-class name: {0}
+err.path.not.found=path not found: {0}
+err.path.not.valid=invalid path: {0}
+err.path.not.a.dir=path must be a directory: {0}
+err.invalid.class.path.entry=invalid class path entry: {0}
+err.file.already.exists=file already exists: {0}
+err.jmod.not.found=no jmod file found: {0}
+err.bad.pattern=bad pattern {0}
+err.unknown.option=unknown option(s): {0}
+err.missing.arg=no value given for {0}
+err.internal.error=internal error: {0} {1} {2}
+err.module.descriptor.not.found=Module descriptor not found
+warn.invalid.arg=Invalid classname or pathname not exist: {0}
diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java
new file mode 100644
index 0000000..06688ee
--- /dev/null
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jlink {
+    exports jdk.tools.jlink;
+    exports jdk.tools.jlink.plugin;
+    exports jdk.tools.jlink.builder;
+
+    requires jdk.internal.opt;
+    requires jdk.jdeps;
+
+    uses jdk.tools.jlink.plugin.TransformerPlugin;
+    uses jdk.tools.jlink.plugin.PostProcessorPlugin;
+
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludePlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.SortResourcesPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
+    provides jdk.tools.jlink.plugin.PostProcessorPlugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
+}
diff --git a/jdk/src/jdk.jsobject/share/classes/module-info.java b/jdk/src/jdk.jsobject/share/classes/module-info.java
new file mode 100644
index 0000000..b8f6a2d
--- /dev/null
+++ b/jdk/src/jdk.jsobject/share/classes/module-info.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+module jdk.jsobject {
+    requires java.desktop;
+    exports netscape.javascript;
+
+    uses jdk.internal.netscape.javascript.spi.JSObjectProvider;
+}
diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService b/jdk/src/jdk.jvmstat.rmi/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService
deleted file mode 100644
index 9ae6583..0000000
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService
+++ /dev/null
@@ -1 +0,0 @@
-sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService
diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java b/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java
new file mode 100644
index 0000000..01ed37c
--- /dev/null
+++ b/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jvmstat.rmi {
+    requires java.rmi;
+    requires jdk.jvmstat;
+
+    // RMI needs to serialize types in this package
+    exports sun.jvmstat.monitor.remote to java.rmi;
+
+    provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService;
+}
+
diff --git a/jdk/src/jdk.jvmstat/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService b/jdk/src/jdk.jvmstat/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService
deleted file mode 100644
index f559e14..0000000
--- a/jdk/src/jdk.jvmstat/share/classes/META-INF/services/sun.jvmstat.monitor.MonitoredHostService
+++ /dev/null
@@ -1,2 +0,0 @@
-sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService
-sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostLocalService
diff --git a/jdk/src/jdk.jvmstat/share/classes/module-info.java b/jdk/src/jdk.jvmstat/share/classes/module-info.java
new file mode 100644
index 0000000..2510a36
--- /dev/null
+++ b/jdk/src/jdk.jvmstat/share/classes/module-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jvmstat {
+    exports sun.jvmstat.monitor to
+        jdk.attach,
+        jdk.jcmd,
+        jdk.jconsole,
+        jdk.jvmstat.rmi;
+    exports sun.jvmstat.monitor.event to
+        jdk.jcmd,
+        jdk.jvmstat.rmi;
+    exports sun.jvmstat.perfdata.monitor to
+        jdk.jvmstat.rmi;
+
+    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;
+}
+
diff --git a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo
deleted file mode 100644
index 076f3b1..0000000
--- a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo
+++ /dev/null
@@ -1,2 +0,0 @@
-sun.util.resources.provider.NonBaseLocaleDataMetaInfo
-sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo
diff --git a/jdk/src/jdk.localedata/share/classes/module-info.java b/jdk/src/jdk.localedata/share/classes/module-info.java
new file mode 100644
index 0000000..6af3dd7
--- /dev/null
+++ b/jdk/src/jdk.localedata/share/classes/module-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+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.provider.NonBaseLocaleDataMetaInfo;
+    provides sun.util.resources.LocaleData.CommonResourceBundleProvider with
+        sun.util.resources.provider.LocaleDataProvider;
+    provides sun.util.resources.LocaleData.SupplementaryResourceBundleProvider with
+        sun.util.resources.provider.SupplementaryLocaleDataProvider;
+}
diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java
new file mode 100644
index 0000000..b2b312e
--- /dev/null
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.provider;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import sun.util.locale.provider.ResourceBundleProviderSupport;
+import sun.util.resources.LocaleData;
+
+/**
+ * {@code LocaleDataProvider} in module jdk.localedata implements
+ * {@code LocaleDataBundleProvider} in module java.base. This class works as a
+ * service agent between {@code ResourceBundle.getBundle} callers in java.base
+ * and resource bundles in jdk.localedata.
+ */
+public class LocaleDataProvider extends LocaleData.CommonResourceBundleProvider {
+    @Override
+    protected boolean isSupportedInModule(String baseName, Locale locale) {
+        // The assumption here is that there are two modules containing
+        // resource bundles for locale support. If resource bundles are split
+        // into more modules, this method will need to be changed to determine
+        // what locales are exactly supported.
+        return !super.isSupportedInModule(baseName, locale);
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (isSupportedInModule(baseName, locale)) {
+            Module module = LocaleDataProvider.class.getModule();
+            String bundleName = toBundleName(baseName, locale);
+            return ResourceBundleProviderSupport.loadResourceBundle(module, bundleName);
+        }
+        return null;
+    }
+}
diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/SupplementaryLocaleDataProvider.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/SupplementaryLocaleDataProvider.java
new file mode 100644
index 0000000..29884d0
--- /dev/null
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/SupplementaryLocaleDataProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources.provider;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import sun.util.locale.provider.ResourceBundleProviderSupport;
+import sun.util.resources.LocaleData;
+
+/**
+ * {@code SupplementaryLocaleDataProvider} in module jdk.localedata implements
+ * {@code JavaTimeSupplementaryProvider} in module java.base. This class works as a
+ * service agent between {@code ResourceBundle.getBundle} callers in java.base
+ * and resource bundles in jdk.localedata.
+ */
+public class SupplementaryLocaleDataProvider extends LocaleData.SupplementaryResourceBundleProvider {
+    @Override
+    protected boolean isSupportedInModule(String baseName, Locale locale) {
+        // The assumption here is that there are two modules containing
+        // resource bundles for locale support. If resource bundles are split
+        // into more modules, this method will need to be changed to determine
+        // what locales are exactly supported.
+        return !super.isSupportedInModule(baseName, locale);
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        Module module = LocaleDataProvider.class.getModule();
+        String bundleName = toBundleName(baseName, locale);
+        return ResourceBundleProviderSupport.loadResourceBundle(module, bundleName);
+    }
+}
diff --git a/jdk/src/jdk.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider b/jdk/src/jdk.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider
deleted file mode 100644
index a5611e8..0000000
--- a/jdk/src/jdk.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-com.sun.management.internal.PlatformMBeanProviderImpl
diff --git a/jdk/src/jdk.management/share/classes/module-info.java b/jdk/src/jdk.management/share/classes/module-info.java
new file mode 100644
index 0000000..34e371b
--- /dev/null
+++ b/jdk/src/jdk.management/share/classes/module-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.management {
+    requires public java.management;
+
+    exports com.sun.management;
+
+    provides sun.management.spi.PlatformMBeanProvider with
+        com.sun.management.internal.PlatformMBeanProviderImpl;
+}
+
diff --git a/jdk/src/jdk.naming.dns/share/classes/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/jdk/src/jdk.naming.dns/share/classes/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
deleted file mode 100644
index 52ff4b1..0000000
--- a/jdk/src/jdk.naming.dns/share/classes/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+++ /dev/null
@@ -1,2 +0,0 @@
-# dns service provider descriptor
-sun.net.spi.nameservice.dns.DNSNameServiceDescriptor
diff --git a/jdk/src/jdk.naming.dns/share/classes/module-info.java b/jdk/src/jdk.naming.dns/share/classes/module-info.java
new file mode 100644
index 0000000..852291f
--- /dev/null
+++ b/jdk/src/jdk.naming.dns/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.naming.dns {
+    requires java.naming;
+
+    exports com.sun.jndi.url.dns to
+        java.naming;
+
+    provides javax.naming.spi.InitialContextFactory
+        with com.sun.jndi.dns.DnsContextFactory;
+    provides sun.net.spi.nameservice.NameServiceDescriptor
+        with sun.net.spi.nameservice.dns.DNSNameServiceDescriptor;
+}
+
diff --git a/jdk/src/jdk.naming.rmi/share/classes/module-info.java b/jdk/src/jdk.naming.rmi/share/classes/module-info.java
new file mode 100644
index 0000000..debe640
--- /dev/null
+++ b/jdk/src/jdk.naming.rmi/share/classes/module-info.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.naming.rmi {
+    requires java.naming;
+    requires java.rmi;
+    provides javax.naming.spi.InitialContextFactory
+        with com.sun.jndi.rmi.registry.RegistryContextFactory;
+
+    // temporary export until NamingManager.getURLContext uses services
+    exports com.sun.jndi.url.rmi to java.naming;
+    exports com.sun.jndi.rmi.registry to java.rmi;
+}
+
diff --git a/jdk/src/jdk.pack200/share/classes/module-info.java b/jdk/src/jdk.pack200/share/classes/module-info.java
new file mode 100644
index 0000000..ffca94f
--- /dev/null
+++ b/jdk/src/jdk.pack200/share/classes/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.pack200 {
+}
+
diff --git a/jdk/src/jdk.policytool/share/classes/module-info.java b/jdk/src/jdk.policytool/share/classes/module-info.java
new file mode 100644
index 0000000..aedfc91
--- /dev/null
+++ b/jdk/src/jdk.policytool/share/classes/module-info.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.policytool {
+    requires java.desktop;
+    requires java.logging;
+    requires java.management;
+    requires java.sql;
+    requires java.security.jgss;
+    requires jdk.security.jgss;
+}
+
diff --git a/jdk/src/jdk.rmic/share/classes/jdk/rmi/rmic/Main.java b/jdk/src/jdk.rmic/share/classes/jdk/rmi/rmic/Main.java
new file mode 100644
index 0000000..90e9189
--- /dev/null
+++ b/jdk/src/jdk.rmic/share/classes/jdk/rmi/rmic/Main.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.rmi.rmic;
+
+/**
+ * The initial class for the rmic tool.
+ */
+
+public class Main {
+    public static void main(String[] args) {
+        sun.rmi.rmic.Main.main(args);
+    }
+}
diff --git a/jdk/src/jdk.rmic/share/classes/module-info.java b/jdk/src/jdk.rmic/share/classes/module-info.java
new file mode 100644
index 0000000..43578b8
--- /dev/null
+++ b/jdk/src/jdk.rmic/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.rmic {
+    requires java.corba;
+    requires jdk.compiler;
+    requires jdk.javadoc;
+    exports jdk.rmi.rmic;
+}
+
diff --git a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java
index fff8bb0..c9304b7 100644
--- a/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java
+++ b/jdk/src/jdk.rmic/share/classes/sun/rmi/rmic/BatchEnvironment.java
@@ -382,8 +382,7 @@
                 /* File is an ordinay file  */
                 String arcname = file.toLowerCase();
                 if (! (arcname.endsWith(".zip") ||
-                       arcname.endsWith(".jar") ||
-                       arcname.endsWith(".jimage"))) {
+                       arcname.endsWith(".jar"))) {
                     /* File name don't have right extension */
 //                      if (warn)
 //                          log.warning(Position.NOPOS,
diff --git a/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java b/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java
index 656eca1..4d5ecf2 100644
--- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassPath.java
@@ -41,6 +41,7 @@
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
 import java.nio.file.spi.FileSystemProvider;
 
 /**
@@ -53,7 +54,6 @@
  */
 public
 class ClassPath {
-    private static final String JIMAGE_EXT = ".jimage";
     private FileSystem getJrtFileSystem() {
         return FileSystems.getFileSystem(URI.create("jrt:/"));
     }
@@ -98,10 +98,14 @@
      * order.
      */
     public ClassPath() {
+        // though this property is removed. Check for null and use only
+        // if it is not null (when bootstrap JDK is used).
         String syscp = System.getProperty("sun.boot.class.path");
         String envcp = System.getProperty("env.class.path");
         if (envcp == null) envcp = ".";
-        String cp = syscp + File.pathSeparator + envcp;
+
+        // add syscp only if not null!
+        String cp = syscp == null? envcp : (syscp + File.pathSeparator + envcp);
         init(cp);
     }
 
@@ -121,8 +125,8 @@
         }
         // Build the class path
         ClassPathEntry[] path = new ClassPathEntry[n+1];
+
         int len = pathstr.length();
-        boolean jrtAdded = false;
         for (i = n = 0; i < len; i = j + 1) {
             if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
                 j = len;
@@ -133,25 +137,27 @@
                 String filename = pathstr.substring(i, j);
                 File file = new File(filename);
                 if (file.isFile()) {
-                    if (filename.endsWith(JIMAGE_EXT)) {
-                        if (jrtAdded) continue;
-                        FileSystem fs = getJrtFileSystem();
-                        path[n++] = new JrtClassPathEntry(fs);
-                        jrtAdded = true;
-                    } else {
-                        try {
-                            ZipFile zip = new ZipFile(file);
-                            path[n++] = new ZipClassPathEntry(zip);
-                        } catch (ZipException e) {
-                        } catch (IOException e) {
-                            // Ignore exceptions, at least for now...
-                        }
+                    try {
+                        ZipFile zip = new ZipFile(file);
+                        path[n++] = new ZipClassPathEntry(zip);
+                    } catch (ZipException e) {
+                    } catch (IOException e) {
+                        // Ignore exceptions, at least for now...
                     }
                 } else {
                     path[n++] = new DirClassPathEntry(file);
                 }
             }
         }
+
+        // add jrt file system at the end
+        try {
+            FileSystem fs = getJrtFileSystem();
+            path[n++] = new JrtClassPathEntry(fs);
+        } catch (ProviderNotFoundException ignored) {
+            // this could happen during jdk build with earlier JDK as bootstrap
+        }
+
         // Trim class path to exact size
         this.path = new ClassPathEntry[n];
         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
@@ -171,30 +177,31 @@
         }
 
         // Build the class path
-        ClassPathEntry[] path = new ClassPathEntry[patharray.length];
+        ClassPathEntry[] path = new ClassPathEntry[patharray.length + 1];
         int n = 0;
-        boolean jrtAdded = false;
         for (String name : patharray) {
             File file = new File(name);
             if (file.isFile()) {
-                if (name.endsWith(JIMAGE_EXT)) {
-                    if (jrtAdded) continue;
-                    FileSystem fs = getJrtFileSystem();
-                    path[n++] = new JrtClassPathEntry(fs);
-                    jrtAdded = true;
-                } else {
-                    try {
-                        ZipFile zip = new ZipFile(file);
-                        path[n++] = new ZipClassPathEntry(zip);
-                    } catch (ZipException e) {
-                    } catch (IOException e) {
-                        // Ignore exceptions, at least for now...
-                    }
-               }
+                try {
+                    ZipFile zip = new ZipFile(file);
+                    path[n++] = new ZipClassPathEntry(zip);
+                } catch (ZipException e) {
+                } catch (IOException e) {
+                    // Ignore exceptions, at least for now...
+                }
             } else {
                 path[n++] = new DirClassPathEntry(file);
             }
         }
+
+        // add jrt file system at the end
+        try {
+            FileSystem fs = getJrtFileSystem();
+            path[n++] = new JrtClassPathEntry(fs);
+        } catch (ProviderNotFoundException ignored) {
+            // this could happen with earlier version of JDK used as bootstrap
+        }
+
         // Trim class path to exact size
         this.path = new ClassPathEntry[n];
         System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
@@ -383,28 +390,12 @@
 // a ClassPathEntry that represents jrt file system
 final class JrtClassPathEntry extends ClassPathEntry {
     private final FileSystem fs;
-    // module directory paths in jrt fs
-    private final Set<Path> jrtModules;
     // package name to package directory path mapping (lazily filled)
     private final Map<String, Path> pkgDirs;
 
     JrtClassPathEntry(FileSystem fs) {
         this.fs = fs;
-        this.jrtModules = new LinkedHashSet<>();
         this.pkgDirs = new HashMap<>();
-
-        // fill in module directories at the root dir
-        Path root = fs.getPath("/modules");
-        try {
-            try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
-                for (Path entry: stream) {
-                    if (Files.isDirectory(entry))
-                        jrtModules.add(entry);
-                }
-            }
-        } catch (IOException ioExp) {
-            throw new UncheckedIOException(ioExp);
-        }
     }
 
     void close() throws IOException {
@@ -417,17 +408,31 @@
             return pkgDirs.get(pkgName);
         }
 
-        for (Path modPath : jrtModules) {
-            Path pkgDir = fs.getPath(modPath.toString(), pkgName);
-            // check if package directory is under any of the known modules
-            if (Files.exists(pkgDir)) {
-                // it is a package directory only if contains atleast one .class file
-                try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgDir)) {
-                    for (Path p : stream) {
-                        if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
-                            // cache package-to-package dir mapping for future
-                            pkgDirs.put(pkgName, pkgDir);
-                            return pkgDir;
+        Path pkgLink = fs.getPath("/packages/" + pkgName.replace('/', '.'));
+        // check if /packages/$PACKAGE directory exists
+        if (Files.isDirectory(pkgLink)) {
+           try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgLink)) {
+                for (Path p : stream) {
+                    // find first symbolic link to module directory
+                    if (Files.isSymbolicLink(p)) {
+                        Path modDir = Files.readSymbolicLink(p);
+                        if (Files.isDirectory(modDir)) {
+                            // get package subdirectory under /modules/$MODULE/
+                            Path pkgDir = fs.getPath(modDir.toString() + "/" + pkgName);
+                            if (Files.isDirectory(pkgDir)) {
+                                // it is a package directory only if contains
+                                // at least one .class file
+                                try (DirectoryStream<Path> pstream =
+                                        Files.newDirectoryStream(pkgDir)) {
+                                    for (Path f : pstream) {
+                                        if (Files.isRegularFile(f)
+                                                && f.toString().endsWith(".class")) {
+                                            pkgDirs.put(pkgName, pkgDir);
+                                            return pkgDir;
+                                        }
+                                    }
+                                }
+                            }
                         }
                     }
                 }
diff --git a/jdk/src/jdk.sctp/share/classes/module-info.java b/jdk/src/jdk.sctp/share/classes/module-info.java
new file mode 100644
index 0000000..c52ceb5
--- /dev/null
+++ b/jdk/src/jdk.sctp/share/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.sctp {
+    exports com.sun.nio.sctp;
+}
+
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 983e987..7bef826 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
@@ -57,7 +57,8 @@
           (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
               public java.util.ResourceBundle run() {
                   return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources"));
+                                ("sun.security.util.AuthResources",
+                                sun.security.util.ResourcesMgr.class.getModule()));
               }
           });
 
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 5068526..a182cf4 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
@@ -56,7 +56,8 @@
           (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
               public java.util.ResourceBundle run() {
                   return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources"));
+                                ("sun.security.util.AuthResources",
+                                 sun.security.util.ResourcesMgr.class.getModule()));
               }
            });
 
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 3350e08..80402c3 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
@@ -54,7 +54,8 @@
           (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
               public java.util.ResourceBundle run() {
                   return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources"));
+                                ("sun.security.util.AuthResources",
+                                 sun.security.util.ResourcesMgr.class.getModule()));
               }
           });
 
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 736309fd..bffbea5 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
@@ -59,7 +59,8 @@
         (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
               public java.util.ResourceBundle run() {
                   return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources"));
+                                ("sun.security.util.AuthResources",
+                                 sun.security.util.ResourcesMgr.class.getModule()));
               }
         });
 
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 1642e43..24eb622 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
@@ -157,7 +157,8 @@
             new PrivilegedAction<ResourceBundle>() {
                 public ResourceBundle run() {
                     return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources");
+                            "sun.security.util.AuthResources",
+                            sun.security.util.ResourcesMgr.class.getModule());
                 }
             }
     );
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 92ec5bc..b79d6cc 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
@@ -116,7 +116,8 @@
             new PrivilegedAction<ResourceBundle>() {
                 public ResourceBundle run() {
                     return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources");
+                            "sun.security.util.AuthResources",
+                            sun.security.util.ResourcesMgr.class.getModule());
                 }
             }
     );
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 8f09436..d59e2a8 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
@@ -423,7 +423,8 @@
             new PrivilegedAction<ResourceBundle>() {
                 public ResourceBundle run() {
                     return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources");
+                            "sun.security.util.AuthResources",
+                            sun.security.util.ResourcesMgr.class.getModule());
                 }
             }
     );
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 7c2da184..29db6c3 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
@@ -310,7 +310,8 @@
             new PrivilegedAction<ResourceBundle>() {
                 public ResourceBundle run() {
                     return ResourceBundle.getBundle(
-                        "sun.security.util.AuthResources");
+                        "sun.security.util.AuthResources",
+                        sun.security.util.ResourcesMgr.class.getModule());
                 }
             }
         );
diff --git a/jdk/src/jdk.security.auth/share/classes/module-info.java b/jdk/src/jdk.security.auth/share/classes/module-info.java
new file mode 100644
index 0000000..06ddb84
--- /dev/null
+++ b/jdk/src/jdk.security.auth/share/classes/module-info.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.security.auth {
+    requires public 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;
+    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.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
new file mode 100644
index 0000000..1497845
--- /dev/null
+++ b/jdk/src/jdk.security.jgss/share/classes/module-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.security.jgss {
+    requires public java.security.jgss;
+    requires java.logging;
+    requires java.security.sasl;
+    exports com.sun.security.jgss;
+    provides java.security.Provider with com.sun.security.sasl.gsskerb.JdkSASL;
+}
+
diff --git a/jdk/src/jdk.zipfs/share/classes/META-INF/services/java.nio.file.spi.FileSystemProvider b/jdk/src/jdk.zipfs/share/classes/META-INF/services/java.nio.file.spi.FileSystemProvider
deleted file mode 100644
index 22b5cb2..0000000
--- a/jdk/src/jdk.zipfs/share/classes/META-INF/services/java.nio.file.spi.FileSystemProvider
+++ /dev/null
@@ -1,2 +0,0 @@
-jdk.nio.zipfs.ZipFileSystemProvider
-
diff --git a/jdk/src/jdk.zipfs/share/classes/module-info.java b/jdk/src/jdk.zipfs/share/classes/module-info.java
new file mode 100644
index 0000000..5b7275e
--- /dev/null
+++ b/jdk/src/jdk.zipfs/share/classes/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.zipfs {
+    provides java.nio.file.spi.FileSystemProvider with jdk.nio.zipfs.ZipFileSystemProvider;
+}
+
diff --git a/jdk/test/Makefile b/jdk/test/Makefile
index 4c348f9..3312ccc 100644
--- a/jdk/test/Makefile
+++ b/jdk/test/Makefile
@@ -87,8 +87,8 @@
 
 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
 ifndef PRODUCT_HOME
-  # Try to use j2sdk-image if it exists
-  ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/j2sdk-image
+  # Try to use images/jdk if it exists
+  ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/jdk
   PRODUCT_HOME :=                       		\
     $(shell                             		\
       if [ -d $(ABS_JDK_IMAGE) ] ; then 		\
@@ -234,7 +234,7 @@
 
 # Expect JT_HOME to be set for jtreg tests. (home for jtreg)
 ifndef JT_HOME
-  JT_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg
+  JT_HOME = $(SLASH_JAVA)/re/jtreg/4.2/promoted/latest/binaries/jtreg
   ifdef JPRT_JTREG_HOME
     JT_HOME = $(JPRT_JTREG_HOME)
   endif
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index 5296f83..88ed7d2 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -222,6 +222,9 @@
 # 8062724
 java/rmi/activation/Activatable/extLoadedImpl/ext.sh            generic-all
 
+# 8145980
+sun/rmi/rmic/newrmic/equivalence/run.sh                         generic-all
+
 ############################################################################
 
 # jdk_security
@@ -308,6 +311,12 @@
 # 8074580
 sun/security/pkcs11/rsa/TestKeyPairGenerator.java               generic-all
 
+# 8038079
+sun/security/krb5/auto/HttpNegotiateServer.java                 generic-all
+
+# 8130302
+sun/security/tools/keytool/autotest.sh                          generic-all
+
 ############################################################################
 
 # jdk_sound
@@ -341,10 +350,12 @@
 # Tests take too long, on sparcs see 7143279
 # also see 8059906
 tools/pack200/CommandLineTests.java                             generic-all
-tools/pack200/Pack200Test.java                                  solaris-all,macosx-all
 
-# 8007410
-tools/launcher/FXLauncherTest.java                              linux-all
+# 8059906 fails on solaris and macosx, 8151901 
+tools/pack200/Pack200Test.java                                  generic-all
+
+# 8068049 
+tools/launcher/FXLauncherTest.java                              linux-all,macosx-all
 
 ############################################################################
 
@@ -395,8 +406,8 @@
 # 8031482
 sun/tools/jcmd/TestJcmdSanity.java				windows-all
 
-# 8072131
-sun/tools/jmap/heapconfig/JMapHeapConfigTest.java macosx-all
+# 8072131, 8132452
+sun/tools/jmap/heapconfig/JMapHeapConfigTest.java generic-all
 
 # 8046285
 sun/tools/jstatd/TestJstatdExternalRegistry.java                generic-all
@@ -410,11 +421,25 @@
 # 8057732
 sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java    generic-all
 
+# 8059035
+sun/tools/jinfo/JInfoSanityTest.java                           generic-all
+
+# 8151899
+demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java       generic-all
+
 ############################################################################
 
 # jdk_other
 
-############################################################################
-
 # 8141370
 com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java			linux-i586,macosx-all
+
+############################################################################
+
+# core_tools
+
+# 8150975
+# tools/jimage/JImageTest.java                                    linux-i586,windows-i586
+
+############################################################################
+
diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT
index 4aed60a..78c24d3 100644
--- a/jdk/test/TEST.ROOT
+++ b/jdk/test/TEST.ROOT
@@ -26,8 +26,8 @@
 # Allow querying of sun.arch.data.model in @requires clauses
 requires.properties=sun.arch.data.model 
 
-# Tests using jtreg 4.1 b12 features
-requiredVersion=4.1 b12
+# Tests using jtreg 4.2 b01 features
+requiredVersion=4.2 b01
 
 # 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 ea9a6d6..07f97cc 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -76,6 +76,7 @@
     jdk/lambda \
     jdk/internal/misc \
     jdk/internal/ref \
+    jdk/modules \
     vm
 
 # All of the java.util package
@@ -239,7 +240,6 @@
 #
 core_tools = \
     tools \
-    jdk/internal/jimage \
     jdk/internal/jrtfs \
     sun/tools/java \
     sun/tools/jrunscript
@@ -522,7 +522,6 @@
   java/util/jar/Manifest/CreateManifest.java \
   java/util/logging/TestMainAppContext.java \
   java/util/logging/TestLoggingWithMainAppContext.java \
-  java/util/ResourceBundle/Control/Bug6530694.java \
   java/text/Bidi/BidiConformance.java \
   java/text/Bidi/BidiEmbeddingTest.java \
   java/text/Bidi/Bug7042148.java \
diff --git a/jdk/test/com/sun/jdi/EarlyReturnNegativeTest.java b/jdk/test/com/sun/jdi/EarlyReturnNegativeTest.java
index c99a885..728130b 100644
--- a/jdk/test/com/sun/jdi/EarlyReturnNegativeTest.java
+++ b/jdk/test/com/sun/jdi/EarlyReturnNegativeTest.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
@@ -227,9 +227,7 @@
         String methodName = origMethodName.substring(2);
         ThreadReference tr = event.thread();
 
-        if (vmm.majorInterfaceVersion() >= 1 &&
-            vmm.minorInterfaceVersion() >= 6 &&
-            vm().canForceEarlyReturn()) {
+        if (vm().canForceEarlyReturn()) {
 
             /* There are some incompatible classes of values.  In the following,
              * we test each combination.
diff --git a/jdk/test/com/sun/jdi/EarlyReturnTest.java b/jdk/test/com/sun/jdi/EarlyReturnTest.java
index 5a7dae0..e76310c 100644
--- a/jdk/test/com/sun/jdi/EarlyReturnTest.java
+++ b/jdk/test/com/sun/jdi/EarlyReturnTest.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
@@ -565,9 +565,7 @@
         String methodName = origMethodName.substring(2);
         ThreadReference tr = event.thread();
 
-        if (vmm.majorInterfaceVersion() >= 1 &&
-            vmm.minorInterfaceVersion() >= 6 &&
-            vm().canForceEarlyReturn()) {
+        if (vm().canForceEarlyReturn()) {
 
             try {
 
@@ -664,9 +662,7 @@
     // This is the MethodExitEvent handler.
     public void methodExited(MethodExitEvent event) {
         String origMethodName = event.method().name();
-        if (vmm.majorInterfaceVersion() >= 1 &&
-            vmm.minorInterfaceVersion() >= 6 &&
-            vm().canGetMethodReturnValues()) {
+        if (vm().canGetMethodReturnValues()) {
             Value retValue = event.returnValue();
 
             if (!origMethodName.startsWith("s_") &&
diff --git a/jdk/test/com/sun/jdi/ImmutableResourceTest.sh b/jdk/test/com/sun/jdi/ImmutableResourceTest.sh
index 95bc877..b38e538 100644
--- a/jdk/test/com/sun/jdi/ImmutableResourceTest.sh
+++ b/jdk/test/com/sun/jdi/ImmutableResourceTest.sh
@@ -93,18 +93,18 @@
 echo "JDK under test is: $TESTJAVA"
 #
 CP="-classpath ${TESTCLASSES}"
-# Compile the test class using the classpath we need:
 #
 env
 #
 set -vx
 #
-#Compile.  tools.jar is required on the classpath.
-${TESTJAVA}/bin/javac -d "${TESTCLASSES}" ${CP} -g \
-                         "${TESTSRC}"/"${TARGETCLASS}".java
+# Compile test class
+${TESTJAVA}/bin/javac -XaddExports:jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
+   -d "${TESTCLASSES}" ${CP} -g "${TESTSRC}"/"${TARGETCLASS}".java
 #
-#Run the test class, again with the classpath we need:
-${TESTJAVA}/bin/java ${CP} ${TARGETCLASS}
+# Run the test class, again with the classpath we need:
+${TESTJAVA}/bin/java -XaddExports:jdk.jdi/com.sun.tools.example.debug.tty=ALL-UNNAMED \
+    ${CP} ${TARGETCLASS}
 status=$?
 echo "test status was: $status"
 if [ $status -eq "0" ];
diff --git a/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java b/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java
index 5c41575..d9131b0 100644
--- a/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java
+++ b/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -488,9 +488,7 @@
             return;
         }
 
-        if (vmm.majorInterfaceVersion() >= 1 &&
-            vmm.minorInterfaceVersion() >= 6 &&
-            vm().canGetMethodReturnValues()) {
+        if (vm().canGetMethodReturnValues()) {
             Value retValue = event.returnValue();
 
             if ("sin".equals(origMethodName)) {
diff --git a/jdk/test/com/sun/jdi/ModulesTest.java b/jdk/test/com/sun/jdi/ModulesTest.java
new file mode 100644
index 0000000..e9c8cff
--- /dev/null
+++ b/jdk/test/com/sun/jdi/ModulesTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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 8049365
+ *  @summary Tests the JDI and JDWP update for modules
+ *
+ *  @modules jdk.jdi
+ *  @run build TestScaffold VMConnection TargetListener TargetAdapter
+ *  @run compile -g ModulesTest.java
+ *  @run driver ModulesTest
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+import java.util.*;
+
+    /********** target program **********/
+
+class ModulesTarg {
+
+    public static void main(String[] args){
+        System.out.println("Goodbye from ModulesTarg!");
+    }
+}
+
+    /********** test program **********/
+
+public class ModulesTest extends TestScaffold {
+    static final String FailPrefix = "ModulesTest: failed: ";
+
+    private static ModuleReference bootUnnamedModule = null;
+    private static ModuleReference appUnnamedModule  = null;
+    private static ModuleReference extUnnamedModule  = null;
+
+    private ReferenceType targetClass;
+    private List<ModuleReference> modules;
+
+
+    ModulesTest (String args[]) {
+        super(args);
+    }
+
+    public static void main(String[] args) throws Exception {
+        new ModulesTest(args).startTests();
+    }
+
+    /********** test core **********/
+
+    private boolean reftypeSanityCheck(ModuleReference module, ReferenceType type) {
+        ModuleReference other = type.module();
+        if (other == null) {
+            testFailed = true;
+            println(FailPrefix + "a ModuleReference should never be null #1");
+            return false;
+        }
+        // Sanity checks: make sure there is no crash or exception
+        String otherName = other.name();
+        boolean cond = module.canRead(other);
+        return true;
+    }
+
+    private void checkLoaderDefinedClasses(ModuleReference module, ClassLoaderReference loader) {
+        String moduleName = module.name();
+        List<ReferenceType> definedClasses = loader.definedClasses();
+        boolean origModuleWasObserved = false;
+
+        for (ReferenceType type: definedClasses) {
+            ClassLoaderReference otherLoader = type.classLoader();
+            if (!loader.equals(otherLoader)) {
+                testFailed = true;
+                println(FailPrefix + "all classes defined by a ClassLoader" +
+                        " should refer to the defining ClassLoader");
+                return;
+            }
+            if (!reftypeSanityCheck(module, type)) {
+                return;
+            }
+        }
+    }
+
+    private void checkLoaderVisibleClasses(ModuleReference module, ClassLoaderReference loader) {
+        String moduleName = module.name();
+        List<ReferenceType> visibleClasses = loader.visibleClasses();
+
+        for (ReferenceType type: visibleClasses) {
+            if (!type.isPrepared()) {
+                continue; // Safety: skip unprepared classes
+            }
+            if (!reftypeSanityCheck(module, type)) {
+                return;
+            }
+        }
+    }
+
+    // Check any ClassLoader except the bootsrtap ClassLoader
+    private void checkClassLoader(ModuleReference module, ClassLoaderReference loader) {
+        checkLoaderDefinedClasses(module, loader);
+        checkLoaderVisibleClasses(module, loader);
+    }
+
+    // Sanity checks to make sure there are no crashes or exceptions.
+    private void checkModule(ModuleReference module, ModuleReference other, int checkIdx) {
+        if (module == null) {
+            testFailed = true;
+            println(FailPrefix + "a ModuleReference should never be null #2");
+            return;
+        }
+        String name = module.name();
+        println("\n--- Check #" + checkIdx);
+        println("    module name: " + name);
+
+        ClassLoaderReference loader = module.classLoader();
+        println("    loader: " + loader);
+
+        if (loader != null) {
+            checkClassLoader(module, loader);
+            String classloaderName = loader.toString();
+            if (classloaderName.contains("AppClassLoader") && name == null) {
+                if (appUnnamedModule != null) {
+                    testFailed = true;
+                    println(FailPrefix + "multiple unnamed modules in AppClassLoader");
+                }
+                appUnnamedModule = module;
+            }
+            if (classloaderName.contains("PlatformClassLoader") && name == null) {
+                if (extUnnamedModule != null) {
+                    testFailed = true;
+                    println(FailPrefix + "multiple unnamed modules in PlatformClassLoader");
+                }
+                extUnnamedModule = module;
+            }
+        } else if (name == null) {
+            if (bootUnnamedModule != null) {
+                testFailed = true;
+                println(FailPrefix + "multiple unnamed modules in BootClassLoader");
+            }
+            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.
+    private void checkBaseModule() {
+        List<ReferenceType> clist = vm().classesByName("java.lang.String");
+        if (clist.size() != 1) {
+            testFailed = true;
+            println(FailPrefix + "just one java.lang.String class is expected" +
+                    "but found multiple class instances: " + clist.size());
+            return;
+        }
+        ModuleReference module = clist.get(0).module();
+        if (module == null) {
+            testFailed = true;
+            println(FailPrefix + "a ModuleReference should never be null #3");
+        }
+        if (module.name().compareTo("java.base") != 0) {
+            testFailed = true;
+            println(FailPrefix + "java.lang.String must belong to java.base module");
+        }
+    }
+
+    // Check that the unnamed modules of the bootsrtap, application
+    // and platform class loaders were observed.
+    private void checkUnnamedModules() {
+        if (bootUnnamedModule == null) {
+            testFailed = true;
+            println(FailPrefix + "unnamed module of BootClassLoader was not observed");
+        }
+        if (appUnnamedModule == null) {
+            testFailed = true;
+            println(FailPrefix + "unnamed module of AppClassLoader was not observed");
+        }
+        if (extUnnamedModule == null) {
+            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 {
+        /*
+         * Get to the top of main() to determine targetClass
+         */
+        BreakpointEvent bpe = startToMain("ModulesTarg");
+        targetClass = bpe.location().declaringType();
+
+        if (!vm().canGetModuleInfo()) {
+            testFailed = true;
+            println(FailPrefix + "vm().canGetModuleInfo() returned false");
+        }
+        ModuleReference other = targetClass.module();
+        modules = vm().allModules();
+
+        int checkIdx = 0;
+
+        for (ModuleReference module : modules) {
+            checkModule(module, other, checkIdx++);
+            other = module;
+        }
+
+        checkBaseModule();
+        checkUnnamedModules();
+
+        /*
+         * resume the target until end
+         */
+        listenUntilVMDisconnect();
+
+        /*
+         * deal with results of test
+         * if anything has called failure("foo") testFailed will be true
+         */
+        if (!testFailed) {
+            println("ModulesTest: passed");
+        } else {
+            throw new Exception("ModulesTest: some checks failed");
+        }
+    }
+}
diff --git a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java
index f6c82e21..546bf8a 100644
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java
@@ -61,6 +61,7 @@
 
             ProcessBuilder pb = ProcessTools.
                 createJavaProcessBuilder(
+                    "-XaddExports:jdk.attach/sun.tools.attach=ALL-UNNAMED",
                     "-XX:+UseConcMarkSweepGC",  // this will cause UseParNewGC to be FLAG_SET_ERGO
                     "-XX:+UseCodeAging",
                     "-XX:+UseCerealGC",         // Should be ignored.
diff --git a/jdk/test/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java b/jdk/test/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java
index 5b9746f..f26c0b2 100644
--- a/jdk/test/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java
+++ b/jdk/test/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java
@@ -26,7 +26,8 @@
   @bug       6187066
   @summary   Tests the Window.autoRequestFocus property for the Window.toFront() method.
   @author    anton.tarasov: area=awt.focus
-  @library    ../../regtesthelpers
+  @library /java/awt/patchlib     ../../regtesthelpers
+  @build java.desktop/java.awt.Helper
   @build      Util
   @run       main AutoRequestFocusToFrontTest
 */
diff --git a/jdk/test/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java b/jdk/test/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java
index 763f01c..cfbe2f4 100644
--- a/jdk/test/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java
+++ b/jdk/test/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java
@@ -26,9 +26,12 @@
   @bug       6516675
   @summary   Tests that EmbeddedFrame can be focused.
   @author    anton.tarasov: area=awt-focus
+  @requires (os.family == "windows")
   @modules   java.desktop/java.awt.peer
              java.desktop/sun.awt
-  @library   ../../regtesthelpers
+             java.desktop/sun.awt.windows
+  @library /java/awt/patchlib    ../../regtesthelpers
+  @build java.desktop/java.awt.Helper
   @build     Util UtilInternal
   @run       main FocusEmbeddedFrameTest
 */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java
index 4cba548..0d9e6ff 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JButton
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JButtonInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java
index 9120b7d..127a3c4 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JButton
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JButtonOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java
index 6109737..972debe 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java
@@ -31,9 +31,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JColorChooser
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JColorChooserOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java
index 23ac96d..ea7d5fa 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java
@@ -42,9 +42,10 @@
 @test
 @summary Overlapping test for javax.swing.JScrollPane
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JComboBoxOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java
index 7ac72de..d1dfd71 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JEditorPaneInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java
index 22ef5be..d7e5ac3 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java
@@ -31,9 +31,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JEditorPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java
index 4b34b71..76336c7 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JLabelInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java
index dd89f63..fe29e85 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JLabelOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java
index 4a087f9..34d4771 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JList
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JListInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JListOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JListOverlapping.java
index 77725e5..c3ed67c 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JListOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JListOverlapping.java
@@ -31,9 +31,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JList
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JListOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java
index 068d4f8..864c8f7 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java
@@ -47,9 +47,10 @@
 @test
 @summary Overlapping test for javax.swing.JScrollPane
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JMenuBarOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java
index eb05250..02c0422 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JPanel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JPanelInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java
index 29a0e83..e6fe8e6 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JPanel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JPanelOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java
index e635d8e..10de3b9 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java
@@ -44,9 +44,10 @@
 @test
 @summary Overlapping test for javax.swing.JScrollPane
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JPopupMenuOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java
index 5b80682..a741eac 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JProgressBar
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JProgressBarInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java
index bad9847..ad4400b 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JProgressBar
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JProgressBarOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java
index 06b66a5..28a9370 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java
@@ -36,9 +36,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JScrollBar
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JScrollBarInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java
index c439b6d..6f4f2c8 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java
@@ -35,9 +35,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JScrollBar
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JScrollBarOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java
index 463b9a7..c9d5693 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JSlider
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JSliderInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java
index 49f6d06..aed5f97 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JSlider
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JSliderOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java
index f41b7e1..a346405 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java
@@ -35,9 +35,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JSpinner
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JSpinnerInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java
index b9624d6..a9e6bca 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java
@@ -34,9 +34,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JSpinner
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JSpinnerOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java
index efe36b2..871275a 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java
@@ -35,9 +35,10 @@
 @test
 @summary Simple Overlapping test for JTable
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTableInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTableOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTableOverlapping.java
index 0b184ed..e29fb93 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTableOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTableOverlapping.java
@@ -31,9 +31,10 @@
 @test
 @summary Simple Overlapping test for JTable
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTableOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java
index 3f9ee35..6b8f707 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTextAreaInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java
index 5ebfb8f..cf0c9f1 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTextAreaOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java
index 0ca69cc..de968ab 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java
@@ -33,9 +33,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTextFieldInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java
index 4c70b0c..c627d14 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JLabel
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JTextFieldOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java
index cb10f62..876f219 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java
@@ -32,9 +32,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JToggleButton
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JToggleButtonInGlassPaneOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java b/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java
index 8ac394a..8045bf6 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java
@@ -31,9 +31,10 @@
 @test
 @summary Simple Overlapping test for javax.swing.JToggleButton
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main JToggleButtonOverlapping
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java b/jdk/test/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java
index 09ee233..e3b0242 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java
@@ -41,9 +41,10 @@
 @bug 6777370
 @summary Issues when resizing the JFrame with HW components
 @author sergey.grinev@oracle.com: area=awt.mixing
-@library ../../regtesthelpers
+@library /java/awt/patchlib  ../../regtesthelpers
 @modules java.desktop/sun.awt
          java.desktop/java.awt.peer
+@build java.desktop/java.awt.Helper
 @build Util
 @run main MixingFrameResizing
  */
diff --git a/jdk/test/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java b/jdk/test/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java
index 5ff316f..97be2a8 100644
--- a/jdk/test/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java
+++ b/jdk/test/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java
@@ -108,8 +108,8 @@
     {    if (Toolkit.getDefaultToolkit().getClass().getName().matches(".*L.*Toolkit")) {
              // No EmbeddedFrame in LWToolkit/LWCToolkit, yet
              // And it should be programmed some other way, too, in any case
-             System.err.println("skipTestingEmbeddedFrame");
-             skipTestingEmbeddedFrame = true;
+             //System.err.println("skipTestingEmbeddedFrame");
+             //skipTestingEmbeddedFrame = true;
          }else {
              System.err.println("do not skipTestingEmbeddedFrame");
          }
@@ -241,21 +241,40 @@
                 container.setVisible(true); // create peer
 
                 long frameWindow = 0;
-                String getWindowMethodName = "getHWnd";
+                String getWindowMethodName = null;
+                String eframeClassName = null;
                 if (Toolkit.getDefaultToolkit().getClass().getName().contains("XToolkit")) {
+                    java.awt.Helper.addExports("sun.awt.X11", OverlappingTestBase.class.getModule());
                     getWindowMethodName = "getWindow";
+                    eframeClassName = "sun.awt.X11.XEmbeddedFrame";
+                }else if (Toolkit.getDefaultToolkit().getClass().getName().contains(".WToolkit")) {
+                    java.awt.Helper.addExports("sun.awt.windows", OverlappingTestBase.class.getModule());
+                    getWindowMethodName = "getHWnd";
+                    eframeClassName = "sun.awt.windows.WEmbeddedFrame";
+                }else if (isMac) {
+                    java.awt.Helper.addExports("sun.lwawt", OverlappingTestBase.class.getModule());
+                    java.awt.Helper.addExports("sun.lwawt.macosx", OverlappingTestBase.class.getModule());
+                    eframeClassName = "sun.lwawt.macosx.CViewEmbeddedFrame";
                 }
+
                 ComponentPeer peer = AWTAccessor.getComponentAccessor()
                                                 .getPeer(embedder);
-                //  System.err.println("Peer: " + peer);
-                Method getWindowMethod = peer.getClass().getMethod(getWindowMethodName);
-                frameWindow = (Long) getWindowMethod.invoke(peer);
-//                System.err.println("frame peer ID: " + frameWindow);
+                if (!isMac) {
+                    Method getWindowMethod = peer.getClass().getMethod(getWindowMethodName);
+                    frameWindow = (Long) getWindowMethod.invoke(peer);
+                } else {
+                    Method m_getPlatformWindowMethod = peer.getClass().getMethod("getPlatformWindow");
+                    Object platformWindow = m_getPlatformWindowMethod.invoke(peer);
+                    Class classPlatformWindow = Class.forName("sun.lwawt.macosx.CPlatformWindow");
 
-                String eframeClassName = "sun.awt.windows.WEmbeddedFrame";
-                if (Toolkit.getDefaultToolkit().getClass().getName().contains("XToolkit")) {
-                    eframeClassName = "sun.awt.X11.XEmbeddedFrame";
+                    Method m_getContentView = classPlatformWindow.getMethod("getContentView");
+                    Object contentView = m_getContentView.invoke(platformWindow);
+                    Class classContentView = Class.forName("sun.lwawt.macosx.CPlatformView");
+
+                    Method m_getAWTView = classContentView.getMethod("getAWTView");
+                    frameWindow = (Long) m_getAWTView.invoke(contentView);
                 }
+
                 Class eframeClass = Class.forName(eframeClassName);
                 Constructor eframeCtor = eframeClass.getConstructor(long.class);
                 EmbeddedFrame eframe = (EmbeddedFrame) eframeCtor.newInstance(frameWindow);
diff --git a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
index 872c93e..e243f87 100644
--- a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
+++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
@@ -28,7 +28,7 @@
 #   @bug 6282388 8030640
 #   @summary Tests that AWT use correct toolkit to be wrapped into HeadlessToolkit
 #   @author artem.ananiev@sun.com: area=awt.headless
-#   @compile TestWrapped.java
+#   compile TestWrapped.java
 #   @run shell WrappedToolkitTest.sh
 
 # Beginning of subroutines:
@@ -105,22 +105,54 @@
 fi
 echo "JDK under test is: $TESTJAVA"
 
-#Deal with .class files:
-if [ -n "${STANDALONE}" ] ; then
-   # then compile all .java files (if there are any) into .class files
-   if [ -a *.java ]; then
-      ${TESTJAVA}/bin/javac$ ./*.java ;
-   fi
-   # else in harness so copy all the class files from where jtreg put them
-   # over to the scratch directory this test is running in. 
-   else cp ${TESTCLASSES}/*.class . ;
-fi
-
+##Deal with .class files:
+#if [ -n "${STANDALONE}" ] ; then
+#   # then compile all .java files (if there are any) into .class files
+#   if [ -a *.java ]; then
+#      ${TESTJAVA}/bin/javac$ ./*.java ;
+#   fi
+#   # else in harness so copy all the class files from where jtreg put them
+#   # over to the scratch directory this test is running in. 
+#   else cp ${TESTCLASSES}/*.class . ;
+#fi
+#
 #if in test harness, then copy the entire directory that the test is in over 
 # to the scratch directory.  This catches any support files needed by the test.
 if [ -z "${STANDALONE}" ] ; 
    then cp ${TESTSRC}/* . 
 fi
+case "$OS" in
+  Windows* | CYGWIN* )
+    ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         *.java
+    status=$?
+    if [ ! $status -eq "0" ]; then
+      fail "Compilation failed";
+    fi
+    ;;
+
+  SunOS | Linux )
+    ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         *.java
+    status=$?
+    if [ ! $status -eq "0" ]; then
+      fail "Compilation failed";
+    fi
+    ;;
+
+  Darwin)
+    ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         *.java
+    status=$?
+    if [ ! $status -eq "0" ]; then
+      fail "Compilation failed";
+    fi
+    ;;
+
+esac
 
 #Just before executing anything, make sure it has executable permission!
 chmod 777 ./*
@@ -130,12 +162,14 @@
 case "$OS" in
   Windows* | CYGWIN* )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,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 \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.windows.WToolkit \
                          TestWrapped sun.awt.windows.WToolkit
     status=$?
@@ -146,6 +180,7 @@
 
   SunOS | Linux )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.X11.XToolkit \
                          TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -153,6 +188,7 @@
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
     fi
     AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                                               -Djava.awt.headless=true \
                                               TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -163,12 +199,14 @@
 
   Darwin)
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,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 \
+                         -XaddExports:java.desktop/sun.awt=ALL-UNNAMED,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 ce5495e..25254d5 100644
--- a/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java
+++ b/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java
@@ -31,6 +31,8 @@
  *          (single clicked, on Mac)
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
  * @library ../../../../lib/testlibrary ../
+ * @library /java/awt/patchlib
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main ActionCommand
  */
diff --git a/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java b/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
index ebafe40..e8710ed 100644
--- a/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
+++ b/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
@@ -33,7 +33,9 @@
  *          triggered when multiple AWTEventListeners and ActionListeners
  *          are added.
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main ActionEventMask
  */
diff --git a/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java b/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
index 4c0bb1d..dca4ef0 100644
--- a/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
+++ b/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
@@ -29,8 +29,10 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build ExtendedRobot SystemTrayIconHelper
+ * @build java.desktop/java.awt.Helper
  * @run main ModalityTest
  */
 public class ModalityTest {
diff --git a/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java b/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
index 113ec7e..c530d28 100644
--- a/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
+++ b/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
@@ -32,7 +32,9 @@
  *          checks if all listeners are triggered when AWTEventListeners
  *          and MouseListeners are added.
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main MouseEventMaskTest
  */
diff --git a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
index c9d2ead..4f8b91c 100644
--- a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
+++ b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
@@ -29,7 +29,9 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../../lib/testlibrary ../../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main/othervm/policy=tray.policy -Djava.security.manager FunctionalityCheck
  */
diff --git a/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java b/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java
index cb36b8fd..1fcf281 100644
--- a/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java
+++ b/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java
@@ -81,6 +81,9 @@
             try {
                 // sun.lwawt.macosx.CTrayIcon
                 Field f_peer = getField( java.awt.TrayIcon.class, "peer");
+                Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.reflect.Module.class);
+                m_addExports.invoke(null, "sun.lwawt.macosx", robot.getClass().getModule());
+
 
                 Object peer = f_peer.get(icon);
                 Method m_getModel = peer.getClass().getDeclaredMethod(
@@ -102,6 +105,9 @@
         } else {
             try {
                 // sun.awt.X11.XTrayIconPeer
+                Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.reflect.Module.class);
+                m_addExports.invoke(null, "sun.awt.X11", robot.getClass().getModule());
+
                 Field f_peer = getField(java.awt.TrayIcon.class, "peer");
 
                 SystemTrayIconHelper.openTrayIfNeeded(robot);
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
index b80db75..585097a 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
@@ -34,7 +34,9 @@
  * @summary Check if MouseEvent has the proper modifiers when
  *          TrayIcon is clicked pressing the modifier keys
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main TrayIconEventModifiersTest
  */
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java b/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
index 275e510..72a8fe5 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
@@ -30,7 +30,9 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main TrayIconEventsTest
  */
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java b/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
index b8f6a69..551878e 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
@@ -31,7 +31,9 @@
  *          it is double clicked using mouse button 1 (or single clicked
  *          with button 3 (on Mac OS X))
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main TrayIconMouseTest
  */
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
index a81e516..f59ff63 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
@@ -29,7 +29,9 @@
  * @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)
+ * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
+ * @build java.desktop/java.awt.Helper
  * @build ExtendedRobot SystemTrayIconHelper
  * @run main TrayIconPopupTest
  */
diff --git a/jdk/test/java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java b/jdk/test/java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java
new file mode 100644
index 0000000..2058f91
--- /dev/null
+++ b/jdk/test/java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.SystemFlavorMap;
+import java.io.IOException;
+import java.io.Reader;
+import javax.swing.JLabel;
+import javax.swing.TransferHandler;
+/*
+ * @test
+ * @bug 8130329
+ * @summary  Audit Core Reflection in module java.desktop AWT/Miscellaneous area
+ *           for places that will require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+public class ConstructFlavoredObjectTest {
+
+    private static final String TEST_MIME_TYPE = "text/plain;class="
+            + MyStringReader.class.getName();
+
+    public static void main(String[] args) throws Exception {
+
+        final DataFlavor dataFlavor = new DataFlavor(TEST_MIME_TYPE);
+        SystemFlavorMap systemFlavorMap = (SystemFlavorMap) SystemFlavorMap.
+                getDefaultFlavorMap();
+        systemFlavorMap.addUnencodedNativeForFlavor(dataFlavor, "TEXT");
+        systemFlavorMap.addFlavorForUnencodedNative("TEXT", dataFlavor);
+
+        TransferHandler transferHandler = new TransferHandler("Test Handler");
+
+        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+        transferHandler.exportToClipboard(new JLabel("Test"), clipboard,
+                TransferHandler.COPY);
+
+        Object clipboardData = clipboard.getData(dataFlavor);
+
+        if (!(clipboardData instanceof MyStringReader)) {
+            throw new RuntimeException("Wrong clipboard data!");
+        }
+    }
+
+    public static class MyStringReader extends Reader {
+
+        public MyStringReader(Reader reader) {
+        }
+
+        @Override
+        public int read(char[] cbuf, int off, int len) throws IOException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void close() throws IOException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+}
diff --git a/jdk/test/java/awt/datatransfer/DataFlavor/DataFlavorRemoteTest.java b/jdk/test/java/awt/datatransfer/DataFlavor/DataFlavorRemoteTest.java
new file mode 100644
index 0000000..e7bac95
--- /dev/null
+++ b/jdk/test/java/awt/datatransfer/DataFlavor/DataFlavorRemoteTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+  @test
+  @bug 8051636
+  @summary DataTransferer optional dependency on RMI
+  @author Semyon Sadetsky
+  @library ../../regtesthelpers/process
+  @build ProcessResults ProcessCommunicator
+  @run main DataFlavorRemoteTest
+*/
+
+import test.java.awt.regtesthelpers.process.ProcessCommunicator;
+import test.java.awt.regtesthelpers.process.ProcessResults;
+
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.Serializable;
+
+interface Hello extends java.rmi.Remote {
+    String sayHello();
+}
+
+public class DataFlavorRemoteTest {
+
+    public static void main(String[] args) throws Exception {
+        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+        Producer contents = new Producer();
+        clipboard.setContents(contents, null);
+        ProcessResults processResults =
+                ProcessCommunicator
+                        .executeChildProcess(Consumer.class, new String[0]);
+        if (!"Hello".equals(processResults.getStdErr())) {
+            throw new RuntimeException("transfer of remote object failed");
+        }
+        System.out.println("ok");
+    }
+
+    static class Consumer {
+        public static void main(String[] args) throws Exception {
+            Clipboard clipboard =
+                    Toolkit.getDefaultToolkit().getSystemClipboard();
+            DataFlavor dataFlavor = new DataFlavor(DataFlavor.javaRemoteObjectMimeType +
+                    ";class=Hello" );
+            Object data = clipboard.getData(dataFlavor);
+            System.err.print(((Hello) data).sayHello());
+        }
+
+    }
+}
+
+class Producer implements Transferable {
+
+    private final DataFlavor dataFlavor;
+    private final HelloImpl impl;
+
+    private static class HelloImpl implements Hello, Serializable {
+        @Override
+        public String sayHello() {
+            return "Hello";
+        }
+    }
+
+    public Producer() throws Exception {
+        dataFlavor = new DataFlavor(DataFlavor.javaRemoteObjectMimeType +
+                ";class=Hello" );
+        impl = new HelloImpl();
+        System.out.println(impl.hashCode());
+    }
+
+    Hello getImpl() {
+        return impl;
+    }
+
+    @Override
+    public DataFlavor[] getTransferDataFlavors() {
+        return new DataFlavor[]{dataFlavor};
+    }
+
+    @Override
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        return flavor.equals(dataFlavor);
+    }
+
+    @Override
+    public Object getTransferData(DataFlavor flavor)
+            throws UnsupportedFlavorException, IOException {
+        return impl;
+    }
+
+}
diff --git a/jdk/test/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java b/jdk/test/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java
index 7620e75..412bdaf 100644
--- a/jdk/test/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java
+++ b/jdk/test/java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java
@@ -28,7 +28,8 @@
   @author oleg.sukhodolsky area=awt.grab
   @modules java.desktop/java.awt.peer
            java.desktop/sun.awt
-  @library ../../regtesthelpers
+  @library /java/awt/patchlib  ../../regtesthelpers
+  @build java.desktop/java.awt.Helper
   @build Util UtilInternal
   @run main EmbeddedFrameTest1
 */
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
new file mode 100644
index 0000000..c16e580
--- /dev/null
+++ b/jdk/test/java/awt/patchlib/java.desktop/java/awt/Helper.java
@@ -0,0 +1,31 @@
+/*
+ * 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 java.awt;
+import java.lang.reflect.Module;
+public class Helper {
+    private Helper() { }
+    public static void addExports(String pn, Module target) {
+        java.awt.Component.class.getModule().addExports(pn, target);
+    }
+}
diff --git a/jdk/test/java/awt/regtesthelpers/Util.java b/jdk/test/java/awt/regtesthelpers/Util.java
index 2b2a8fb..62feee2 100644
--- a/jdk/test/java/awt/regtesthelpers/Util.java
+++ b/jdk/test/java/awt/regtesthelpers/Util.java
@@ -212,22 +212,6 @@
         robot.waitForIdle();
     }
 
-    public static Field getField(final Class klass, final String fieldName) {
-        return AccessController.doPrivileged(new PrivilegedAction<Field>() {
-            public Field run() {
-                try {
-                    Field field = klass.getDeclaredField(fieldName);
-                    assert (field != null);
-                    field.setAccessible(true);
-                    return field;
-                } catch (SecurityException se) {
-                    throw new RuntimeException("Error: unexpected exception caught!", se);
-                } catch (NoSuchFieldException nsfe) {
-                    throw new RuntimeException("Error: unexpected exception caught!", nsfe);
-                }
-            }
-        });
-    }
 
     /*
      * Waits for a notification and for a boolean condition to become true.
@@ -461,6 +445,10 @@
 
         try {
             final Class _clazz = clazz;
+            Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.reflect.Module.class);
+            // No MToolkit anymore: nothing to do about it.
+            // We may be called from non-X11 system, and this permission cannot be delegated to a test.
+            m_addExports.invoke(null, "sun.awt.X11", Util.class.getModule());
             Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() {
                     public Object run() {
                         try {
@@ -478,6 +466,10 @@
                     }
                 });
             return ((Integer)m_getWMID.invoke(null, new Object[] {})).intValue();
+        } catch (ClassNotFoundException cnfe) {
+            cnfe.printStackTrace();
+        } catch (NoSuchMethodException nsme) {
+            nsme.printStackTrace();
         } catch (IllegalAccessException iae) {
             iae.printStackTrace();
         } catch (InvocationTargetException ite) {
diff --git a/jdk/test/java/awt/regtesthelpers/UtilInternal.java b/jdk/test/java/awt/regtesthelpers/UtilInternal.java
index ef12684..d7f0e1e 100644
--- a/jdk/test/java/awt/regtesthelpers/UtilInternal.java
+++ b/jdk/test/java/awt/regtesthelpers/UtilInternal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -33,7 +33,6 @@
 
 import sun.awt.AWTAccessor;
 
-
 /**
    Class with static methods using internal/proprietary API by necessity.
 */
@@ -50,6 +49,8 @@
                                           .getPeer(embedder);
         System.out.println("frame's peer = " + frame_peer);
         if ("sun.awt.windows.WToolkit".equals(tk.getClass().getName())) {
+            java.awt.Helper.addExports("sun.awt.windows", UtilInternal.class.getModule());
+
             Class comp_peer_class =
                 Class.forName("sun.awt.windows.WComponentPeer");
             System.out.println("comp peer class = " + comp_peer_class);
@@ -63,8 +64,8 @@
             Constructor constructor = clazz.getConstructor (new Class [] {Long.TYPE});
             return (Frame) constructor.newInstance (new Object[] {hwnd});
         } else if ("sun.awt.X11.XToolkit".equals(tk.getClass().getName())) {
+            java.awt.Helper.addExports("sun.awt.X11", UtilInternal.class.getModule());
             Class x_base_window_class = Class.forName("sun.awt.X11.XBaseWindow");
-            System.out.println("x_base_window_class = " + x_base_window_class);
             Method get_window = x_base_window_class.getMethod("getWindow", new Class[0]);
             System.out.println("get_window = " + get_window);
             long window = (Long) get_window.invoke(frame_peer, new Object[0]);
diff --git a/jdk/test/java/awt/xembed/server/TesterClient.java b/jdk/test/java/awt/xembed/server/TesterClient.java
index 22991f3..535e65b 100644
--- a/jdk/test/java/awt/xembed/server/TesterClient.java
+++ b/jdk/test/java/awt/xembed/server/TesterClient.java
@@ -32,6 +32,8 @@
     public static void main(String[] args) throws Throwable {
         // First parameter is the name of the test, second is the window, the rest are rectangles
         Class cl = Class.forName("sun.awt.X11.XEmbedServerTester");
+        cl.getModule().addExports("sun.awt.X11",TesterClient.class.getModule());
+
         test = cl.getMethod(args[0], new Class[0]);
         long window = Long.parseLong(args[1]);
         Rectangle r[] = new Rectangle[(args.length-2)/4];
diff --git a/jdk/test/java/beans/XMLEncoder/sun_swing_PrintColorUIResource.java b/jdk/test/java/beans/XMLEncoder/sun_swing_PrintColorUIResource.java
index b6e5b86..b6e7946 100644
--- a/jdk/test/java/beans/XMLEncoder/sun_swing_PrintColorUIResource.java
+++ b/jdk/test/java/beans/XMLEncoder/sun_swing_PrintColorUIResource.java
@@ -25,8 +25,8 @@
  * @test
  * @bug 6589532
  * @summary Tests PrintColorUIResource value encoding
- * @author Sergey Malenkov
  * @modules java.desktop/sun.swing
+ * @author Sergey Malenkov
  */
 
 import java.awt.Color;
diff --git a/jdk/test/java/lang/Class/Foo.java b/jdk/test/java/lang/Class/Foo.java
new file mode 100644
index 0000000..bc8df3d
--- /dev/null
+++ b/jdk/test/java/lang/Class/Foo.java
@@ -0,0 +1,27 @@
+/*
+ * 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 foo;
+
+// Loaded by a custom class loader in GetPackageTest
+public class Foo {
+}
diff --git a/jdk/test/java/lang/Class/GetModuleTest.java b/jdk/test/java/lang/Class/GetModuleTest.java
new file mode 100644
index 0000000..566721c
--- /dev/null
+++ b/jdk/test/java/lang/Class/GetModuleTest.java
@@ -0,0 +1,153 @@
+/**
+ * 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
+ * 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 Exercise Class#getModule
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.desktop
+ * @run testng GetModuleTest
+ */
+
+import java.awt.Component;
+import java.lang.reflect.Field;
+import java.lang.reflect.Module;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import sun.misc.Unsafe;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+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 Module TEST_MODULE = GetModuleTest.class.getModule();
+
+
+    @DataProvider(name = "testclasses")
+    public Object[][] testClasses() {
+        return new Object[][] {
+
+            // unnamed module
+
+            { GetModuleTest.class,      null },
+            { GetModuleTest[].class,    null },
+            { GetModuleTest[][].class,  null },
+
+            // should return named module
+
+            { int.class,            "java.base" },
+            { int[].class,          "java.base" },
+            { int[][].class,        "java.base" },
+            { void.class,           "java.base" },
+
+            { Object.class,         "java.base" },
+            { Object[].class,       "java.base" },
+            { Object[][].class,     "java.base" },
+            { Component.class,      "java.desktop" },
+            { Component[].class,    "java.desktop" },
+            { Component[][].class,  "java.desktop" },
+        };
+    }
+
+    @Test(dataProvider = "testclasses")
+    public void testGetModule(Class<?> type, String expected) {
+        Module m = type.getModule();
+        assertNotNull(m);
+        if (expected == null) {
+            assertTrue(m == TEST_MODULE);
+        } else {
+            assertEquals(m.getName(), expected);
+        }
+    }
+
+
+    @DataProvider(name = "hostclasses")
+    public Object[][] hostClasses() {
+        return new Object[][] {
+
+            { GetModuleTest.class,      null },
+            { GetModuleTest[].class,    null },
+            { Object.class,             null },
+            { Object[].class,           null },
+            { Component.class,          null },
+            { Component[].class,        null },
+
+        };
+    }
+
+    /**
+     * Exercise Class::getModule on VM anonymous classes
+     */
+    @Test(dataProvider = "hostclasses")
+    public void testGetModuleOnVMAnonymousClass(Class<?> hostClass, String ignore) {
+
+        // choose a class name in the same package as the host class
+        String prefix = packageName(hostClass);
+        if (prefix.length() > 0)
+            prefix = prefix.replace('.', '/') + "/";
+        String className = prefix + "Anon";
+
+        // create the class
+        String superName = "java/lang/Object";
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                         + ClassWriter.COMPUTE_FRAMES);
+        cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
+                 className, null, superName, null);
+        byte[] classBytes = cw.toByteArray();
+        int cpPoolSize = constantPoolSize(classBytes);
+        Class<?> anonClass
+            = U.defineAnonymousClass(hostClass, classBytes, new Object[cpPoolSize]);
+
+        assertTrue(anonClass.getModule() == hostClass.getModule());
+    }
+
+    private static String packageName(Class<?> c) {
+        if (c.isArray()) {
+            return packageName(c.getComponentType());
+        } else {
+            String name = c.getName();
+            int dot = name.lastIndexOf('.');
+            if (dot == -1) return "";
+            return name.substring(0, dot);
+        }
+    }
+
+    private static int constantPoolSize(byte[] classFile) {
+        return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
+    }
+
+}
diff --git a/jdk/test/java/lang/Class/GetPackageTest.java b/jdk/test/java/lang/Class/GetPackageTest.java
new file mode 100644
index 0000000..d1ffea7
--- /dev/null
+++ b/jdk/test/java/lang/Class/GetPackageTest.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Basic test for Class.getPackage
+ * @compile Foo.java
+ * @run testng GetPackageTest
+ */
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import static org.testng.Assert.*;
+
+public class GetPackageTest {
+    private static Class<?> fooClass; // definePackage is not called for Foo class
+
+    @BeforeTest
+    public static void loadFooClass() throws ClassNotFoundException {
+        TestClassLoader loader = new TestClassLoader();
+        fooClass = loader.loadClass("foo.Foo");
+        assertEquals(fooClass.getClassLoader(), loader);
+    }
+
+    @DataProvider(name = "testclasses")
+    public Object[][] testClasses() {
+        return new Object[][] {
+                // primitive type, void, array types
+                { int.class,            null },
+                { long[].class,         null },
+                { Object[][].class,     null },
+                { void.class,           null },
+
+                // unnamed package
+                { GetPackageTest.class, "" },
+
+                // named package
+                { fooClass,             "foo" },
+                { Object.class,         "java.lang" },
+                { Properties.class,     "java.util" },
+                { BigInteger.class,     "java.math" },
+                { Test.class,           "org.testng.annotations" },
+        };
+    }
+
+    @Test(dataProvider = "testClasses")
+    public void testGetPackage(Class<?> type, String expected) {
+        Package p = type.getPackage();
+        if (expected == null) {
+            assertTrue(p == null);
+        } else {
+            assertEquals(p.getName(), expected);
+        }
+    }
+
+    static class TestClassLoader extends ClassLoader {
+        public TestClassLoader() {
+            super();
+        }
+
+        public TestClassLoader(ClassLoader parent) {
+            super(parent);
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            Path p = Paths.get(System.getProperty("test.classes", "."));
+
+            try {
+                byte[] bb = Files.readAllBytes(p.resolve("foo/Foo.class"));
+                return defineClass(name, bb, 0, bb.length);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+        @Override
+        protected Class<?> loadClass(String cn, boolean resolve) throws ClassNotFoundException {
+            if (!cn.equals("foo.Foo"))
+                return super.loadClass(cn, resolve);
+            return findClass(cn);
+        }
+
+    }
+}
+
+
diff --git a/jdk/test/java/lang/Class/forName/modules/TestDriver.java b/jdk/test/java/lang/Class/forName/modules/TestDriver.java
new file mode 100644
index 0000000..690849b
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/TestDriver.java
@@ -0,0 +1,172 @@
+/*
+ * 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.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.FileUtils;
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @bug 8087335
+ * @summary Tests for Class.forName(Module,String)
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build TestDriver CompilerUtils jdk.testlibrary.ProcessTools jdk.testlibrary.FileUtils TestMain TestLayer
+ * @run testng TestDriver
+ */
+
+public class TestDriver {
+
+    private static final String TEST_SRC =
+            Paths.get(System.getProperty("test.src")).toString();
+    private static final String TEST_CLASSES =
+            Paths.get(System.getProperty("test.classes")).toString();
+
+    private static final Path MOD_SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MOD_DEST_DIR = Paths.get("mods");
+
+    private static final String[] modules = new String[] {"m1", "m2", "m3"};
+
+    /**
+     * Compiles all modules used by the test.
+     */
+    @BeforeClass
+    public void setup() throws Exception {
+        assertTrue(CompilerUtils.compile(
+                        MOD_SRC_DIR, MOD_DEST_DIR,
+                        "-modulesourcepath",
+                        MOD_SRC_DIR.toString()));
+
+        copyDirectories(MOD_DEST_DIR.resolve("m1"), Paths.get("mods1"));
+        copyDirectories(MOD_DEST_DIR.resolve("m2"), Paths.get("mods2"));
+    }
+
+    @Test
+    public void test() throws Exception {
+        String[] options = new String[] {
+                "-cp", TEST_CLASSES,
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "-m", "m2/p2.test.Main"
+        };
+        runTest(options);
+    }
+
+    @Test
+    public void testUnnamedModule() throws Exception {
+        String[] options = new String[] {
+                "-cp", TEST_CLASSES,
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "TestMain"
+        };
+        runTest(options);
+    }
+
+    @Test
+    public void testLayer() throws Exception {
+        String[] options = new String[] {
+                "-cp", TEST_CLASSES,
+                "TestLayer"
+        };
+
+        runTest(options);
+    }
+
+    @Test
+    public void testDeniedClassLoaderAccess() throws Exception {
+        String[] options = new String[] {
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "-m", "m3/p3.NoGetClassLoaderAccess"
+        };
+        assertTrue(executeTestJava(options)
+                        .outputTo(System.out)
+                        .errorTo(System.err)
+                        .getExitValue() == 0);
+    }
+
+    @Test
+    public void testDeniedAccess() throws Exception {
+        Path policyFile = Paths.get(TEST_SRC, "policy.denied");
+
+        String[] options = new String[] {
+                "-Djava.security.manager",
+                "-Djava.security.policy=" + policyFile.toString(),
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "-m", "m3/p3.NoAccess"
+        };
+        assertTrue(executeTestJava(options)
+                        .outputTo(System.out)
+                        .errorTo(System.err)
+                        .getExitValue() == 0);
+    }
+
+    private String[] runWithSecurityManager(String[] options) {
+        Path policyFile = Paths.get(TEST_SRC, "policy");
+        Stream<String> opts = Stream.concat(Stream.of("-Djava.security.manager",
+                                                      "-Djava.security.policy=" + policyFile.toString()),
+                                            Arrays.stream(options));
+        return opts.toArray(String[]::new);
+    }
+
+    private void runTest(String[] options) throws Exception {
+        assertTrue(executeTestJava(options)
+                        .outputTo(System.out)
+                        .errorTo(System.err)
+                        .getExitValue() == 0);
+
+        assertTrue(executeTestJava(runWithSecurityManager(options))
+                        .outputTo(System.out)
+                        .errorTo(System.err)
+                        .getExitValue() == 0);
+    }
+
+    private void copyDirectories(Path source, Path dest) throws IOException {
+        if (Files.exists(dest))
+            FileUtils.deleteFileTreeWithRetry(dest);
+        Files.walk(source, Integer.MAX_VALUE)
+                .filter(Files::isRegularFile)
+                .forEach(p -> {
+                    try {
+                        Path to = dest.resolve(source.relativize(p));
+                        Files.createDirectories(to.getParent());
+                        Files.copy(p, to);
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                });
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/TestLayer.java b/jdk/test/java/lang/Class/forName/modules/TestLayer.java
new file mode 100644
index 0000000..8a01cb1
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/TestLayer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+public class TestLayer {
+    private static final Path MODS_DIR = Paths.get("mods");
+    private static final Set<String> modules = Set.of("m1", "m2");
+
+    public static void main(String[] args) throws Exception {
+        // disable security manager until Class.forName is called.
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            System.setSecurityManager(null);
+        }
+
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = parent.resolveRequiresAndUses(ModuleFinder.empty(),
+                                                         finder,
+                                                         modules);
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl);
+
+        Module m1 = layer.findModule("m1").get();
+        Module m2 = layer.findModule("m2").get();
+
+        if (sm != null) {
+            System.setSecurityManager(sm);
+        }
+
+        // find exported and non-exported class from a named module
+        findClass(m1, "p1.A");
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+
+        // find class from unnamed module
+        ClassLoader ld = TestLayer.class.getClassLoader();
+        findClass(ld.getUnnamedModule(), "TestDriver");
+
+        // check if clinit should not be initialized
+        // compile without module-path; so use reflection
+        Class<?> c = Class.forName(m1, "p1.Initializer");
+        Method m = c.getMethod("isInited");
+        Boolean isClinited = (Boolean) m.invoke(null);
+        if (isClinited.booleanValue()) {
+           throw new RuntimeException("clinit should not be invoked");
+        }
+    }
+
+    static Class<?> findClass(Module module, String cn) {
+        Class<?> c = Class.forName(module, cn);
+        if (c == null) {
+            throw new RuntimeException(cn + " not found in " + module);
+        }
+        if (c.getModule() != module) {
+            throw new RuntimeException(c.getModule() + " != " + module);
+        }
+        return c;
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/TestMain.java b/jdk/test/java/lang/Class/forName/modules/TestMain.java
new file mode 100644
index 0000000..0da5136
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/TestMain.java
@@ -0,0 +1,63 @@
+/*
+ * 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.lang.reflect.Method;
+import java.lang.reflect.Module;
+
+public class TestMain {
+    public static void main(String[] args) throws Exception {
+        Layer boot = Layer.boot();
+        Module m1 = boot.findModule("m1").get();
+        Module m2 = boot.findModule("m2").get();
+
+        // find exported and non-exported class from a named module
+        findClass(m1, "p1.A");
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+
+        // find class from unnamed module
+        ClassLoader loader = TestMain.class.getClassLoader();
+        findClass(loader.getUnnamedModule(), "TestDriver");
+
+        // check if clinit should not be initialized
+        // compile without module-path; so use reflection
+        Class<?> c = Class.forName(m1, "p1.Initializer");
+        Method m = c.getMethod("isInited");
+        Boolean isClinited = (Boolean) m.invoke(null);
+        if (isClinited.booleanValue()) {
+            throw new RuntimeException("clinit should not be invoked");
+        }
+    }
+
+    static Class<?> findClass(Module module, String cn) {
+        Class<?> c = Class.forName(module, cn);
+        if (c == null) {
+            throw new RuntimeException(cn + " not found in " + module);
+        }
+        if (c.getModule() != module) {
+            throw new RuntimeException(c.getModule() + " != " + module);
+        }
+        return c;
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/policy b/jdk/test/java/lang/Class/forName/modules/policy
new file mode 100644
index 0000000..a95ecca
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/policy
@@ -0,0 +1,7 @@
+grant {
+    permission java.lang.RuntimePermission "setSecurityManager";
+    permission java.lang.RuntimePermission "getBootLayer";
+    permission java.lang.RuntimePermission "getClassLoader";
+    permission java.io.FilePermission "mods/-", "read";
+    permission java.util.PropertyPermission "user.dir", "read";
+};
diff --git a/jdk/test/java/lang/Class/forName/modules/policy.denied b/jdk/test/java/lang/Class/forName/modules/policy.denied
new file mode 100644
index 0000000..763f615
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/policy.denied
@@ -0,0 +1,11 @@
+grant {
+    permission java.lang.RuntimePermission "setSecurityManager";
+    permission java.lang.RuntimePermission "getBootLayer";
+    permission java.lang.RuntimePermission "getClassLoader";
+    permission java.io.FilePermission "mods1", "read";
+    permission java.io.FilePermission "mods2", "read";
+    // only grant access to p1.* classes
+    // no access to p1.internal.* and p2.* classes
+    permission java.io.FilePermission "mods1/p1/*", "read";
+    permission java.util.PropertyPermission "user.dir", "read";
+};
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m1/module-info.java b/jdk/test/java/lang/Class/forName/modules/src/m1/module-info.java
new file mode 100644
index 0000000..47a2c4c
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    exports p1;
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m1/p1/A.java b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/A.java
new file mode 100644
index 0000000..444b8cc
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/A.java
@@ -0,0 +1,31 @@
+/*
+ * 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 p1;
+
+public class A {
+    static {
+        Initializer.init();
+        System.out.println("p1.A is initialzed");
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m1/p1/Initializer.java b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/Initializer.java
new file mode 100644
index 0000000..e8823ca
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/Initializer.java
@@ -0,0 +1,34 @@
+/*
+ * 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 p1;
+
+public class Initializer {
+    private static boolean inited = false;
+    static synchronized void init() {
+        inited = true;
+    }
+    public static synchronized boolean isInited() {
+        return inited;
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m1/p1/internal/B.java b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/internal/B.java
new file mode 100644
index 0000000..3454c06
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m1/p1/internal/B.java
@@ -0,0 +1,28 @@
+/*
+ * 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 p1.internal;
+
+public class B {
+    public B() {}
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m2/module-info.java b/jdk/test/java/lang/Class/forName/modules/src/m2/module-info.java
new file mode 100644
index 0000000..e28b220
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports p2;
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m2/p2/C.java b/jdk/test/java/lang/Class/forName/modules/src/m2/p2/C.java
new file mode 100644
index 0000000..e976c5c
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m2/p2/C.java
@@ -0,0 +1,27 @@
+/*
+ * 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 p2;
+
+public class C {
+}
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
new file mode 100644
index 0000000..83856c6
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m2/p2/test/Main.java
@@ -0,0 +1,61 @@
+/*
+ * 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 p2.test;
+
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+
+public class Main {
+    public static void main(String... args) throws Exception {
+        Layer boot = Layer.boot();
+        Module m1 = boot.findModule("m1").get();
+        Module m2 = Main.class.getModule();
+
+        // find exported and non-exported class from a named module
+        findClass(m1, "p1.A");
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+
+        // find class from unnamed module
+        ClassLoader loader = m2.getClassLoader();
+        findClass(loader.getUnnamedModule(), "TestDriver");
+
+        try {
+            Class<?> c = findClass(m1, "p1.internal.B");
+            c.newInstance();
+            throw new RuntimeException(c.getName() + " is not exported to m2");
+        } catch (IllegalAccessException e) {}
+    }
+
+    static Class<?> findClass(Module module, String cn) {
+        Class<?> c = Class.forName(module, cn);
+        if (c == null) {
+            throw new RuntimeException(cn + " not found in " + module);
+        }
+        if (c.getModule() != module) {
+            throw new RuntimeException(c.getModule() + " != " + module);
+        }
+        return c;
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m3/module-info.java b/jdk/test/java/lang/Class/forName/modules/src/m3/module-info.java
new file mode 100644
index 0000000..a92b756
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m3/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 {
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java
new file mode 100644
index 0000000..902e92d
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoAccess.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p3;
+
+import java.io.FilePermission;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.AccessControlException;
+import java.security.Permission;
+import java.util.Set;
+
+public class NoAccess {
+    private static final Module M3 = NoAccess.class.getModule();
+    private static final Path MODS_DIR1 = Paths.get("mods1");
+    private static final Path MODS_DIR2 = Paths.get("mods2");
+    public static void main(String[] args) throws Exception {
+        // disable security manager until Class.forName is called.
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            System.setSecurityManager(null);
+        }
+
+        ModuleFinder finder = ModuleFinder.of(Paths.get("mods1"), Paths.get("mods2"));
+
+        Layer bootLayer = Layer.boot();
+        Configuration parent = bootLayer.configuration();
+
+        Configuration cf = parent.resolveRequiresAndUses(finder,
+                                                         ModuleFinder.empty(),
+                                                         Set.of("m1", "m2"));
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithManyLoaders(cf, scl);
+
+        if (sm != null) {
+            System.setSecurityManager(sm);
+        }
+
+        Module m1 = bootLayer.findModule("m1").get();
+        Module m2 = bootLayer.findModule("m2").get();
+        Module m3 = bootLayer.findModule("m3").get();
+
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+        findClass(m3, "p3.internal.Foo");
+
+        // permissions granted
+        findClass(m1, "p1.A");
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+        findClass(m3, "p3.internal.Foo");
+
+
+        // m1 and m2 from a different layer
+        m1 = layer.findModule("m1").get();
+        m2 = layer.findModule("m2").get();
+        m3 = layer.findModule("m3").get();
+
+        findClass(m1, "p1.A");
+        findClass(m3, "p3.internal.Foo");
+
+        // no permission
+        Path path = MODS_DIR1.resolve("p1").resolve("internal").resolve("B.class");
+        findClass(m1, "p1.internal.B", new FilePermission(path.toString(), "read"));
+        path = MODS_DIR2.resolve("p2").resolve("C.class");
+        findClass(m2, "p2.C", new FilePermission(path.toString(), "read"));
+    }
+
+    static Class<?> findClass(Module module, String cn) {
+        return findClass(module, cn, null);
+    }
+
+    static Class<?> findClass(Module module, String cn, Permission perm) {
+        try {
+            Class<?> c = Class.forName(module, cn);
+            if (c == null) {
+                throw new RuntimeException(cn + " not found in " + module);
+            }
+            if (c.getModule() != module) {
+                throw new RuntimeException(c.getModule() + " != " + module);
+            }
+            return c;
+        } catch (AccessControlException e) {
+            if (e.getPermission().equals(perm))
+                return null;
+            throw e;
+        }
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoGetClassLoaderAccess.java b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoGetClassLoaderAccess.java
new file mode 100644
index 0000000..1c2ee70
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/NoGetClassLoaderAccess.java
@@ -0,0 +1,69 @@
+/*
+ * 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 java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.security.AccessControlException;
+import java.security.Permission;
+
+/**
+ * Verify RuntimePermission("getClassLoader") is needed to load
+ * a class in another module
+ */
+public class NoGetClassLoaderAccess {
+    private static final Module m3 = NoGetClassLoaderAccess.class.getModule();
+    private static final Permission GET_CLASSLOADER_PERMISSION = new RuntimePermission("getClassLoader");
+
+    public static void main(String[] args) throws Exception {
+        Layer boot = Layer.boot();
+
+        System.setSecurityManager(new SecurityManager());
+        Module m1 = boot.findModule("m1").get();
+        Module m2 = boot.findModule("m2").get();
+        findClass(m1, "p1.A");
+        findClass(m1, "p1.internal.B");
+        findClass(m2, "p2.C");
+        findClass(m3, "p3.internal.Foo");
+    }
+
+    static Class<?> findClass(Module module, String cn) {
+        try {
+            Class<?> c = Class.forName(module, cn);
+            if (c == null) {
+                throw new RuntimeException(cn + " not found in " + module);
+            }
+            if (c.getModule() != module) {
+                throw new RuntimeException(c.getModule() + " != " + module);
+            }
+            return c;
+        } catch (AccessControlException e) {
+            if (module != m3) {
+                if (e.getPermission().equals(GET_CLASSLOADER_PERMISSION))
+                    return null;
+            }
+            throw e;
+        }
+    }
+}
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m3/p3/internal/Foo.java b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/internal/Foo.java
new file mode 100644
index 0000000..c6693f1
--- /dev/null
+++ b/jdk/test/java/lang/Class/forName/modules/src/m3/p3/internal/Foo.java
@@ -0,0 +1,27 @@
+/*
+ * 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.internal;
+
+public class Foo {
+}
diff --git a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
index 71ee0df..45a7b8e 100644
--- a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
+++ b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
@@ -23,7 +23,11 @@
 
 import java.io.FilePermission;
 import java.io.IOException;
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
+import java.lang.reflect.Module;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.InaccessibleObjectException;
 import java.lang.reflect.ReflectPermission;
 import java.net.URI;
 import java.nio.file.FileSystem;
@@ -47,6 +51,8 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Stream;
 
+import jdk.internal.module.Modules;
+
 /**
  * @test
  * @bug 8065552
@@ -54,6 +60,7 @@
  *          set accessible if the right permission is granted; this test
  *          loads all the classes in the BCL, get their declared fields,
  *          and call setAccessible(false) followed by setAccessible(true);
+ * @modules java.base/jdk.internal.module
  * @run main/othervm FieldSetAccessibleTest UNSECURE
  * @run main/othervm FieldSetAccessibleTest SECURE
  *
@@ -73,22 +80,47 @@
 
 
     // Test that all fields for any given class can be made accessibles
-    static void testSetFieldsAccessible(Class<?> c) {
+    static void testSetFieldsAccessible(Class<?> c, boolean expectException) {
         for (Field f : c.getDeclaredFields()) {
             fieldCount.incrementAndGet();
-            f.setAccessible(false);
-            f.setAccessible(true);
+            boolean expect = expectException;
+            if ((c == Module.class || c == AccessibleObject.class) &&
+                !Modifier.isPublic(f.getModifiers())) {
+                expect = true;
+            }
+            try {
+                f.setAccessible(false);
+                f.setAccessible(true);
+                if (expect) {
+                    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) {
+                    throw new RuntimeException(expected);
+                }
+            }
         }
     }
 
     // Performs a series of test on the given class.
     // At this time, we only call testSetFieldsAccessible(c)
-    public static boolean test(Class<?> c) {
-        //System.out.println(c.getName());
+    public static boolean test(Class<?> c, boolean addExports) {
+        Module self = FieldSetAccessibleTest.class.getModule();
+        Module target = c.getModule();
+        String pn = c.getPackage().getName();
+        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);
+        testSetFieldsAccessible(c, expectException);
 
         // add more tests here...
 
@@ -154,17 +186,25 @@
         final long start = System.nanoTime();
         boolean classFound = false;
         int index = 0;
-        for (String s: iterable) {
+        for (String s : iterable) {
             if (index == maxIndex) break;
             try {
                 if (index < startIndex) continue;
-                if (test(s)) {
+                if (test(s, false)) {
                     classFound = true;
                 }
             } finally {
                 index++;
             }
         }
+
+        // Re-test with all packages exported
+        for (String s : iterable) {
+            test(s, true);
+        }
+
+        classCount.set(classCount.get() / 2);
+        fieldCount.set(fieldCount.get() / 2);
         long elapsed = System.nanoTime() - start;
         long secs = elapsed / 1000_000_000;
         long millis = (elapsed % 1000_000_000) / 1000_000;
@@ -187,17 +227,13 @@
         }
     }
 
-    static boolean test(String s) {
+    static boolean test(String s, boolean addExports) {
         try {
-            if (s.startsWith("WrapperGenerator")) {
-                System.out.println("Skipping "+ s);
-                return false;
-            }
             final Class<?> c = Class.forName(
                     s.replace('/', '.').substring(0, s.length() - 6),
                     false,
                     systemClassLoader);
-            return test(c);
+            return test(c, addExports);
         } catch (Exception t) {
             t.printStackTrace(System.err);
             failed.add(s);
@@ -224,7 +260,7 @@
                     .filter(x -> x.getNameCount() > 2)
                     .map( x-> x.subpath(2, x.getNameCount()))
                     .map( x -> x.toString())
-                    .filter(s -> s.endsWith(".class"));
+                    .filter(s -> s.endsWith(".class") && !s.endsWith("module-info.class"));
         }
 
         @Override
diff --git a/jdk/test/java/lang/Class/getPackageName/Basic.java b/jdk/test/java/lang/Class/getPackageName/Basic.java
new file mode 100644
index 0000000..e0c0bd1
--- /dev/null
+++ b/jdk/test/java/lang/Class/getPackageName/Basic.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @compile Basic.java
+ * @run testng p.Basic
+ * @summary Basic test for java.lang.Class::getPackageName
+ */
+
+package p;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+public class Basic {
+
+
+    // -- member classes --
+
+    static class Nested {
+        static class Foo { }
+    }
+
+    Class<?> getNestedClass1() {
+        return Nested.class;
+    }
+    Class<?> getNestedClass2() {
+        return Nested.Foo.class;
+    }
+
+    class Inner {
+        class Foo { }
+    }
+
+    Class<?> getInnerClass1() {
+        return Inner.class;
+    }
+    Class<?> getInnerClass2() {
+        return Inner.Foo.class;
+    }
+
+    // -- local and anonymous classes --
+
+    Class<?> getLocalClass1() {
+        class Local { }
+        return Local.class;
+    }
+
+    Class<?> getLocalClass2() {
+        class Local {
+            class Foo { }
+        }
+        return Local.Foo.class;
+    }
+
+    Class<?> getLocalClass3() {
+        class Local {
+            final Class<?> c;
+            Local() {
+                class Foo { }
+                this.c = Foo.class;
+            }
+            Class<?> get() {
+                return c;
+            }
+        }
+        return new Local().get();
+    }
+
+    Class<?> getAnonymousClass1() {
+        Runnable r = new Runnable() { public void run() { } };
+        return r.getClass();
+    }
+
+    Class<?> getAnonymousClass2() {
+        class Local {
+            Class<?> get() {
+                Runnable r = new Runnable() { public void run() { } };
+                return r.getClass();
+            }
+        }
+        return new Local().get();
+    }
+
+    Class<?> getAnonymousClass3() {
+        Runnable r = () -> { };
+        return r.getClass();
+    }
+
+    Class<?> getAnonymousClass4() {
+        class Local {
+            Class<?> get() {
+                Runnable r = () -> { };
+                return r.getClass();
+            }
+        }
+        return new Local().get();
+    }
+
+    Class<?> getAnonymousClass5() {
+        class Local {
+            final Class<?> c;
+            Local() {
+                Runnable r = new Runnable() { public void run() { } };
+                this.c = r.getClass();
+            }
+            Class<?> get() {
+                return c;
+            }
+        }
+        return new Local().get();
+    }
+
+    Class<?> getAnonymousClass6() {
+        class Local {
+            final Class<?> c;
+            Local() {
+                Runnable r = () -> { };
+                this.c = r.getClass();
+            }
+            Class<?> get() {
+                return c;
+            }
+        }
+        return new Local().get();
+    }
+
+    static final String TEST_PACKAGE = Basic.class.getPackage().getName();
+
+    @DataProvider(name = "classes")
+    public Object[][] classes() {
+        return new Object[][] {
+
+            { Basic.class,                  TEST_PACKAGE },
+            { Basic[].class,                null },
+            { Basic[][].class,              null },
+
+            { getNestedClass1(),            TEST_PACKAGE },
+            { getNestedClass2(),            TEST_PACKAGE },
+            { getInnerClass1(),             TEST_PACKAGE },
+            { getInnerClass2(),             TEST_PACKAGE },
+
+            { getLocalClass1(),             TEST_PACKAGE },
+            { getLocalClass2(),             TEST_PACKAGE },
+            { getLocalClass3(),             TEST_PACKAGE },
+
+            { getAnonymousClass1(),         TEST_PACKAGE },
+            { getAnonymousClass2(),         TEST_PACKAGE },
+            { getAnonymousClass3(),         TEST_PACKAGE },
+            { getAnonymousClass4(),         TEST_PACKAGE },
+            { getAnonymousClass5(),         TEST_PACKAGE },
+            { getAnonymousClass6(),         TEST_PACKAGE },
+
+            { Object.class,                 "java.lang" },
+            { Object[].class,               null },
+            { Object[][].class,             null },
+
+            { int.class,                    null },
+            { int[].class,                  null },
+            { int[][].class,                null },
+
+            { void.class,                   null },
+
+        };
+    }
+
+    @Test(dataProvider = "classes")
+    public void testPackageName(Class<?> type, String expected) {
+        assertEquals(type.getPackageName(), expected);
+    }
+
+}
diff --git a/jdk/test/java/lang/Class/getResource/Main.java b/jdk/test/java/lang/Class/getResource/Main.java
new file mode 100644
index 0000000..b1b45f3
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/Main.java
@@ -0,0 +1,167 @@
+/*
+ * 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.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;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Basic test of Class getResource and getResourceAsStream when invoked from
+ * code in named modules.
+ */
+
+public class Main {
+
+    static final String NAME = "myresource";
+
+    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 m2/myresource containing "m2"
+        file = directoryFor("m2").resolve(NAME);
+        Files.write(file, "m2".getBytes("UTF-8"));
+
+        // 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 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);
+
+        // check contents of resurces at url1 and url2
+        assertEquals(new String(readAll(url1), "UTF-8"), "m1");
+        assertEquals(new String(readAll(url2), "UTF-8"), "m2");
+
+        // invoke Class getResourceAsStream from the unnamed module
+        InputStream in0 = Main.class.getResourceAsStream("/" + NAME);
+        assertNull(in0);
+
+        // 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);
+
+        // 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);
+
+        // 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");
+
+        // SecurityManager case
+        System.setSecurityManager(new SecurityManager());
+
+        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!");
+    }
+
+    /**
+     * Returns the directory for the given module (by name).
+     */
+    static Path directoryFor(String name) {
+        Configuration cf = Layer.boot().configuration();
+        ResolvedModule resolvedModule = cf.findModule(name).orElse(null);
+        if (resolvedModule == null)
+            throw new RuntimeException("not found: " + name);
+        Path dir = Paths.get(resolvedModule.reference().location().get());
+        if (!Files.isDirectory(dir))
+            throw new RuntimeException("not a directory: " + dir);
+        return dir;
+    }
+
+    static byte[] readAll(URL url) throws IOException {
+        try (InputStream in = url.openStream()) {
+            return in.readAllBytes();
+        }
+    }
+
+    static void assertTrue(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/Class/getResource/ResourcesTest.java b/jdk/test/java/lang/Class/getResource/ResourcesTest.java
new file mode 100644
index 0000000..a78e335
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/ResourcesTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+
+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 jdk.compiler
+ * @build ResourcesTest CompilerUtils jdk.testlibrary.*
+ * @run testng ResourcesTest
+ * @summary Driver for basic test of Class getResource and getResourceAsStream
+ */
+
+@Test
+public class ResourcesTest {
+
+    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");
+
+
+    /**
+     * Compiles the modules used by the test and the test Main
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        boolean compiled;
+
+        // javac -modulesource mods -d mods src/**
+        compiled = CompilerUtils
+            .compile(SRC_DIR,
+                     MODS_DIR,
+                     "-modulesourcepath", SRC_DIR.toString());
+        assertTrue(compiled);
+
+        // javac -mp mods -d classes Main.java
+        compiled = CompilerUtils
+            .compile(Paths.get(TEST_SRC, "Main.java"),
+                     CLASSES_DIR,
+                     "-mp", MODS_DIR.toString(),
+                     "-addmods", "m1,m2,m3");
+        assertTrue(compiled);
+
+    }
+
+    /**
+     * Run the test
+     */
+    public void runTest() throws Exception {
+
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "m1,m2,m3",
+                               "-cp", CLASSES_DIR.toString(),
+                              "Main")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+}
+
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
new file mode 100644
index 0000000..47a2c4c
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    exports p1;
+}
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
new file mode 100644
index 0000000..afc1395
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m1/p1/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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 p1;
+
+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/Class/getResource/src/m2/module-info.java b/jdk/test/java/lang/Class/getResource/src/m2/module-info.java
new file mode 100644
index 0000000..e28b220
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports p2;
+}
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
new file mode 100644
index 0000000..51bdcf6
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m2/p2/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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 p2;
+
+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/Class/getResource/src/m3/module-info.java b/jdk/test/java/lang/Class/getResource/src/m3/module-info.java
new file mode 100644
index 0000000..f9754a0
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m3/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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
new file mode 100644
index 0000000..08062e1
--- /dev/null
+++ b/jdk/test/java/lang/Class/getResource/src/m3/p3/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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/GetSystemPackage.java b/jdk/test/java/lang/ClassLoader/GetSystemPackage.java
index 3e7d326..fba5648 100644
--- a/jdk/test/java/lang/ClassLoader/GetSystemPackage.java
+++ b/jdk/test/java/lang/ClassLoader/GetSystemPackage.java
@@ -85,15 +85,15 @@
         buildJar("no-manifest.jar", null);
 
         runSubProcess("System package with manifest improperly resolved.",
-                "-Xbootclasspath/p:" + testClassesDir + "/manifest.jar",
+                "-Xbootclasspath/a:" + testClassesDir + "/manifest.jar",
                 "GetSystemPackage", "system-manifest");
 
         runSubProcess("System package from directory improperly resolved.",
-                "-Xbootclasspath/p:" + testClassesDir, "GetSystemPackage",
+                "-Xbootclasspath/a:" + testClassesDir, "GetSystemPackage",
                 "system-no-manifest");
 
         runSubProcess("System package with no manifest improperly resolved",
-                "-Xbootclasspath/p:" + testClassesDir + "/no-manifest.jar",
+                "-Xbootclasspath/a:" + testClassesDir + "/no-manifest.jar",
                 "GetSystemPackage", "system-no-manifest");
 
         runSubProcess("Classpath package with manifest improperly resolved",
@@ -112,8 +112,6 @@
                 testClassesDir + "/package2/Class2.class");
         jar.addClassFile("GetSystemPackage.class",
                 testClassesDir + "/GetSystemPackage.class");
-        jar.addClassFile("GetSystemPackageClassLoader.class",
-                testClassesDir + "/GetSystemPackageClassLoader.class");
         jar.build();
     }
 
@@ -128,9 +126,10 @@
     }
 
     private static void verifyPackage(boolean hasManifest,
-            boolean isSystemPackage) throws Exception
+                                      boolean isSystemPackage)
+            throws Exception
     {
-        Class c = Class.forName("package2.Class2");
+        Class<?> c = Class.forName("package2.Class2");
         Package pkg = c.getPackage();
         if (pkg == null || pkg != Package.getPackage("package2") ||
                 !"package2".equals(pkg.getName())) {
@@ -148,14 +147,11 @@
         }
         if (!hasManifest && specificationTitle != null) {
             fail("Invalid manifest for package " + pkg.getName() + ": was " +
-                 specificationTitle + " expected: null");
+                    specificationTitle + " expected: null");
         }
 
-        // force the use of a classloader with no parent, then retrieve the
-        // package in a way that bypasses the classloader pkg maps
-        GetSystemPackageClassLoader classLoader =
-                new GetSystemPackageClassLoader();
-        Package systemPkg = classLoader.getSystemPackage("package2");
+        ClassLoader ld = c.getClassLoader();
+        Package systemPkg = ld != null ? null : Package.getPackage("package2");
 
         if (findPackage("java.lang") == null) {
             fail("java.lang not found via Package.getPackages()");
@@ -194,21 +190,6 @@
 }
 
 /*
- * This classloader bypasses the system classloader to give as direct access
- * to Package.getSystemPackage() as possible
- */
-class GetSystemPackageClassLoader extends ClassLoader {
-
-    public GetSystemPackageClassLoader() {
-        super(null);
-    }
-
-    public Package getSystemPackage(String name) {
-        return super.getPackage(name);
-    }
-}
-
-/*
  * Helper class for building jar files
  */
 class JarBuilder {
diff --git a/jdk/test/java/lang/ClassLoader/findSystemClass/Loader.java b/jdk/test/java/lang/ClassLoader/findSystemClass/Loader.java
index e141462..94f1726 100644
--- a/jdk/test/java/lang/ClassLoader/findSystemClass/Loader.java
+++ b/jdk/test/java/lang/ClassLoader/findSystemClass/Loader.java
@@ -44,7 +44,6 @@
  *      - Loadee.java            (source for a class that refers to Loader)
  *      - Loadee.classfile       (to test findSystemClass)
  *      - Loadee.resource        (to test getSystemResource)
- *      - java/lang/Object.class (to test getSystemResources)
  *
  * The extension ".classfile" is so the class file is not seen by any loader
  * other than Loader.  If you need to make any changes you will have to
@@ -127,25 +126,6 @@
                 throw new Exception
                     ("java.lang.ClassLoader.getSystemResource() test failed!");
         }
-
-        if ((tests & RESOURCES) == RESOURCES) {
-            report("getSystemResources()");
-            java.util.Enumeration e =
-                getSystemResources("java/lang/Object.class");
-            HashSet hs = new HashSet();
-            while (e.hasMoreElements()) {
-                URL u = (URL)e.nextElement();
-                if (u == null)
-                    break;
-                System.out.println("url: " + u);
-                hs.add(u);
-            }
-            if (hs.size() != 2) {
-                throw
-                    new Exception("java.lang.ClassLoader.getSystemResources()"+
-                                  " did not find all resources");
-            }
-        }
     }
 
     private static void report(String s) {
diff --git a/jdk/test/java/lang/ClassLoader/getResource/GetResource.sh b/jdk/test/java/lang/ClassLoader/getResource/GetResource.sh
index 2f178cd..fc365db 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/GetResource.sh
+++ b/jdk/test/java/lang/ClassLoader/getResource/GetResource.sh
@@ -29,21 +29,12 @@
 #
 # @run shell GetResource.sh
 
-if [ "${TESTSRC}" = "" ] ; then
-    TESTSRC=`pwd`
-fi
-if [ "${TESTCLASSES}" = "" ] ; then
-    TESTCLASSES=`pwd`
-fi
-
-if [ "${TESTJAVA}" = "" ] ; then
-    echo "TESTJAVA not set.  Test cannot execute."
-    echo "FAILED!!!"
-    exit 1
-fi
-
-if [ "${COMPILEJAVA}" = "" ] ; then
-    COMPILEJAVA="${TESTJAVA}"
+if [ -z "$TESTJAVA" ]; then
+  if [ $# -lt 1 ]; then exit 1; fi
+  TESTJAVA="$1"; shift
+  COMPILEJAVA="${TESTJAVA}"
+  TESTSRC="`pwd`"
+  TESTCLASSES="`pwd`"
 fi
 
 # set platform-specific variables
@@ -96,12 +87,7 @@
 cd ${TESTCLASSES}
 DIR=`pwd`
 
-#    Expected    -Xbootclasspath
-#    Location    or -classpath
-runTest "a"      "-Xbootclasspath/p:a"
-runTest "a"      "-Xbootclasspath/p:a${PS}b"
-runTest "b"      "-Xbootclasspath/p:b" 
-runTest "b"      "-Xbootclasspath/p:b${PS}a"
+#    Expected    -classpath
 runTest "a"      -cp a
 runTest "a"      -cp "a${PS}b"
 runTest "b"      -cp b
@@ -109,16 +95,10 @@
 
 cd ${DIR}/a
 
-runTest "a"      "-Xbootclasspath/p:."
-runTest "b"      "-Xbootclasspath/p:../b" 
-
 # no -classpath
 runTest "a"      -cp "${PS}"                            
 runTest "b"      -cp "../b"                   
 
-# Test empty path in bootclasspath not default to current working directory
-runTest "b"      "-Xbootclasspath/p:${PS}../b" 
-
 # Test empty path in classpath default to current working directory
 runTest "a"      -cp "${PS}../b"
 
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java b/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java
new file mode 100644
index 0000000..a6436af
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java
@@ -0,0 +1,112 @@
+/*
+ * 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.lang.module.Configuration;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Basic test of ClassLoader getResource and getResourceAsStream when
+ * invoked from code in named modules.
+ */
+
+public class Main {
+
+    static final String NAME = "myresource";
+
+    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 m2/myresource containing "m2"
+        file = directoryFor("m2").resolve(NAME);
+        Files.write(file, "m2".getBytes("UTF-8"));
+
+        // 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));
+
+        // 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));
+
+        // invoke ClassLoader getResourceAsStream from the unnamed module
+        assertNull(Main.class.getClassLoader().getResourceAsStream("/" + NAME));
+
+        // 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));
+
+        // SecurityManager case
+        System.setSecurityManager(new SecurityManager());
+
+        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!");
+    }
+
+    /**
+     * Returns the directory for the given module (by name).
+     */
+    static Path directoryFor(String mn) {
+        Configuration cf = Layer.boot().configuration();
+        ResolvedModule resolvedModule = cf.findModule(mn).orElse(null);
+        if (resolvedModule == null)
+            throw new RuntimeException("not found: " + mn);
+        Path dir = Paths.get(resolvedModule.reference().location().get());
+        if (!Files.isDirectory(dir))
+            throw new RuntimeException("not a directory: " + dir);
+        return dir;
+    }
+
+    static void assertTrue(boolean condition) {
+        if (!condition) throw new RuntimeException();
+    }
+
+    static void assertNull(Object o) {
+        assertTrue(o == null);
+    }
+}
+
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java b/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java
new file mode 100644
index 0000000..c6e1bcf
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.executeTestJava;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8087335
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build ResourcesTest CompilerUtils jdk.testlibrary.*
+ * @run testng ResourcesTest
+ * @summary Driver for basic test of ClassLoader getResource and getResourceAsStream
+ */
+
+@Test
+public class ResourcesTest {
+
+    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");
+
+    /**
+     * Compiles the modules used by the test and the test Main
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        boolean compiled;
+
+        // javac -modulesource mods -d mods src/**
+        compiled = CompilerUtils
+            .compile(SRC_DIR,
+                     MODS_DIR,
+                     "-modulesourcepath", SRC_DIR.toString());
+        assertTrue(compiled);
+
+        // javac -mp mods -d classes Main.java
+        compiled = CompilerUtils
+            .compile(Paths.get(TEST_SRC, "Main.java"),
+                     CLASSES_DIR,
+                     "-mp", MODS_DIR.toString(),
+                     "-addmods", "m1,m2,m3");
+        assertTrue(compiled);
+    }
+
+    /**
+     * Run the test
+     */
+    public void runTest() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "m1,m2,m3",
+                               "-cp", CLASSES_DIR.toString(),
+                              "Main")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+}
+
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
new file mode 100644
index 0000000..47a2c4c
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    exports p1;
+}
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
new file mode 100644
index 0000000..9e14eb0
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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 p1;
+
+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/ClassLoader/getResource/modules/src/m2/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java
new file mode 100644
index 0000000..e28b220
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports p2;
+}
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
new file mode 100644
index 0000000..6f291a2
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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 p2;
+
+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/ClassLoader/getResource/modules/src/m3/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/module-info.java
new file mode 100644
index 0000000..f9754a0
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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
new file mode 100644
index 0000000..55a23b9
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/p3/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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/ClassLoader/platformClassLoader/DefinePlatformClass.java b/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java
new file mode 100644
index 0000000..d02c483
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java
@@ -0,0 +1,43 @@
+/*
+ * 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 java.* class defined by the platform class loader
+ * @build jdk.zipfs/java.fake.Fake
+ * @modules jdk.zipfs/java.fake
+ * @run main DefinePlatformClass
+ */
+
+import java.fake.Fake;
+
+public class DefinePlatformClass {
+    public static void main(String... args) {
+        Fake fake = new Fake();
+        fake.run();
+        ClassLoader loader = fake.getClass().getClassLoader();
+        if (loader != ClassLoader.getPlatformClassLoader()) {
+            throw new RuntimeException("unexpected class loader: " + loader);
+        }
+    }
+}
diff --git a/jdk/test/java/lang/ClassLoader/platformClassLoader/jdk.zipfs/java/fake/Fake.java b/jdk/test/java/lang/ClassLoader/platformClassLoader/jdk.zipfs/java/fake/Fake.java
new file mode 100644
index 0000000..67d7dc0
--- /dev/null
+++ b/jdk/test/java/lang/ClassLoader/platformClassLoader/jdk.zipfs/java/fake/Fake.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.fake;
+
+public class Fake {
+    public void run() {}
+}
diff --git a/jdk/test/java/lang/Package/Foo.java b/jdk/test/java/lang/Package/Foo.java
new file mode 100644
index 0000000..9243bae
--- /dev/null
+++ b/jdk/test/java/lang/Package/Foo.java
@@ -0,0 +1,34 @@
+/*
+ * 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 foo;
+
+public class Foo {
+    /**
+     * Returns all Packages visible to the class loader defining by
+     * this Foo class.  Package.getPackages() is caller-sensitive.
+     */
+    public static Package[] getPackages() {
+        return Package.getPackages();
+    }
+}
+
diff --git a/jdk/test/java/lang/Package/GetPackages.java b/jdk/test/java/lang/Package/GetPackages.java
new file mode 100644
index 0000000..3f0a4d9
--- /dev/null
+++ b/jdk/test/java/lang/Package/GetPackages.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test Package object is local to each ClassLoader.
+ *          There can be one Package object of "foo" name defined by
+ *          different class loader.
+ * @compile Foo.java
+ * @run testng GetPackages
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.lang.reflect.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class GetPackages {
+    final TestClassLoader loader;
+    final Class<?> fooClass;
+    /*
+     * Each TestClassLoader defines a "foo.Foo" class which has a unique
+     * Package object of "foo" regardless whether its ancestor class loader
+     * defines a package "foo" or not.
+     */
+    GetPackages(TestClassLoader loader) throws ClassNotFoundException {
+        this.loader = loader;
+        this.fooClass = loader.loadClass("foo.Foo");
+    }
+
+    /*
+     * Check package "foo" defined locally in the TestClassLoader
+     * as well as its ancestors.
+     */
+    void checkPackage() throws ClassNotFoundException {
+        // Name of an unnamed package is empty string
+        assertEquals(this.getClass().getPackage().getName(), "");
+
+        assertEquals(fooClass.getClassLoader(), loader);
+
+        Package p = loader.getDefinedPackage("foo");
+        assertEquals(p.getName(), "foo");
+        assertEquals(p, loader.getPackage("foo"));
+
+        if (loader.getParent() != null) {
+            Package p2 = ((TestClassLoader)loader.getParent()).getDefinedPackage("foo");
+            assertTrue(p != p2);
+        }
+
+        long count = Arrays.stream(loader.getDefinedPackages())
+                            .map(Package::getName)
+                            .filter(pn -> pn.equals("foo"))
+                            .count();
+        assertEquals(count, 1);
+    }
+
+    /*
+     * Check the number of package "foo" defined to this class loader and
+     * its ancestors
+     */
+    Package[] getPackagesFromLoader() {
+        return loader.packagesInClassLoaderChain();
+    }
+
+    /*
+     * Package.getPackages is caller-sensitve.  Call through Foo class
+     * to find all Packages visible to this TestClassLoader and its ancestors
+     */
+    Package[] getPackagesFromFoo() throws Exception {
+        Method m = fooClass.getMethod("getPackages");
+        return (Package[])m.invoke(null);
+    }
+
+    private static long numFooPackages(Package[] pkgs) throws Exception {
+        return Arrays.stream(pkgs)
+                     .filter(p -> p.getName().equals("foo"))
+                     .count();
+    }
+
+    @DataProvider(name = "loaders")
+    public static Object[][] testLoaders() {
+        TestClassLoader loader1 = new TestClassLoader(null);
+        TestClassLoader loader2 = new TestClassLoader(loader1);
+        TestClassLoader loader3 = new TestClassLoader(loader2);
+
+        // Verify the number of expected Package object of "foo" visible
+        // to the class loader
+        return new Object[][] {
+                { loader1, 1 },
+                { loader2, 2 },
+                { loader3, 3 }
+        };
+    }
+
+    @Test(dataProvider = "loaders")
+    public static void test(TestClassLoader loader, long expected) throws Exception {
+        GetPackages test = new GetPackages(loader);
+        // check package "foo" existence
+        test.checkPackage();
+
+        assertEquals(numFooPackages(test.getPackagesFromLoader()), expected);
+        assertEquals(numFooPackages(test.getPackagesFromFoo()), expected);
+    }
+}
+
+class TestClassLoader extends ClassLoader {
+    public TestClassLoader() {
+        super();
+    }
+
+    public TestClassLoader(ClassLoader parent) {
+        super(parent);
+    }
+
+    public Package getPackage(String pn) {
+        return super.getPackage(pn);
+    }
+
+    public Package[] packagesInClassLoaderChain() {
+        return super.getPackages();
+    }
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        Path p = Paths.get(System.getProperty("test.classes", "."));
+
+        try {
+            byte[] bb = Files.readAllBytes(p.resolve("foo/Foo.class"));
+            return defineClass(name, bb, 0, bb.length);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+    @Override
+    protected Class<?> loadClass(String cn, boolean resolve) throws ClassNotFoundException {
+        if (!cn.equals("foo.Foo"))
+            return super.loadClass(cn, resolve);
+        return findClass(cn);
+    }
+}
diff --git a/jdk/test/java/lang/Package/annotation/PackageInfoTest.java b/jdk/test/java/lang/Package/annotation/PackageInfoTest.java
new file mode 100644
index 0000000..6e41390
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/PackageInfoTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Basic test of package-info in named module and duplicate
+ *          package-info in unnamed module
+ * @modules java.compiler
+ *          java.desktop
+ *          jdk.compiler
+ *          jdk.xml.dom
+ * @build jdk.xml.dom/org.w3c.dom.css.Fake
+ *        jdk.xml.dom/org.w3c.dom.css.FakePackage
+ * @compile/module=jdk.xml.dom org/w3c/dom/css/package-info.java
+ * @compile package-info.java PackageInfoTest.java
+ * @run testng p.PackageInfoTest
+ */
+
+package p;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.css.CSSRule;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import static org.testng.Assert.*;
+
+public class PackageInfoTest {
+    @DataProvider(name = "jdkClasses")
+    public Object[][] jdkClasses() {
+        return new Object[][] {
+            { java.awt.Button.class,             null },
+            { java.lang.Object.class,            null },
+            { org.w3c.dom.css.CSSRule.class,     null },
+            { loadClass("org.w3c.dom.css.Fake"), loadClass("org.w3c.dom.css.FakePackage") },
+        };
+    }
+
+    @Test(dataProvider = "jdkClasses")
+    public void testPackageInfo(Class<?> type, Class<? extends Annotation> annType) {
+        Package pkg = type.getPackage();
+        assertTrue(pkg.isSealed());
+        assertTrue(annType == null || pkg.getDeclaredAnnotations().length != 0);
+        if (annType != null) {
+            assertTrue(pkg.isAnnotationPresent(annType));
+        }
+    }
+
+    private Class<?> loadClass(String name) {
+        return Class.forName(CSSRule.class.getModule(), name);
+    }
+
+    @DataProvider(name = "classpathClasses")
+    public Object[][] cpClasses() throws IOException, ClassNotFoundException {
+        // these classes will be loaded from classpath in unnamed module
+        return new Object[][]{
+                { p.PackageInfoTest.class, Deprecated.class }
+        };
+    }
+
+    @Test(dataProvider = "classpathClasses")
+    public void testClassPathPackage(Class<?> type, Class<? extends Annotation> annType) {
+        Package pkg = type.getPackage();
+        assertTrue(pkg.isSealed() == false);
+        assertTrue(pkg.isAnnotationPresent(annType));
+    }
+
+    static final String[] otherClasses = new String[] {
+            "p/package-info.class",
+            "p/Duplicate.class",
+            "p/Bar.class"
+    };
+
+    @Test
+    public void testDuplicatePackage() throws Exception {
+        // a custom class loader loading another package p annotated with @Duplicate
+        Path classes = Paths.get(System.getProperty("test.classes", "."), "tmp");
+        Files.createDirectories(classes);
+        URLClassLoader loader = new URLClassLoader(new URL[] { classes.toUri().toURL() });
+
+        // clean up before compiling classes
+        Arrays.stream(otherClasses)
+                .forEach(c -> {
+                    try {
+                        Files.deleteIfExists(classes.resolve(c));
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                });
+
+        Path src = Paths.get(System.getProperty("test.src", "."), "src", "p");
+        compile(classes,
+                src.resolve("package-info.java"),
+                src.resolve("Duplicate.java"),
+                src.resolve("Bar.java"));
+
+        // verify if classes are present
+        Arrays.stream(otherClasses)
+              .forEach(c -> {
+                  if (Files.notExists(classes.resolve(c))) {
+                      throw new RuntimeException(c + " not exist");
+                  }
+        });
+
+        Class<?> c = Class.forName("p.Bar", true, loader);
+        assertTrue(c.getClassLoader() == loader);
+        assertTrue(this.getClass().getClassLoader() != loader);
+
+        // package p defined by the custom class loader
+        Package pkg = c.getPackage();
+        assertTrue(pkg.getName().equals("p"));
+        assertTrue(pkg.isSealed() == false);
+
+        // package p defined by the application class loader
+        Package p = this.getClass().getPackage();
+        assertTrue(p.getName().equals("p"));
+        assertTrue(p != pkg);
+
+        Arrays.stream(pkg.getDeclaredAnnotations())
+              .forEach(ann -> System.out.format("%s @%s%n", pkg.getName(), ann));
+
+        Arrays.stream(p.getDeclaredAnnotations())
+              .forEach(ann -> System.out.format("%s @%s%n", p.getName(), ann));
+
+        // local package p defined by loader
+        Class<? extends Annotation> ann =
+            (Class<? extends Annotation>)Class.forName("p.Duplicate", false, loader);
+        assertTrue(pkg.isAnnotationPresent(ann));
+    }
+
+    private void compile(Path destDir, Path... files) throws IOException {
+        compile(null, destDir, files);
+    }
+
+    private void compile(String option, Path destDir, Path... files)
+            throws IOException
+    {
+        System.err.println("compile...");
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+            Iterable<? extends JavaFileObject> fileObjects =
+                fm.getJavaFileObjectsFromPaths(Arrays.asList(files));
+
+            List<String> options = new ArrayList<>();
+            if (option != null) {
+                options.add(option);
+            }
+            if (destDir != null) {
+                options.add("-d");
+                options.add(destDir.toString());
+            }
+            options.add("-cp");
+            options.add(System.getProperty("test.classes", "."));
+
+            JavaCompiler.CompilationTask task =
+                compiler.getTask(null, fm, null, options, null, fileObjects);
+            if (!task.call())
+                throw new AssertionError("compilation failed");
+        }
+    }
+
+}
diff --git a/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/Fake.java b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/Fake.java
new file mode 100644
index 0000000..88e5fb6
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/Fake.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.w3c.dom.css;
+
+public class Fake {}
diff --git a/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/FakePackage.java b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/FakePackage.java
new file mode 100644
index 0000000..4323286
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/FakePackage.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.w3c.dom.css;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value={PACKAGE})
+public @interface FakePackage {
+}
+
diff --git a/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/package-info.java b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/package-info.java
new file mode 100644
index 0000000..7d200df
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/jdk.xml.dom/org/w3c/dom/css/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+@FakePackage
+package org.w3c.dom.css;
diff --git a/jdk/test/java/lang/Package/annotation/package-info.java b/jdk/test/java/lang/Package/annotation/package-info.java
new file mode 100644
index 0000000..6b5931c
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+@Deprecated
+package p;
diff --git a/jdk/test/java/lang/Package/annotation/src/p/Bar.java b/jdk/test/java/lang/Package/annotation/src/p/Bar.java
new file mode 100644
index 0000000..0f23144
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/src/p/Bar.java
@@ -0,0 +1,26 @@
+/*
+ * 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 Bar {}
diff --git a/jdk/test/java/lang/Package/annotation/src/p/Duplicate.java b/jdk/test/java/lang/Package/annotation/src/p/Duplicate.java
new file mode 100644
index 0000000..eacbd89
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/src/p/Duplicate.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value={PACKAGE})
+public @interface Duplicate {
+}
+
diff --git a/jdk/test/java/lang/Package/annotation/src/p/package-info.java b/jdk/test/java/lang/Package/annotation/src/p/package-info.java
new file mode 100644
index 0000000..2975a18
--- /dev/null
+++ b/jdk/test/java/lang/Package/annotation/src/p/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+@Duplicate
+package p;
diff --git a/jdk/test/java/lang/SecurityManager/RestrictedPackages.java b/jdk/test/java/lang/SecurityManager/RestrictedPackages.java
index 546df6b..56d0ed5 100644
--- a/jdk/test/java/lang/SecurityManager/RestrictedPackages.java
+++ b/jdk/test/java/lang/SecurityManager/RestrictedPackages.java
@@ -77,6 +77,7 @@
         "jdk.internal.",
         "jdk.nashorn.internal.",
         "jdk.nashorn.tools.",
+        "jdk.rmi.rmic.",
         "jdk.tools.jimage.",
         "com.sun.activation.registries.",
         "com.sun.java.accessibility.util.internal."
diff --git a/jdk/test/java/lang/SecurityManager/modules/CustomSecurityManager.sh b/jdk/test/java/lang/SecurityManager/modules/CustomSecurityManager.sh
new file mode 100644
index 0000000..e722677
--- /dev/null
+++ b/jdk/test/java/lang/SecurityManager/modules/CustomSecurityManager.sh
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @summary Basic test of -Djava.security.manager to a class in 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
+
+OS=`uname -s`
+case "$OS" in
+  Windows*)
+    PS=";"
+    ;;
+  CYGWIN* )
+    PS=";"
+    ;;
+  * )
+    PS=":"
+    ;;
+esac
+
+JAVAC="$COMPILEJAVA/bin/javac"
+JAVA="$TESTJAVA/bin/java ${TESTVMOPTS}"
+
+mkdir -p mods
+$JAVAC -d mods -modulesourcepath ${TESTSRC} `find ${TESTSRC}/m -name "*.java"`
+
+mkdir -p classes
+$JAVAC -d classes ${TESTSRC}/Test.java
+
+$JAVA -cp classes -mp mods -addmods m \
+    -Djava.security.manager \
+    -Djava.security.policy=${TESTSRC}/test.policy Test
+$JAVA -cp classes -mp mods -addmods m \
+    -Djava.security.manager=p.CustomSecurityManager \
+    -Djava.security.policy=${TESTSRC}/test.policy Test
+
+exit 0
diff --git a/jdk/test/java/lang/SecurityManager/modules/Test.java b/jdk/test/java/lang/SecurityManager/modules/Test.java
new file mode 100644
index 0000000..81cf617
--- /dev/null
+++ b/jdk/test/java/lang/SecurityManager/modules/Test.java
@@ -0,0 +1,36 @@
+/*
+ * 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.Module;
+
+public class Test {
+    public static void main(String... args) {
+        SecurityManager sm = System.getSecurityManager();
+        Module module = sm.getClass().getModule();
+        String s = System.getProperty("java.security.manager");
+        String expected = s.isEmpty() ? "java.base" : "m";
+        if (!module.isNamed() || !module.getName().equals(expected)) {
+            throw new RuntimeException(module + " expected module m instead");
+        }
+    }
+}
diff --git a/jdk/test/java/lang/SecurityManager/modules/m/module-info.java b/jdk/test/java/lang/SecurityManager/modules/m/module-info.java
new file mode 100644
index 0000000..cf46bcc
--- /dev/null
+++ b/jdk/test/java/lang/SecurityManager/modules/m/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 m {
+}
diff --git a/jdk/test/java/lang/SecurityManager/modules/m/p/CustomSecurityManager.java b/jdk/test/java/lang/SecurityManager/modules/m/p/CustomSecurityManager.java
new file mode 100644
index 0000000..bc6e22d
--- /dev/null
+++ b/jdk/test/java/lang/SecurityManager/modules/m/p/CustomSecurityManager.java
@@ -0,0 +1,29 @@
+/*
+ * 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 CustomSecurityManager extends SecurityManager {
+    public CustomSecurityManager() {
+    }
+}
diff --git a/jdk/test/java/lang/SecurityManager/modules/test.policy b/jdk/test/java/lang/SecurityManager/modules/test.policy
new file mode 100644
index 0000000..a3929e3
--- /dev/null
+++ b/jdk/test/java/lang/SecurityManager/modules/test.policy
@@ -0,0 +1,3 @@
+grant {
+        permission java.util.PropertyPermission "*", "read";
+};
diff --git a/jdk/test/java/lang/StackTraceElement/ModuleFrames.java b/jdk/test/java/lang/StackTraceElement/ModuleFrames.java
new file mode 100644
index 0000000..a3b6675
--- /dev/null
+++ b/jdk/test/java/lang/StackTraceElement/ModuleFrames.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Stack trace should have module information
+ * @run testng ModuleFrames
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class ModuleFrames {
+
+    @Test
+    public void testModuleName() {
+        try {
+            Integer.parseInt("a");
+        } catch (NumberFormatException e) {
+
+            StackTraceElement[] stack = e.getStackTrace();
+            StackTraceElement topFrame = stack[0];
+            StackTraceElement thisFrame = findFrame(this.getClass().getName(), stack);
+
+            assertEquals(topFrame.getModuleName(), "java.base",
+                    "Expected top frame to be in module java.base");
+
+            assertTrue(topFrame.toString().contains("java.base"),
+                    "Expected toString of top frame to include java.base");
+
+            assertNull(thisFrame.getModuleName(),
+                    "Expected frame for test not to have a module name");
+        }
+    }
+
+    private static StackTraceElement findFrame(String cn, StackTraceElement[] stack) {
+        return Arrays.stream(stack)
+                .filter(s -> s.getClassName().equals(cn))
+                .findFirst()
+                .get();
+    }
+}
diff --git a/jdk/test/java/lang/StackTraceElement/PublicConstructor.java b/jdk/test/java/lang/StackTraceElement/PublicConstructor.java
index b83538e..b4ec9a4 100644
--- a/jdk/test/java/lang/StackTraceElement/PublicConstructor.java
+++ b/jdk/test/java/lang/StackTraceElement/PublicConstructor.java
@@ -41,9 +41,25 @@
             throw new RuntimeException("1");
         if (ste.isNativeMethod())
             throw new RuntimeException("2");
-        StackTraceElement ste2 = new StackTraceElement("com.acme.Widget",
-            "frobnicate", "Widget.java", -2);
-        if (!ste2.isNativeMethod())
+        StackTraceElement ste2
+            = new StackTraceElement("jdk.module",
+                                    "9.0",
+                                    "com.acme.Widget",
+                                    "frobnicate",
+                                    "Widget.java",
+                                    42);
+        if (!(ste2.getClassName().equals("com.acme.Widget")  &&
+                ste2.getModuleName().equals("jdk.module") &&
+                ste2.getModuleVersion().equals("9.0") &&
+                ste2.getFileName().equals("Widget.java") &&
+                ste2.getMethodName().equals("frobnicate") &&
+                ste2.getLineNumber() == 42))
             throw new RuntimeException("3");
+        if (ste2.isNativeMethod())
+            throw new RuntimeException("4");
+        StackTraceElement ste3 = new StackTraceElement("com.acme.Widget",
+            "frobnicate", "Widget.java", -2);
+        if (!ste3.isNativeMethod())
+            throw new RuntimeException("5");
     }
 }
diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java
index c6c46fb..b5f8653 100644
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java
@@ -72,7 +72,7 @@
             "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:158)\n" +
             "4: VerifyStackTrace.invoke(VerifyStackTrace.java:188)\n" +
             "5: VerifyStackTrace$1.run(VerifyStackTrace.java:218)\n" +
-            "6: java.security.AccessController.doPrivileged(Native Method)\n" +
+            "6: java.security.AccessController.doPrivileged(java.base/Native Method)\n" +
             "7: VerifyStackTrace.test(VerifyStackTrace.java:227)\n" +
             "8: VerifyStackTrace.main(VerifyStackTrace.java:182)\n";
 
@@ -101,12 +101,12 @@
             "2: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:147)\n" +
             "3: VerifyStackTrace$Handle.run(VerifyStackTrace.java:160)\n" +
             "4: VerifyStackTrace.invoke(VerifyStackTrace.java:190)\n" +
-            "5: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
-            "6: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
-            "7: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
-            "8: java.lang.reflect.Method.invoke(Method.java:520)\n" +
+            "5: sun.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" +
+            "6: sun.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" +
+            "7: sun.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" +
+            "8: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" +
             "9: VerifyStackTrace$1.run(VerifyStackTrace.java:220)\n" +
-            "10: java.security.AccessController.doPrivileged(Native Method)\n" +
+            "10: java.security.AccessController.doPrivileged(java.base/Native Method)\n" +
             "11: VerifyStackTrace.test(VerifyStackTrace.java:229)\n" +
             "12: VerifyStackTrace.main(VerifyStackTrace.java:185)\n";
 
@@ -134,16 +134,16 @@
             "1: VerifyStackTrace.lambda$test$1(VerifyStackTrace.java:213)\n" +
             "2: VerifyStackTrace$$Lambda$1/662441761.run(Unknown Source)\n" +
             "3: VerifyStackTrace$Handle.execute(VerifyStackTrace.java:149)\n" +
-            "4: java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(LambdaForm$DMH)\n" +
-            "5: java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(LambdaForm$MH)\n" +
+            "4: java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(java.base/LambdaForm$DMH)\n" +
+            "5: java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(java.base/LambdaForm$MH)\n" +
             "6: VerifyStackTrace$Handle.run(VerifyStackTrace.java:162)\n" +
             "7: VerifyStackTrace.invoke(VerifyStackTrace.java:192)\n" +
-            "8: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
-            "9: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
-            "10: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
-            "11: java.lang.reflect.Method.invoke(Method.java:520)\n" +
+            "8: sun.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" +
+            "9: sun.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" +
+            "10: sun.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" +
+            "11: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" +
             "12: VerifyStackTrace$1.run(VerifyStackTrace.java:222)\n" +
-            "13: java.security.AccessController.doPrivileged(Native Method)\n" +
+            "13: java.security.AccessController.doPrivileged(java.base/Native Method)\n" +
             "14: VerifyStackTrace.test(VerifyStackTrace.java:231)\n" +
             "15: VerifyStackTrace.main(VerifyStackTrace.java:188)\n";
 
@@ -202,6 +202,8 @@
             // out before comparing. We also erase the hash-like names of
             // synthetic frames introduced by lambdas & method handles
             return produced.replaceAll(":[1-9][0-9]*\\)", ":00)")
+                    .replaceAll("-internal/", "/").replaceAll("-ea/", "/")
+                    .replaceAll("java.base@[0-9]+/", "java.base/")
                     .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
                     .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
                     .replaceAll("\\$[0-9]+", "\\$??");
diff --git a/jdk/test/java/lang/instrument/ATransformerManagementTestCase.java b/jdk/test/java/lang/instrument/ATransformerManagementTestCase.java
index 9afc5e7..b48610a 100644
--- a/jdk/test/java/lang/instrument/ATransformerManagementTestCase.java
+++ b/jdk/test/java/lang/instrument/ATransformerManagementTestCase.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
@@ -25,6 +25,7 @@
 import java.io.*;
 import java.lang.instrument.*;
 
+import java.lang.reflect.Module;
 import java.security.ProtectionDomain;
 import java.util.*;
 
@@ -291,7 +292,25 @@
             // The transform testing is triggered by redefine, ignore others
             if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);
 
-            return super.transform(    loader,
+            return super.transform(     loader,
+                                        className,
+                                        classBeingRedefined,
+                                        protectionDomain,
+                                        classfileBuffer);
+        }
+
+        public byte[]
+        transform(
+            Module module,
+            String className,
+            Class<?> classBeingRedefined,
+            ProtectionDomain    protectionDomain,
+            byte[] classfileBuffer) {
+
+            // The transform testing is triggered by redefine, ignore others
+            if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);
+
+            return super.transform(     module,
                                         className,
                                         classBeingRedefined,
                                         protectionDomain,
diff --git a/jdk/test/java/lang/instrument/BootClassPath/Agent.java b/jdk/test/java/lang/instrument/BootClassPath/Agent.java
index a233d46..b072e5f 100644
--- a/jdk/test/java/lang/instrument/BootClassPath/Agent.java
+++ b/jdk/test/java/lang/instrument/BootClassPath/Agent.java
@@ -33,10 +33,7 @@
 
 public class Agent {
     public static void premain(String options, Instrumentation ins) throws Exception {
-        String bootclasspath = System.getProperty("sun.boot.class.path");
-        System.out.println("bootclasspath: " + bootclasspath);
-
-        Class c = Class.forName("AgentSupport");
+        Class<?> c = Class.forName("AgentSupport");
         ClassLoader cl = c.getClassLoader();
         if (cl != null) {
             System.err.println("AgentSupport loaded by: " + cl);
diff --git a/jdk/test/java/lang/instrument/MakeJAR2.sh b/jdk/test/java/lang/instrument/MakeJAR2.sh
index 596a0d4..ec76b82 100644
--- a/jdk/test/java/lang/instrument/MakeJAR2.sh
+++ b/jdk/test/java/lang/instrument/MakeJAR2.sh
@@ -86,7 +86,8 @@
 ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} bootreporter/*.java
 cd ..
 
-${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -XDignore.symbol.file ${AGENT}.java asmlib/*.java
+${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+    -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED ${AGENT}.java asmlib/*.java
 ${JAVAC} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -classpath .${PATHSEP}bootpath ${APP}.java
 
 echo "Manifest-Version: 1.0"    >  ${AGENT}.mf
diff --git a/jdk/test/java/lang/instrument/RedefineClassWithNativeMethodAgent.java b/jdk/test/java/lang/instrument/RedefineClassWithNativeMethodAgent.java
index ad1a725..b114671 100644
--- a/jdk/test/java/lang/instrument/RedefineClassWithNativeMethodAgent.java
+++ b/jdk/test/java/lang/instrument/RedefineClassWithNativeMethodAgent.java
@@ -21,10 +21,12 @@
  * questions.
  */
 
-import java.lang.instrument.*;
-import java.net.*;
-import java.util.*;
-import java.io.*;
+import java.io.InputStream;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Module;
+import java.util.Timer;
+import java.util.TimerTask;
 
 public class RedefineClassWithNativeMethodAgent {
     static Class clz;
@@ -33,29 +35,20 @@
     public static void premain(String agentArgs, final Instrumentation inst) throws Exception {
         String s = agentArgs.substring(0, agentArgs.indexOf(".class"));
         clz = Class.forName(s.replace('/', '.'));
-        ClassLoader loader =
-            RedefineClassWithNativeMethodAgent.class.getClassLoader();
-        URL classURL = loader.getResource(agentArgs);
-        if (classURL == null) {
+        InputStream in;
+        Module m = clz.getModule();
+        if (m != null) {
+            in = m.getResourceAsStream(agentArgs);
+        } else {
+            ClassLoader loader =
+                RedefineClassWithNativeMethodAgent.class.getClassLoader();
+            in = loader.getResourceAsStream(agentArgs);
+        }
+        if (in == null) {
             throw new Exception("Cannot find class: " + agentArgs);
         }
+        byte[] buffer = in.readAllBytes();
 
-        int         redefineLength;
-        InputStream redefineStream;
-
-        System.out.println("Reading test class from " + classURL);
-        if (classURL.getProtocol().equals("file")) {
-            File f = new File(classURL.getFile());
-            redefineStream = new FileInputStream(f);
-            redefineLength = (int) f.length();
-        } else {
-            URLConnection conn = classURL.openConnection();
-            redefineStream = conn.getInputStream();
-            redefineLength = conn.getContentLength();
-        }
-
-        final byte[] buffer = new byte[redefineLength];
-        new BufferedInputStream(redefineStream).read(buffer);
         new Timer(true).schedule(new TimerTask() {
             public void run() {
                 try {
diff --git a/jdk/test/java/lang/instrument/RetransformAgent.java b/jdk/test/java/lang/instrument/RetransformAgent.java
index 920fffb..19cd34e 100644
--- a/jdk/test/java/lang/instrument/RetransformAgent.java
+++ b/jdk/test/java/lang/instrument/RetransformAgent.java
@@ -34,6 +34,7 @@
  */
 
 import java.lang.instrument.*;
+import java.lang.reflect.Module;
 import java.security.ProtectionDomain;
 import java.io.*;
 import asmlib.*;
@@ -67,12 +68,13 @@
             this.nname = nname;
         }
 
-        public byte[] transform(ClassLoader loader,
+        public byte[] transform(Module module,
                                 String className,
                                 Class<?> classBeingRedefined,
                                 ProtectionDomain    protectionDomain,
                                 byte[] classfileBuffer) {
             boolean redef = classBeingRedefined != null;
+
             // System.err.println("hook " + trname + ": " + className +
             //                    (redef? " REDEF" : " LOAD"));
             if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) {
diff --git a/jdk/test/java/lang/instrument/SimpleIdentityTransformer.java b/jdk/test/java/lang/instrument/SimpleIdentityTransformer.java
index cf4b987..d8fc0c0 100644
--- a/jdk/test/java/lang/instrument/SimpleIdentityTransformer.java
+++ b/jdk/test/java/lang/instrument/SimpleIdentityTransformer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, 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,6 +24,7 @@
 import java.lang.instrument.Instrumentation;
 import java.lang.instrument.ClassFileTransformer;
 
+import java.lang.reflect.Module;
 import java.security.*;
 
 /*
@@ -59,4 +60,16 @@
         return newBuffer;
     }
 
+    public byte[]
+    transform(
+        Module module,
+        String className,
+        Class<?> classBeingRedefined,
+        ProtectionDomain    protectionDomain,
+        byte[] classfileBuffer) {
+        byte[] newBuffer = new byte[classfileBuffer.length];
+        System.arraycopy(classfileBuffer, 0, newBuffer, 0, classfileBuffer.length);
+
+        return newBuffer;
+    }
 }
diff --git a/jdk/test/java/lang/invoke/AccessControlTest.java b/jdk/test/java/lang/invoke/AccessControlTest.java
index 5e6fc14..57cec50 100644
--- a/jdk/test/java/lang/invoke/AccessControlTest.java
+++ b/jdk/test/java/lang/invoke/AccessControlTest.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
@@ -31,6 +31,7 @@
 
 import java.lang.invoke.*;
 import java.lang.reflect.*;
+import java.lang.reflect.Modifier;
 import java.util.*;
 import org.testng.*;
 import org.testng.annotations.*;
@@ -117,11 +118,13 @@
                 suffix = "/noaccess";
             else if (lookupModes == PUBLIC)
                 suffix = "/public";
-            else if (lookupModes == (PUBLIC|PACKAGE))
+            else if (lookupModes == (PUBLIC|MODULE))
+                suffix = "/module";
+            else if (lookupModes == (PUBLIC|MODULE|PACKAGE))
                 suffix = "/package";
-            else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE))
+            else if (lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE))
                 suffix = "/private";
-            else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE|PROTECTED))
+            else if (lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED))
                 suffix = "";
             else
                 suffix = "/#"+Integer.toHexString(lookupModes);
@@ -147,16 +150,26 @@
          * <li>[A6] If the new lookup class is not accessible to the old lookup class,
          * using the original access modes,
          * then no members, not even public members, will be accessible.
-         * [A7] (In all other cases, public members will continue to be accessible.)
+         * <li>[A7] If the new lookup class for this {@code Lookup} is in the unnamed module,
+         * and the new lookup class is in a named module {@code M}, then no members in
+         * {@code M}'s non-exported packages will be accessible.
+         * <li>[A8] If the lookup for this {@code Lookup} is in a named module, and the
+         * new lookup class is in a different module, then no members, not even
+         * public members in {@code M}'s exported packages, will be accessible.
+         * [A8] (In all other cases, public members will continue to be accessible.)
          * </ul>
          * Other than the above cases, the new lookup will have the same
-         * access capabilities as the original. [A8]
+         * access capabilities as the original. [A10]
          * <hr>
          */
         public LookupCase in(Class<?> c2) {
             Class<?> c1 = lookupClass();
             int m1 = lookupModes();
             int changed = 0;
+            // for the purposes of access control then treat classes in different unnamed
+            // modules as being in the same module.
+            boolean sameModule = (c1.getModule() == c2.getModule()) ||
+                                 (!c1.getModule().isNamed() && !c2.getModule().isNamed());
             boolean samePackage = (c1.getClassLoader() == c2.getClassLoader() &&
                                    packagePrefix(c1).equals(packagePrefix(c2)));
             boolean sameTopLevel = (topLevelClass(c1) == topLevelClass(c2));
@@ -166,12 +179,20 @@
             boolean accessible = sameClass;  // [A6]
             if ((m1 & PACKAGE) != 0)  accessible |= samePackage;
             if ((m1 & PUBLIC ) != 0)  accessible |= (c2.getModifiers() & PUBLIC) != 0;
+            if (!sameModule) {
+                if (c1.getModule().isNamed()) {
+                    accessible = false;  // [A8]
+                } else {
+                    // Different module; loose MODULE and lower access.
+                    changed |= (MODULE|PACKAGE|PRIVATE|PROTECTED);  // [A7]
+                }
+            }
             if (!accessible) {
                 // Different package and no access to c2; lose all access.
-                changed |= (PUBLIC|PACKAGE|PRIVATE|PROTECTED);  // [A6]
+                changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED);  // [A6]
             }
             if (!samePackage) {
-                // Different package; lose PACKAGE and lower access.
+                // Different package; loose PACKAGE and lower access.
                 changed |= (PACKAGE|PRIVATE|PROTECTED);  // [A4]
             }
             if (!sameTopLevel) {
@@ -181,9 +202,9 @@
             if (!sameClass) {
                 changed |= (PROTECTED);     // [A3]
             } else {
-                assert(changed == 0);       // [A8] (no deprivation if same class)
+                assert(changed == 0);       // [A10] (no deprivation if same class)
             }
-            if (accessible)  assert((changed & PUBLIC) == 0);  // [A7]
+            if (accessible)  assert((changed & PUBLIC) == 0);  // [A9]
             int m2 = m1 & ~changed;
             LookupCase l2 = new LookupCase(c2, m2);
             assert(l2.lookupClass() == c2); // [A1]
@@ -206,6 +227,16 @@
         public boolean willAccess(Method m) {
             Class<?> c1 = lookupClass();
             Class<?> c2 = m.getDeclaringClass();
+
+            // if the lookup class is in a loose module with PUBLIC access then
+            // public members of public types in all unnamed modules can be accessed
+            if (isLooseModule(c1.getModule())
+                && (lookupModes & PUBLIC) != 0
+                && (!c2.getModule().isNamed())
+                && Modifier.isPublic(c2.getModifiers())
+                && Modifier.isPublic(m.getModifiers()))
+                return true;
+
             LookupCase lc = this.in(c2);
             int m1 = lc.lookupModes();
             int m2 = fixMods(m.getModifiers());
@@ -227,9 +258,25 @@
         /** Predict the success or failure of accessing this class. */
         public boolean willAccessClass(Class<?> c2, boolean load) {
             Class<?> c1 = lookupClass();
-            if (load && c1.getClassLoader() == null) {
+            if (load && c2.getClassLoader() != null) {
+                if (c1.getClassLoader() == null) {
+                    // not visible
                 return false;
             }
+                if (c1 == publicLookup().lookupClass()) {
+                    // not visible as lookup class is defined by child of the boot loader
+                    return false;
+                }
+            }
+
+            // if the lookup class is in a loose module with PUBLIC access then
+            // public types in all unnamed modules can be accessed
+            if (isLooseModule(c1.getModule())
+                && (lookupModes & PUBLIC) != 0
+                && (!c2.getModule().isNamed())
+                && Modifier.isPublic(c2.getModifiers()))
+                return true;
+
             LookupCase lc = this.in(c2);
             int m1 = lc.lookupModes();
             boolean r = false;
@@ -248,6 +295,11 @@
             }
             return r;
         }
+
+        private boolean isLooseModule(Module m) {
+            ClassLoader cl = new ClassLoader() { };
+            return m.canRead(cl.getUnnamedModule());
+        }
     }
 
     private static Class<?> topLevelClass(Class<?> cls) {
@@ -303,7 +355,7 @@
             LookupCase expect = l1.in(c2);
             if (!expect.equals(l2))
                 System.out.println("*** expect "+l1+" => "+expect+" but got "+l2);
-            assertEquals(expect, l2);
+            assertEquals(l2, expect);
         }
     }
 
@@ -420,6 +472,7 @@
     }
 
     static Method targetMethod(Class<?> targetClass, int targetAccess, MethodType methodType) {
+        assert targetAccess != MODULE;
         String methodName = accessName(targetAccess)+placeName(targetClass);
         if (verbosity >= 2)
             System.out.println(targetClass.getSimpleName()+"."+methodName+methodType);
@@ -453,6 +506,7 @@
         assert(false);
         return "?";
     }
+    // MODULE not a test case at this time
     private static final int[] ACCESS_CASES = {
         PUBLIC, PACKAGE, PRIVATE, PROTECTED
     };
diff --git a/jdk/test/java/lang/invoke/CustomizedLambdaFormTest.java b/jdk/test/java/lang/invoke/CustomizedLambdaFormTest.java
index 3e24673..5b439fa 100644
--- a/jdk/test/java/lang/invoke/CustomizedLambdaFormTest.java
+++ b/jdk/test/java/lang/invoke/CustomizedLambdaFormTest.java
@@ -21,21 +21,25 @@
  * questions.
  */
 
-package java.lang.invoke;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodType;
 
 /* @test
  * @summary Assertion in LambdaFormEditor.bindArgumentType is too strong
  *
- * @run main/bootclasspath -esa java.lang.invoke.CustomizedLambdaFormTest
+ * @compile/module=java.base java/lang/invoke/MethodHandleHelper.java
+ * @run main/othervm -esa CustomizedLambdaFormTest
  */
+
 public class CustomizedLambdaFormTest {
 
     static void testExtendCustomizedBMH() throws Exception {
         // Construct BMH
-        MethodHandle mh = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual(String.class, "concat",
+        MethodHandle mh = MethodHandleHelper.IMPL_LOOKUP.findVirtual(String.class, "concat",
                 MethodType.methodType(String.class, String.class))
                 .bindTo("a");
-        mh.customize();
+        MethodHandleHelper.customize(mh);
         mh.bindTo("b"); // Try to extend customized BMH
     }
 
diff --git a/jdk/test/java/lang/invoke/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java
index 7b578a4..3370767 100644
--- a/jdk/test/java/lang/invoke/MethodHandlesTest.java
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java
@@ -386,7 +386,7 @@
     static final Lookup PACKAGE = PackageSibling.lookup();
     // This lookup is good for public members and protected members of PubExample
     static final Lookup SUBCLASS = RemoteExample.lookup();
-    // This lookup is good only for public members.
+    // This lookup is good only for public members in exported packages.
     static final Lookup PUBLIC  = MethodHandles.publicLookup();
 
     // Subject methods...
@@ -634,10 +634,15 @@
     public void testFindVirtualClone0() throws Throwable {
         // test some ad hoc system methods
         testFindVirtual(false, PUBLIC, Object.class, Object.class, "clone");
+
+        // ##### FIXME - disable tests for clone until we figure out how they should work with modules
+
+        /*
         testFindVirtual(true, PUBLIC, Object[].class, Object.class, "clone");
         testFindVirtual(true, PUBLIC, int[].class, Object.class, "clone");
         for (Class<?> cls : new Class<?>[]{ boolean[].class, long[].class, float[].class, char[].class })
             testFindVirtual(true, PUBLIC, cls, Object.class, "clone");
+         */
     }
 
     void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
diff --git a/jdk/test/java/lang/invoke/VarargsArrayTest.java b/jdk/test/java/lang/invoke/VarargsArrayTest.java
index a247fa5..98e0698 100644
--- a/jdk/test/java/lang/invoke/VarargsArrayTest.java
+++ b/jdk/test/java/lang/invoke/VarargsArrayTest.java
@@ -21,8 +21,10 @@
  * questions.
  */
 
-package java.lang.invoke;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodType;
 import sun.invoke.util.Wrapper;
 import java.util.Arrays;
 import java.util.Collections;
@@ -31,14 +33,16 @@
 /* @test
  * @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int),
  *          MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int)
+ * @modules java.base/sun.invoke.util
  * @library /lib/testlibrary /lib/testlibrary/jsr292
- * @run main/bootclasspath java.lang.invoke.VarargsArrayTest
+ * @compile/module=java.base java/lang/invoke/MethodHandleHelper.java
+ * @run main/bootclasspath VarargsArrayTest
  * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
- *                         java.lang.invoke.VarargsArrayTest
+ *                         VarargsArrayTest
  */
 
 /* This might take a while and burn lots of metadata:
- * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true java.lang.invoke.VarargsArrayTest
+ * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true VarargsArrayTest
  */
 public class VarargsArrayTest {
     private static final Class<?> CLASS = VarargsArrayTest.class;
@@ -60,7 +64,7 @@
         final int MIN = START_ARITY;
         final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
         for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
-            MethodHandle target = MethodHandleImpl.varargsArray(nargs);
+            MethodHandle target = MethodHandleHelper.varargsArray(nargs);
             Object[] args = new Object[nargs];
             for (int i = 0; i < nargs; i++)
                 args[i] = "#"+i;
@@ -110,7 +114,7 @@
         if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
         for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
             Object[] args = makeTestArray(elemType, nargs);
-            MethodHandle varargsArray = MethodHandleImpl.varargsArray(arrayType, nargs);
+            MethodHandle varargsArray = MethodHandleHelper.varargsArray(arrayType, nargs);
             MethodType vaType = varargsArray.type();
             assertEquals(arrayType, vaType.returnType());
             if (nargs != 0) {
diff --git a/jdk/test/java/lang/invoke/java.base/java/lang/invoke/MethodHandleHelper.java b/jdk/test/java/lang/invoke/java.base/java/lang/invoke/MethodHandleHelper.java
new file mode 100644
index 0000000..d85d6d1
--- /dev/null
+++ b/jdk/test/java/lang/invoke/java.base/java/lang/invoke/MethodHandleHelper.java
@@ -0,0 +1,52 @@
+/*
+ * 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 java.lang.invoke;
+
+import java.lang.invoke.MethodHandles.Lookup;
+
+/**
+ * Helper class to inject into java.lang.invoke that provides access to
+ * package-private methods in this package.
+ */
+
+public class MethodHandleHelper {
+
+    private MethodHandleHelper() { }
+
+    public static final Lookup IMPL_LOOKUP = Lookup.IMPL_LOOKUP;
+
+    public static void customize(MethodHandle mh) {
+        mh.customize();
+    }
+
+    public static MethodHandle varargsArray(int nargs) {
+        return MethodHandleImpl.varargsArray(nargs);
+    }
+
+    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+        return MethodHandleImpl.varargsArray(arrayType, nargs);
+    }
+
+}
+
diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java
index a5917e5..83024e5 100644
--- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java
@@ -54,8 +54,6 @@
         scratch.clear();
         scratch.add("public class Bar {");
         scratch.add("public static void main(String... args) {");
-        scratch.add("System.out.println(\"sun.boot.class.path\" + \"=\" +");
-        scratch.add("    System.getProperty(\"sun.boot.class.path\", \"\"));");
         scratch.add("System.setSecurityManager(new SecurityManager());");
         scratch.add("DoPriv.main();");
         scratch.add("}");
diff --git a/jdk/test/java/lang/invoke/modules/ModuleAccessControlTest.java b/jdk/test/java/lang/invoke/modules/ModuleAccessControlTest.java
new file mode 100644
index 0000000..d76513e
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/ModuleAccessControlTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+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 jdk.compiler
+ * @build CompilerUtils jdk.testlibrary.*
+ * @run testng ModuleAccessControlTest
+ * @summary Driver for testing module access checking by MethodHandles.Lookup
+ */
+
+public class ModuleAccessControlTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("m1", "m2");
+
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils
+                .compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+    }
+
+    /**
+     * Launch the test
+     */
+    @Test
+    public void runTest() throws Exception {
+        int exitValue = executeTestJava("-mp", MODS_DIR.toString(),
+                                        "-m", "m1/p1.Main")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/modules/src/m1/module-info.java
new file mode 100644
index 0000000..175c772
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module m1 {
+    requires m2;
+    exports p1;
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m1/p1/Main.java b/jdk/test/java/lang/invoke/modules/src/m1/p1/Main.java
new file mode 100644
index 0000000..3fd1a0e
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m1/p1/Main.java
@@ -0,0 +1,225 @@
+/*
+ * 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 p1;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+/**
+ * Basic test case for module access check, supplements AccessControlTest.
+ *
+ * The tests consists of two modules:
+ *
+ * module m1 { requires m2; exports p1; }
+ * module m2 { exports q1; }
+ *
+ * Both modules read java.base (as every module reads java.base)
+ *
+ * module m1 has public types in packages p1 and p2, p2 is not exported.
+ * module m2 has public types in packages q1 and q2, q2 is not exported.
+ */
+
+public class Main {
+
+    static final int MODULE = Lookup.MODULE;
+
+    // Use Class.forName to get classes for test because some
+    // are not accessible at compile-time
+
+    static final Class<?> p1_Type1;        // m1, exported
+    static final Class<?> p2_Type2;        // m1, not exported
+    static final Class<?> q1_Type1;        // m2, exported, m1 reads m2
+    static final Class<?> q2_Type2;        // m2, not exported, m1 reads m2
+    static final Class<?> x500NameClass;   // java.base, not exported
+
+    static {
+        try {
+            p1_Type1 = Class.forName("p1.Type1");
+            p2_Type2 = Class.forName("p2.Type2");
+            q1_Type1 = Class.forName("q1.Type1");
+            q2_Type2 = Class.forName("q2.Type2");
+            x500NameClass = Class.forName("sun.security.x509.X500Name");
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Lookup lookup, lookup2;
+
+        /**
+         * MethodHandles.lookup()
+         * has module access [A0]
+         * can access all public types in m1 [A1]
+         * can access public types in packages exported by modules that m1 reads [A2]
+         * cannot access public types in non-exported modules of modules that m1 reads [A3]
+         */
+        lookup = MethodHandles.lookup();
+        assertTrue((lookup.lookupModes() & MODULE) == MODULE); // [A0]
+        findConstructor(lookup, p1_Type1, void.class); // [A1]
+        findConstructor(lookup, p2_Type2, void.class); // [A1]
+        findConstructor(lookup, q1_Type1, void.class); // [A2]
+        findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A3]
+        findConstructor(lookup, Object.class, void.class); // [A2]
+        findConstructorExpectingIAE(lookup, x500NameClass, void.class, String.class); // [A3]
+
+        /**
+         * Teleport from MethodHandles.lookup() to lookup class in the same module
+         * module access is retained [A0]
+         * can access all public types in m1 [A1]
+         * can access public types in packages exported by modules that m1 reads [A2]
+         * cannot access public types in non-exported modules of modules that m1 reads [A3]
+         */
+        lookup2 = lookup.in(p2_Type2);
+        assertTrue((lookup2.lookupModes() & MODULE) == MODULE); // [A0]
+        findConstructor(lookup2, p1_Type1, void.class); // [A1]
+        findConstructor(lookup2, p2_Type2, void.class); // [A1]
+        findConstructor(lookup2, q1_Type1, void.class); // [A2]
+        findConstructorExpectingIAE(lookup2, q2_Type2, void.class); // [A3]
+        findConstructor(lookup2, Object.class, void.class); // [A2]
+        findConstructorExpectingIAE(lookup2, x500NameClass, void.class, String.class); // [A3]
+
+        /**
+         * Teleport from MethodHandles.lookup() to lookup class in another named module
+         * has no access [A0]
+         */
+        lookup2 = lookup.in(Object.class);
+        assertTrue(lookup2.lookupModes() == 0); // [A0]
+        findConstructorExpectingIAE(lookup2, Object.class, void.class);  // [A0]
+
+        /**
+         * Teleport from MethodHandles.lookup() to lookup class in an unnamed module
+         * has no access [A0]
+         */
+        Class<?> c = MethodHandles.publicLookup().lookupClass();
+        assertTrue(!c.getModule().isNamed());
+        lookup2 = lookup.in(c);
+        assertTrue(lookup2.lookupModes() == 0); // [A0]
+        findConstructorExpectingIAE(lookup2, Object.class, void.class);
+
+        /**
+         * MethodHandles.publicLookup()
+         * has no module access [A0]
+         * can access public types in exported packages [A1]
+         * cannot access public types in non-exported packages [A2]
+         */
+        lookup = MethodHandles.publicLookup();
+        assertTrue((lookup.lookupModes() & MODULE) == 0); // [A0]
+        findConstructor(lookup, p1_Type1, void.class); // [A1]
+        findConstructorExpectingIAE(lookup, p2_Type2, void.class); // [A1]
+        findConstructor(lookup, q1_Type1, void.class); // [A1]
+        findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A2]
+        findConstructor(lookup, Object.class, void.class); // [A1]
+        findConstructorExpectingIAE(lookup, x500NameClass, void.class); // [A2]
+
+        /**
+         * Teleport from MethodHandles.publicLookup() to lookup class in java.base
+         * has no module access [A0]
+         * can access public types in packages exported by java.base [A1]
+         * cannot access public types in non-exported packages [A2]
+         * no access to types in other named modules [A3]
+         */
+        lookup2 = lookup.in(Object.class);
+        assertTrue((lookup2.lookupModes() & MODULE) == 0); // [A0]
+        findConstructor(lookup2, String.class, void.class); // [A1]
+        findConstructorExpectingIAE(lookup2, x500NameClass, void.class, String.class); // [A2]
+        findConstructorExpectingIAE(lookup2, p1_Type1, void.class); // [A3]
+        findConstructorExpectingIAE(lookup2, q1_Type1, void.class); // [A3]
+
+        /**
+         * Teleport from MethodHandles.publicLookup() to lookup class in m1
+         * has no module access [A0]
+         * can access public types in packages exported by m1, m2 and java.base [A1]
+         * cannot access public types is non-exported packages [A2]
+         */
+        lookup2 = lookup.in(p1_Type1);
+        assertTrue((lookup2.lookupModes() & MODULE) == 0); // [A0]
+        findConstructor(lookup2, p1_Type1, void.class);  // [A1]
+        findConstructor(lookup2, q1_Type1, void.class);  // [A1]
+        findConstructor(lookup2, Object.class, void.class);  // [A1]
+        findConstructorExpectingIAE(lookup, p2_Type2, void.class); // [A2]
+        findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A2]
+        findConstructorExpectingIAE(lookup2, x500NameClass, void.class, String.class); // [A2]
+
+        /**
+         * Teleport from MethodHandles.publicLookup() to lookup class in m2
+         * has no module access [A0]
+         * can access public types in packages exported by m2 and java.base [A1]
+         * cannot access public types is non-exported packages or modules that m2 does
+         *   not read [A2]
+         */
+        lookup2 = lookup.in(q1_Type1);
+        assertTrue((lookup2.lookupModes() & MODULE) == 0); // [A0]
+        findConstructor(lookup2, q1_Type1, void.class); // [A1]
+        findConstructor(lookup2, Object.class, void.class); // [A1]
+        findConstructorExpectingIAE(lookup2, p1_Type1, void.class); // [A2]
+        findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A2]
+        findConstructorExpectingIAE(lookup2, x500NameClass, void.class, String.class);  // [A2]
+
+        /**
+         * Teleport from MethodHandles.publicLookup() to lookup class that is not
+         * in an exported package, should get no access [A0]
+         */
+        lookup2 = lookup.in(p2_Type2);
+        assertTrue(lookup2.lookupModes()  == 0); // [A0]
+        findConstructorExpectingIAE(lookup, q2_Type2, void.class); // [A0]
+    }
+
+    /**
+     * Invokes Lookup findConstructor with a method type constructored from the
+     * given return and parameter types, expecting IllegalAccessException to be
+     * thrown.
+     */
+    static MethodHandle findConstructorExpectingIAE(Lookup lookup,
+                                                    Class<?> clazz,
+                                                    Class<?> rtype,
+                                                    Class<?>... ptypes) throws Exception {
+        try {
+            findConstructor(lookup, clazz, rtype, ptypes);
+            throw new RuntimeException("IllegalAccessError expected");
+        } catch (IllegalAccessException expected) {
+            return null;
+        }
+    }
+
+    /**
+     * Invokes Lookup findConstructor with a method type constructored from the
+     * given return and parameter types.
+     */
+    static MethodHandle findConstructor(Lookup lookup,
+                                        Class<?> clazz,
+                                        Class<?> rtype,
+                                        Class<?>... ptypes) throws Exception {
+        MethodType mt = MethodType.methodType(rtype, ptypes);
+        return lookup.findConstructor(clazz, mt);
+    }
+
+    static void assertTrue(boolean condition) {
+        if (!condition)
+            throw new RuntimeException();
+    }
+
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m1/p1/Type1.java b/jdk/test/java/lang/invoke/modules/src/m1/p1/Type1.java
new file mode 100644
index 0000000..341fdcd
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m1/p1/Type1.java
@@ -0,0 +1,27 @@
+/*
+ * 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 p1;
+
+public class Type1 {
+    public Type1() { }
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m1/p2/Type2.java b/jdk/test/java/lang/invoke/modules/src/m1/p2/Type2.java
new file mode 100644
index 0000000..bf62a78
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m1/p2/Type2.java
@@ -0,0 +1,27 @@
+/*
+ * 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 p2;
+
+public class Type2 {
+    public Type2() { }
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m2/module-info.java b/jdk/test/java/lang/invoke/modules/src/m2/module-info.java
new file mode 100644
index 0000000..f26ae1c
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m2/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module m2 {
+    exports q1;
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m2/q1/Type1.java b/jdk/test/java/lang/invoke/modules/src/m2/q1/Type1.java
new file mode 100644
index 0000000..b845ee3
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m2/q1/Type1.java
@@ -0,0 +1,27 @@
+/*
+ * 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 q1;
+
+public class Type1 {
+    public Type1() { }
+}
diff --git a/jdk/test/java/lang/invoke/modules/src/m2/q2/Type2.java b/jdk/test/java/lang/invoke/modules/src/m2/q2/Type2.java
new file mode 100644
index 0000000..ecc30c4
--- /dev/null
+++ b/jdk/test/java/lang/invoke/modules/src/m2/q2/Type2.java
@@ -0,0 +1,27 @@
+/*
+ * 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 q2;
+
+public class Type2 {
+    public Type2() { }
+}
diff --git a/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java b/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java
index 9b026b9..80ca1c4 100644
--- a/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java
+++ b/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java
@@ -39,6 +39,7 @@
 import java.lang.management.LockInfo;
 import java.lang.management.MonitorInfo;
 import java.lang.management.ThreadInfo;
+import java.util.Objects;
 
 public class ThreadInfoCompositeData {
     private static StackTraceElement[] ste = new StackTraceElement[1];
@@ -173,6 +174,14 @@
             throw new RuntimeException("Class name = " +
                 s2.getClassName() + " expected = " + s1.getClassName());
         }
+        if (!Objects.equals(s1.getModuleName(), s2.getModuleName())) {
+            throw new RuntimeException("Module name = " +
+                s2.getModuleName() + " expected = " + s1.getModuleName());
+        }
+        if (!Objects.equals(s1.getModuleVersion(), s2.getModuleVersion())) {
+            throw new RuntimeException("Module version = " +
+                s2.getModuleVersion() + " expected = " + s1.getModuleVersion());
+        }
         if (!s1.getMethodName().equals(s2.getMethodName())) {
             throw new RuntimeException("Method name = " +
                 s2.getMethodName() + " expected = " + s1.getMethodName());
@@ -329,6 +338,8 @@
 
     private static final String[] steItemNames = {
         "className",
+        "moduleName",
+        "moduleVersion",
         "methodName",
         "fileName",
         "lineNumber",
@@ -352,6 +363,8 @@
 
             final Object[] steValue = {
                 ste[0].getClassName(),
+                ste[0].getModuleName(),
+                ste[0].getModuleVersion(),
                 ste[0].getMethodName(),
                 ste[0].getFileName(),
                 new Integer(ste[0].getLineNumber()),
diff --git a/jdk/test/java/lang/management/MemoryMXBean/PendingAllGC.sh b/jdk/test/java/lang/management/MemoryMXBean/PendingAllGC.sh
index 2cc76ee..c189894 100644
--- a/jdk/test/java/lang/management/MemoryMXBean/PendingAllGC.sh
+++ b/jdk/test/java/lang/management/MemoryMXBean/PendingAllGC.sh
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,8 @@
 # @summary 
 # @author  Mandy Chung
 # @requires vm.gc=="null"
-# @modules java.base/sun.misc
+# @modules java.base/jdk.internal.misc
+#          java.management
 # @run compile Pending.java
 # @run shell PendingAllGC.sh
 #
diff --git a/jdk/test/java/lang/module/AutomaticModulesTest.java b/jdk/test/java/lang/module/AutomaticModulesTest.java
new file mode 100644
index 0000000..d400ffb
--- /dev/null
+++ b/jdk/test/java/lang/module/AutomaticModulesTest.java
@@ -0,0 +1,572 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @build AutomaticModulesTest ModuleUtils
+ * @run testng AutomaticModulesTest
+ * @summary Basic tests for automatic modules
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class AutomaticModulesTest {
+
+    private static final Path USER_DIR
+         = Paths.get(System.getProperty("user.dir"));
+
+
+    @DataProvider(name = "names")
+    public Object[][] createNames() {
+
+        return new Object[][] {
+
+            // JAR file name                module-name[/version]
+
+            { "foo.jar",                    "foo" },
+
+            { "foo-1.jar",                  "foo/1" },
+            { "foo-1.2.jar",                "foo/1.2" },
+            { "foo-1.2.3.jar",              "foo/1.2.3" },
+            { "foo-1.2.3.4.jar",            "foo/1.2.3.4" },
+
+            { "foo-10.jar",                 "foo/10" },
+            { "foo-10.20.jar",              "foo/10.20" },
+            { "foo-10.20.30.jar",           "foo/10.20.30" },
+            { "foo-10.20.30.40.jar",        "foo/10.20.30.40" },
+
+            { "foo-bar.jar",                "foo.bar" },
+            { "foo-bar-1.jar",              "foo.bar/1" },
+            { "foo-bar-1.2.jar",            "foo.bar/1.2"},
+            { "foo-bar-10.jar",             "foo.bar/10" },
+            { "foo-bar-10.20.jar",          "foo.bar/10.20" },
+
+            { "foo-1.2-SNAPSHOT.jar",       "foo/1.2-SNAPSHOT" },
+            { "foo-bar-1.2-SNAPSHOT.jar",   "foo.bar/1.2-SNAPSHOT" },
+
+            { "foo--bar-1.0.jar",           "foo.bar/1.0" },
+            { "-foo-bar-1.0.jar",           "foo.bar/1.0" },
+            { "foo-bar--1.0.jar",           "foo.bar/1.0" },
+
+        };
+    }
+
+    /**
+     * Test mapping of JAR file names to module names
+     */
+    @Test(dataProvider = "names")
+    public void testNames(String fn, String mid) throws IOException {
+
+        String[] s = mid.split("/");
+        String mn = s[0];
+        String vs = (s.length == 2) ? s[1] : null;
+
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path jf = dir.resolve(fn);
+
+        // create empty JAR file
+        createJarFile(jf);
+
+        // create a ModuleFinder to find modules in the directory
+        ModuleFinder finder = ModuleFinder.of(dir);
+
+        // a module with the expected name should be found
+        Optional<ModuleReference> mref = finder.find(mn);
+        assertTrue(mref.isPresent(), mn + " not found");
+
+        ModuleDescriptor descriptor = mref.get().descriptor();
+        assertEquals(descriptor.name(), mn);
+        if (vs == null) {
+            assertFalse(descriptor.version().isPresent());
+        } else {
+            assertEquals(descriptor.version().get().toString(), vs);
+        }
+
+    }
+
+
+    /**
+     * Test all packages are exported
+     */
+    public void testExports() throws IOException {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m1.jar"),
+                      "p/C1.class", "p/C2.class", "q/C1.class");
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = resolve(parent, finder, "m1");
+
+        ModuleDescriptor m1 = findDescriptor(cf, "m1");
+
+        Set<String> exports
+            = m1.exports().stream().map(Exports::source).collect(Collectors.toSet());
+
+        assertTrue(exports.size() == 2);
+        assertTrue(exports.contains("p"));
+        assertTrue(exports.contains("q"));
+        assertTrue(m1.conceals().isEmpty());
+    }
+
+
+    /**
+     * Test that a JAR file with a Main-Class attribute results
+     * in a module with a main class.
+     */
+    public void testMainClass() throws IOException {
+        String mainClass = "p.Main";
+
+        Manifest man = new Manifest();
+        Attributes attrs = man.getMainAttributes();
+        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+        attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
+
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m1.jar"), man);
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = resolve(parent, finder, "m1");
+
+        ModuleDescriptor m1 = findDescriptor(cf, "m1");
+
+        assertTrue(m1.mainClass().isPresent());
+        assertEquals(m1.mainClass().get(), mainClass);
+    }
+
+
+    /**
+     * Basic test of a configuration created with automatic modules.
+     *   m1 requires m2*
+     *   m1 requires m3*
+     *   m2*
+     *   m3*
+     */
+    public void testConfiguration1() throws Exception {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("m3")
+                .requires("java.base")
+                .build();
+
+        // m2 and m3 are automatic modules
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m2.jar"), "p/T.class");
+        createJarFile(dir.resolve("m3.jar"), "q/T.class");
+
+        // module finder locates m1 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");
+
+        assertTrue(cf.modules().size() == 3);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.findModule("m3").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();
+
+        // m2 && m3 only require java.base
+        assertTrue(m2.reference().descriptor().requires().size() == 1);
+        assertTrue(m3.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(m2.reads().contains(m1));
+        assertTrue(m2.reads().contains(m3));
+        testReadAllBootModules(cf, "m2");  // m2 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
+
+    }
+
+    /**
+     * Basic test of a configuration created with automatic modules
+     *   m1 requires m2
+     *   m2 requires m3*
+     *   m3*
+     *   m4*
+     */
+    public void testInConfiguration2() throws IOException {
+
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("java.base")
+                .build();
+
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .requires("m3")
+                .requires("java.base")
+                .build();
+
+        // m3 and m4 are automatic modules
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m3.jar"), "p/T.class");
+        createJarFile(dir.resolve("m4.jar"), "q/T.class");
+
+        // module finder locates m1 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");
+
+        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());
+
+        // m3 && m4 should only require java.base
+        assertTrue(findDescriptor(cf, "m3").requires().size() == 1);
+        assertTrue(findDescriptor(cf, "m4").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();
+
+        assertTrue(m1.reads().size() == 2);
+        assertTrue(m1.reads().contains(m2));
+        assertTrue(m1.reads().contains(base));
+
+        assertTrue(m2.reads().size() == 3);
+        assertTrue(m2.reads().contains(m3));
+        assertTrue(m2.reads().contains(m4));
+        assertTrue(m2.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(m4.reads().contains(m1));
+        assertTrue(m4.reads().contains(m2));
+        assertTrue(m4.reads().contains(m3));
+        testReadAllBootModules(cf, "m4");    // m4 reads all modules in boot layer
+
+    }
+
+
+    /**
+     * Basic test of a configuration created with automatic modules
+     *   m1 requires m2
+     *   m2 requires public m3*
+     *   m3*
+     *   m4*
+     */
+    public void testInConfiguration3() throws IOException {
+
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("java.base")
+                .build();
+
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m3")
+                .requires("java.base")
+                .build();
+
+        // m3 and m4 are automatic modules
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m3.jar"), "p/T.class");
+        createJarFile(dir.resolve("m4.jar"), "q/T.class");
+
+        // module finder locates m1 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");
+
+        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());
+
+        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();
+
+        // m3 && m4 should only require java.base
+        assertTrue(findDescriptor(cf, "m3").requires().size() == 1);
+        assertTrue(findDescriptor(cf, "m4").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(m2.reads().size() == 3);
+        assertTrue(m2.reads().contains(m3));
+        assertTrue(m2.reads().contains(m4));
+        assertTrue(m2.reads().contains(base));
+
+        assertTrue(reads(cf, "m2", "m3"));
+        assertTrue(reads(cf, "m2", "m4"));
+        assertTrue(reads(cf, "m2", "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(m4.reads().contains(m1));
+        assertTrue(m4.reads().contains(m2));
+        assertTrue(m4.reads().contains(m3));
+        testReadAllBootModules(cf, "m4");    // m4 reads all modules in boot layer
+
+    }
+
+
+    /**
+     * Basic test of Layer containing automatic modules
+     */
+    public void testInLayer() throws IOException {
+        ModuleDescriptor descriptor
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("m3")
+                .build();
+
+        // m2 and m3 are simple JAR files
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createJarFile(dir.resolve("m2.jar"), "p/T.class");
+        createJarFile(dir.resolve("m3.jar"), "q/T2.class");
+
+        // module finder locates m1 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");
+        assertTrue(cf.modules().size() == 3);
+
+        // each module gets its own loader
+        Layer layer = Layer.boot().defineModules(cf, mn -> new ClassLoader() { });
+
+        // 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 m3 = layer.findModule("m3").get();
+        assertTrue(m3.isNamed());
+        assertTrue(m2.canRead(unnamed));
+        testsReadsAll(m3, layer);
+    }
+
+
+    /**
+     * Test miscellaneous methods.
+     */
+    public void testMisc() throws IOException {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path m1_jar = createJarFile(dir.resolve("m1.jar"), "p/T.class");
+
+        ModuleFinder finder = ModuleFinder.of(m1_jar);
+
+        assertTrue(finder.find("m1").isPresent());
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+
+        // test miscellaneous methods
+        assertTrue(m1.isAutomatic());
+        assertFalse(m1.isSynthetic());
+        assertFalse(m1.osName().isPresent());
+        assertFalse(m1.osArch().isPresent());
+        assertFalse(m1.osVersion().isPresent());
+    }
+
+
+    /**
+     * Invokes parent.resolveRequires to resolve the given root modules.
+     */
+    static Configuration resolve(Configuration parent,
+                                 ModuleFinder finder,
+                                 String... roots) {
+        return parent.resolveRequires(finder, ModuleFinder.empty(), Set.of(roots));
+    }
+
+    /**
+     * Finds a module in the given configuration or its parents, returning
+     * the module descriptor (or null if not found)
+     */
+    static ModuleDescriptor findDescriptor(Configuration cf, String name) {
+        Optional<ResolvedModule> om = cf.findModule(name);
+        if (om.isPresent()) {
+            return om.get().reference().descriptor();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Test that a module in a configuration reads all modules in the boot
+     * configuration.
+     */
+    static void testReadAllBootModules(Configuration cf, String mn) {
+
+        Set<String> bootModules = Layer.boot().modules().stream()
+                .map(Module::getName)
+                .collect(Collectors.toSet());
+
+        bootModules.forEach(other -> assertTrue(reads(cf, mn, other)));
+
+    }
+
+    /**
+     * Test that the given Module reads all module in the given Layer
+     * and its parent Layers.
+     */
+    static void testsReadsAll(Module m, Layer layer) {
+        while (layer != Layer.empty()) {
+
+            // 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();
+        }
+    }
+
+    /**
+     * Returns {@code true} if the configuration contains module mn1
+     * that reads module mn2.
+     */
+    static boolean reads(Configuration cf, String mn1, String mn2) {
+        Optional<ResolvedModule> om1 = cf.findModule(mn1);
+        if (!om1.isPresent())
+            return false;
+
+        return om1.get().reads().stream()
+                .map(ResolvedModule::name)
+                .anyMatch(mn2::equals);
+    }
+
+    /**
+     * Creates a JAR file, optionally with a manifest, and with the given
+     * entries. The entries will be empty in the resulting JAR file.
+     */
+    static Path createJarFile(Path file, Manifest man, String... entries)
+        throws IOException
+    {
+        try (OutputStream out = Files.newOutputStream(file)) {
+            try (JarOutputStream jos = new JarOutputStream(out)) {
+
+                if (man != null) {
+                    JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+                    jos.putNextEntry(je);
+                    man.write(jos);
+                    jos.closeEntry();
+                }
+
+                for (String entry : entries) {
+                    JarEntry je = new JarEntry(entry);
+                    jos.putNextEntry(je);
+                    jos.closeEntry();
+                }
+
+            }
+        }
+        return file;
+    }
+
+    /**
+     * Creates a JAR file and with the given entries. The entries will be empty
+     * in the resulting JAR file.
+     */
+    static Path createJarFile(Path file, String... entries)
+        throws IOException
+    {
+        return createJarFile(file, null, entries);
+    }
+
+}
diff --git a/jdk/test/java/lang/module/ConfigurationTest.java b/jdk/test/java/lang/module/ConfigurationTest.java
new file mode 100644
index 0000000..9e7e9d4
--- /dev/null
+++ b/jdk/test/java/lang/module/ConfigurationTest.java
@@ -0,0 +1,1554 @@
+/*
+ * 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
+ * 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 ConfigurationTest ModuleUtils
+ * @run testng ConfigurationTest
+ * @summary Basic tests for java.lang.module.Configuration
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ResolutionException;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.util.Optional;
+import java.util.Set;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ConfigurationTest {
+
+
+    /**
+     * Basic test of resolver
+     *     m1 requires m2, m2 requires m3
+     */
+    public void testBasic() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m3")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 3);
+
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.findModule("m3").isPresent());
+
+        assertTrue(cf.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+        ResolvedModule m3 = cf.findModule("m3").get();
+
+        // m1 reads m2
+        assertTrue(m1.reads().size() == 1);
+        assertTrue(m1.reads().contains(m2));
+
+        // m2 reads m3
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m3));
+
+        // m3 reads nothing
+        assertTrue(m3.reads().size() == 0);
+
+        // toString
+        assertTrue(cf.toString().contains("m1"));
+        assertTrue(cf.toString().contains("m2"));
+        assertTrue(cf.toString().contains("m3"));
+    }
+
+
+    /**
+     * Basic test of "requires public":
+     *     m1 requires m2, m2 requires public m3
+     */
+    public void testRequiresPublic1() {
+        // m1 requires m2, m2 requires public m3
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m3")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 3);
+
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.findModule("m3").isPresent());
+
+        assertTrue(cf.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+        ResolvedModule m3 = cf.findModule("m3").get();
+
+        // m1 reads m2 and m3
+        assertTrue(m1.reads().size() == 2);
+        assertTrue(m1.reads().contains(m2));
+        assertTrue(m1.reads().contains(m3));
+
+        // m2 reads m3
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m3));
+
+        // m3 reads nothing
+        assertTrue(m3.reads().size() == 0);
+    }
+
+
+    /**
+     * Basic test of "requires public" with configurations.
+     *
+     * The test consists of three configurations:
+     * - Configuration cf1: m1, m2 requires public m1
+     * - Configuration cf2: m3 requires m1
+     */
+    public void testRequiresPublic2() {
+
+        // cf1: m1 and m2, m2 requires public m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m1")
+                .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.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        ResolvedModule m2 = cf1.findModule("m2").get();
+
+        assertTrue(m1.reads().size() == 0);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+
+        // cf2: m3, m3 requires m2
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m1").isPresent());  // in parent
+        assertTrue(cf2.findModule("m2").isPresent());  // in parent
+        assertTrue(cf2.findModule("m3").isPresent());
+        assertTrue(cf2.parent().get() == cf1);
+
+        ResolvedModule m3 = cf2.findModule("m3").get();
+        assertTrue(m3.configuration() == cf2);
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1));
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Basic test of "requires public" with configurations.
+     *
+     * The test consists of three configurations:
+     * - Configuration cf1: m1
+     * - Configuration cf2: m2 requires public m3, m3 requires m2
+     */
+    public void testRequiresPublic3() {
+
+        // cf1: m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf1.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        assertTrue(m1.reads().size() == 0);
+
+
+        // cf2: m2, m3: m2 requires public m1, m3 requires m2
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2, descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        assertTrue(cf2.modules().size() == 2);
+        assertTrue(cf2.findModule("m1").isPresent());   // in parent
+        assertTrue(cf2.findModule("m2").isPresent());
+        assertTrue(cf2.findModule("m3").isPresent());
+        assertTrue(cf2.parent().get() == cf1);
+
+        ResolvedModule m2 = cf2.findModule("m2").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+
+        assertTrue(m2.configuration() == cf2);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+        assertTrue(m3.configuration() == cf2);
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1));
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Basic test of "requires public" with configurations.
+     *
+     * The test consists of three configurations:
+     * - Configuration cf1: m1
+     * - Configuration cf2: m2 requires public m1
+     * - Configuraiton cf3: m3 requires m3
+     */
+    public void testRequiresPublic4() {
+
+        // cf1: m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf1.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        assertTrue(m1.reads().size() == 0);
+
+
+        // cf2: m2 requires public m1
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m2");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m1").isPresent());  // in parent
+        assertTrue(cf2.findModule("m2").isPresent());
+        assertTrue(cf2.parent().get() == cf1);
+
+        ResolvedModule m2 = cf2.findModule("m2").get();
+
+        assertTrue(m2.configuration() == cf2);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+
+        // cf3: m3 requires m2
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder3 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf3 = resolveRequires(cf2, finder3, "m3");
+
+        assertTrue(cf3.modules().size() == 1);
+        assertTrue(cf3.findModule("m1").isPresent());  // in parent
+        assertTrue(cf3.findModule("m2").isPresent());  // in parent
+        assertTrue(cf3.findModule("m3").isPresent());
+        assertTrue(cf3.parent().get() == cf2);
+
+        ResolvedModule m3 = cf3.findModule("m3").get();
+
+        assertTrue(m3.configuration() == cf3);
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1));
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Basic test of "requires public" with configurations.
+     *
+     * The test consists of two configurations:
+     * - Configuration cf1: m1, m2 requires public m1
+     * - Configuration cf2: m3 requires public m2, m4 requires m3
+     */
+    public void testRequiresPublic5() {
+
+        // cf1: m1, m2 requires public m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m1")
+                .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.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        ResolvedModule m2 = cf1.findModule("m2").get();
+
+        assertTrue(m1.configuration() == cf1);
+        assertTrue(m1.reads().size() == 0);
+
+        assertTrue(m2.configuration() == cf1);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+
+        // cf2: m3 requires public m2, m4 requires m3
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires(Modifier.PUBLIC, "m2")
+                .build();
+
+        ModuleDescriptor descriptor4
+            = new ModuleDescriptor.Builder("m4")
+                .requires("m3")
+                .build();
+
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3", "m4");
+
+        assertTrue(cf2.modules().size() == 2);
+        assertTrue(cf2.findModule("m1").isPresent());   // in parent
+        assertTrue(cf2.findModule("m2").isPresent());   // in parent
+        assertTrue(cf2.findModule("m3").isPresent());
+        assertTrue(cf2.findModule("m4").isPresent());
+        assertTrue(cf2.parent().get() == cf1);
+
+        ResolvedModule m3 = cf2.findModule("m3").get();
+        ResolvedModule m4 = cf2.findModule("m4").get();
+
+        assertTrue(m3.configuration() == cf2);
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1));
+        assertTrue(m3.reads().contains(m2));
+
+        assertTrue(m4.configuration() == cf2);
+        assertTrue(m4.reads().size() == 3);
+        assertTrue(m4.reads().contains(m1));
+        assertTrue(m4.reads().contains(m2));
+        assertTrue(m4.reads().contains(m3));
+    }
+
+
+    /**
+     * Basic test of binding services
+     *     m1 uses p.S
+     *     m2 provides p.S
+     */
+    public void testServiceBinding1() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequiresAndUses(finder, "m1");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+
+        assertTrue(m1.configuration() == cf);
+        assertTrue(m1.reads().size() == 0);
+
+        assertTrue(m2.configuration() == cf);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of binding services
+     *     m1 uses p.S1
+     *     m2 provides p.S1, m2 uses p.S2
+     *     m3 provides p.S2
+     */
+    public void testServiceBinding2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .uses("p.S2")
+                .conceals("q")
+                .provides("p.S1", "q.Service1Impl")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S2", "q.Service2Impl")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        Configuration cf = resolveRequiresAndUses(finder, "m1");
+
+        assertTrue(cf.modules().size() == 3);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.findModule("m3").isPresent());
+        assertTrue(cf.parent().get() == Configuration.empty());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+        ResolvedModule m3 = cf.findModule("m3").get();
+
+        assertTrue(m1.configuration() == cf);
+        assertTrue(m1.reads().size() == 0);
+
+        assertTrue(m2.configuration() == cf);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+        assertTrue(m3.configuration() == cf);
+        assertTrue(m3.reads().size() == 1);
+        assertTrue(m3.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of binding services with configurations.
+     *
+     * The test consists of two configurations:
+     * - Configuration cf1: m1 uses p.S
+     * - Configuration cf2: m2 provides p.S
+     */
+    public void testServiceBindingWithConfigurations1() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
+
+        Configuration cf2 = resolveRequiresAndUses(cf1, finder2); // no roots
+
+        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m2").isPresent());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        ResolvedModule m2 = cf2.findModule("m2").get();
+
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of binding services with configurations.
+     *
+     * The test consists of two configurations:
+     * - Configuration cf1: m1 uses p.S && provides p.S,
+     *                      m2 provides p.S
+     * - Configuration cf2: m3 provides p.S
+     *                      m4 provides p.S
+     */
+    public void testServiceBindingWithConfigurations2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .conceals("p1")
+                .provides("p.S", "p1.ServiceImpl")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("p2")
+                .provides("p.S", "p2.ServiceImpl")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf1 = resolveRequiresAndUses(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 2);
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf1.findModule("m2").isPresent());
+
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m1")
+                .conceals("p3")
+                .provides("p.S", "p3.ServiceImpl")
+                .build();
+
+        ModuleDescriptor descriptor4
+            = new ModuleDescriptor.Builder("m4")
+                .requires("m1")
+                .conceals("p4")
+                .provides("p.S", "p4.ServiceImpl")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
+
+        Configuration cf2 = resolveRequiresAndUses(cf1, finder2); // no roots
+
+        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.modules().size() == 2);
+        assertTrue(cf2.findModule("m3").isPresent());
+        assertTrue(cf2.findModule("m4").isPresent());
+
+        ResolvedModule m1 = cf2.findModule("m1").get();  // should find in parent
+        ResolvedModule m2 = cf2.findModule("m2").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+        ResolvedModule m4 = cf2.findModule("m4").get();
+
+        assertTrue(m1.reads().size() == 0);
+
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+
+        assertTrue(m3.reads().size() == 1);
+        assertTrue(m3.reads().contains(m1));
+
+        assertTrue(m4.reads().size() == 1);
+        assertTrue(m4.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of binding services with configurations.
+     *
+     * Configuration cf1: p@1.0 provides p.S
+     * Test configuration cf2: m1 uses p.S
+     * Test configuration cf2: m1 uses p.S, p@2.0 uses p.S
+     */
+    public void testServiceBindingWithConfigurations3() {
+
+        ModuleDescriptor service
+            = new ModuleDescriptor.Builder("s")
+                .exports("p")
+                .build();
+
+        ModuleDescriptor provider_v1
+            = new ModuleDescriptor.Builder("p")
+                .version("1.0")
+                .requires("s")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(service, provider_v1);
+
+        Configuration cf1 = resolveRequires(finder1, "p");
+
+        assertTrue(cf1.modules().size() == 2);
+        assertTrue(cf1.findModule("s").isPresent());
+        assertTrue(cf1.findModule("p").isPresent());
+
+        // p@1.0 in cf1
+        ResolvedModule p = cf1.findModule("p").get();
+        assertEquals(p.reference().descriptor(), provider_v1);
+
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("s")
+                .uses("p.S")
+                .build();
+
+        ModuleDescriptor provider_v2
+            = new ModuleDescriptor.Builder("p")
+                .version("2.0")
+                .requires("s")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, provider_v2);
+
+
+        // finder2 is the before ModuleFinder and so p@2.0 should be located
+
+        Configuration cf2 = resolveRequiresAndUses(cf1, finder2, "m1");
+
+        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.modules().size() == 2);
+
+        // p should be found in cf2
+        p = cf2.findModule("p").get();
+        assertTrue(p.configuration() == cf2);
+        assertEquals(p.reference().descriptor(), provider_v2);
+
+
+        // finder2 is the after ModuleFinder and so p@2.0 should not be located
+        // as module p is in parent configuration.
+
+        cf2 = resolveRequiresAndUses(cf1, ModuleFinder.empty(), finder2, "m1");
+
+        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.modules().size() == 1);
+
+        // p should be found in cf1
+        p = cf2.findModule("p").get();
+        assertTrue(p.configuration() == cf1);
+        assertEquals(p.reference().descriptor(), provider_v1);
+    }
+
+
+    /**
+     * Basic test with two module finders.
+     *
+     * Module m2 can be found by both the before and after finders.
+     */
+    public void testWithTwoFinders1() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .build();
+
+        ModuleDescriptor descriptor2_v1
+            = new ModuleDescriptor.Builder("m2")
+                .version("1.0")
+                .build();
+
+        ModuleDescriptor descriptor2_v2
+            = new ModuleDescriptor.Builder("m2")
+                .version("2.0")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor2_v1);
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor2_v2);
+
+        Configuration cf = resolveRequires(finder1, finder2, "m1");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+
+        assertEquals(m1.reference().descriptor(), descriptor1);
+        assertEquals(m2.reference().descriptor(), descriptor2_v1);
+    }
+
+
+    /**
+     * Basic test with two modules finders and service binding.
+     *
+     * The before and after ModuleFinders both locate a service provider module
+     * named "m2" that provide implementations of the same service type.
+     */
+    public void testWithTwoFinders2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .build();
+
+        ModuleDescriptor descriptor2_v1
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleDescriptor descriptor2_v2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2_v1);
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2_v2);
+
+        Configuration cf = resolveRequiresAndUses(finder1, finder2, "m1");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+
+        assertEquals(m1.reference().descriptor(), descriptor1);
+        assertEquals(m2.reference().descriptor(), descriptor2_v1);
+    }
+
+
+    /**
+     * Basic test for resolving a module that is located in the parent
+     * configuration.
+     */
+    public void testResolvedInParent1() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+        Configuration cf2 = resolveRequires(cf1, finder, "m1");
+
+        assertTrue(cf2.modules().size() == 1);
+    }
+
+
+    /**
+     * Basic test for resolving a module that has a dependency on a module
+     * in the parent configuration.
+     */
+    public void testResolvedInParent2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
+
+        Configuration cf2 = resolveRequires(cf1, ModuleFinder.empty(), finder2, "m2");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m2").isPresent());
+
+        ResolvedModule m1 = cf2.findModule("m1").get();   // find in parent
+        ResolvedModule m2 = cf2.findModule("m2").get();
+
+        assertTrue(m1.reads().size() == 0);
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of using the beforeFinder to override a module in the parent
+     * configuration.
+     */
+    public void testOverriding1() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder, "m1");
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+        Configuration cf2 = resolveRequires(cf1, finder, "m1");
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+    }
+
+
+    /**
+     * Basic test of using the beforeFinder to override a module in the parent
+     * configuration but where implied readability in the picture so that the
+     * module in the parent is read.
+     *
+     * The test consists of two configurations:
+     * - Configuration cf1: m1, m2 requires public m1
+     * - Configuration cf2: m1, m3 requires m2
+     */
+    public void testOverriding2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(Modifier.PUBLIC, "m1")
+                .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());
+
+        // cf2: m3 requires m2, m1
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m1", "m3");
+
+        assertTrue(cf2.parent().get() == cf1);
+
+        assertTrue(cf2.modules().size() == 2);
+        assertTrue(cf2.findModule("m1").isPresent());
+        assertTrue(cf2.findModule("m3").isPresent());
+
+        ResolvedModule m1_1 = cf1.findModule("m1").get();
+        ResolvedModule m1_2 = cf2.findModule("m1").get();
+        ResolvedModule m2 = cf1.findModule("m2").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+
+        assertTrue(m1_1.configuration() == cf1);
+        assertTrue(m1_2.configuration() == cf2);
+        assertTrue(m3.configuration() == cf2);
+
+
+        // check that m3 reads cf1/m1 and cf2/m2
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1_1));
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Root module not found
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testRootNotFound() {
+        resolveRequires(ModuleFinder.empty(), "m1");
+    }
+
+
+    /**
+     * Direct dependency not found
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testDirectDependencyNotFound() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+        resolveRequires(finder, "m1");
+    }
+
+
+    /**
+     * Transitive dependency not found
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testTransitiveDependencyNotFound() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2").requires("m3").build();
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+        resolveRequires(finder, "m1");
+    }
+
+
+    /**
+     * Service provider dependency not found
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testServiceProviderDependencyNotFound() {
+
+        // service provider dependency (on m3) not found
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .requires("m3")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        // should throw ResolutionException because m3 is not found
+        Configuration cf = resolveRequiresAndUses(finder, "m1");
+    }
+
+
+    /**
+     * Simple cycle.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testSimpleCycle() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2").requires("m3").build();
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3").requires("m1").build();
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+        resolveRequires(finder, "m1");
+    }
+
+    /**
+     * Basic test for detecting cycles involving a service provider module
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testCycleInProvider() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .uses("p.S")
+                .build();
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .requires("m3")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        // should throw ResolutionException because of the m2 <--> m3 cycle
+        resolveRequiresAndUses(finder, "m1");
+    }
+
+
+    /**
+     * Test two modules exporting package p to a module that reads both.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testPackageSuppliedByTwoOthers() {
+
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("m3")
+                .build();
+
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .exports("p")
+                .build();
+
+        ModuleDescriptor descriptor3
+            =  new ModuleDescriptor.Builder("m3")
+                .exports("p", "m1")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        // m2 and m3 export package p to module m1
+        resolveRequires(finder, "m1");
+    }
+
+
+    /**
+     * Test the scenario where a module has a concealed package p and reads
+     * a module that exports package p.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testPackageSuppliedBySelfAndOther() {
+
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .conceals("p")
+                .build();
+
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .exports("p")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        //  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.
+     */
+    public void testPackagePrivateToSelfAndOther() {
+
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .conceals("p")
+                .build();
+
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .conceals("p")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+
+        // m1 reads m2, m2 reads nothing
+        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);
+    }
+
+
+    /**
+     * Test the scenario where a module that exports a package that is also
+     * exported by a module that it reads in a parent layer.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testExportSamePackageAsBootLayer() {
+        ModuleDescriptor descriptor
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("java.base")
+                .exports("java.lang")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+        Configuration bootConfiguration = Layer.boot().configuration();
+
+        // m1 contains package java.lang, java.base exports package java.lang to m1
+        resolveRequires(bootConfiguration, finder, "m1");
+    }
+
+
+    /**
+     * Test "uses p.S" where p is a concealed package in the same module.
+     */
+    public void testConcealedService1() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("p")
+                .uses("p.S")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 1);
+        assertTrue(cf.findModule("m1").isPresent());
+    }
+
+
+    /**
+     * Test "uses p.S" where p is a concealed package in a different module.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testConcealedService2() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("p")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .uses("p.S")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        // m2 does not read a module that exports p
+        resolveRequires(finder, "m2");
+    }
+
+
+    /**
+     * Test "provides p.S" where p is a concealed package in the same module.
+     */
+    public void testConcealedService3() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("p")
+                .conceals("q")
+                .provides("p.S", "q.S1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 1);
+        assertTrue(cf.findModule("m1").isPresent());
+    }
+
+
+    /**
+     * Test "provides p.S" where p is a concealed package in a different module.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testConcealedService4() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("p")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .conceals("q")
+                .provides("p.S", "q.S1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        // m2 does not read a module that exports p
+        resolveRequires(finder, "m2");
+    }
+
+
+    /**
+     * Test "uses p.S" where p is not exported to the module.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testServiceTypePackageNotExported1() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .uses("p.S")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        // m1 does not read a module that exports p
+        resolveRequires(finder, "m1");
+    }
+
+
+    /**
+     * Test "provides p.S" where p is not exported to the module.
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testServiceTypePackageNotExported2() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("q")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        // m1 does not read a module that exports p
+        resolveRequires(finder, "m1");
+    }
+
+
+    /**
+     * Test "provides p.S" where p is not local
+     */
+    @Test(expectedExceptions = { ResolutionException.class })
+    public void testProviderPackageNotLocal() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .exports("q")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m1")
+                .provides("p.S", "q.T")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        // q.T not in module m2
+        resolveRequires(finder, "m2");
+    }
+
+
+    /**
+     * Test the empty configuration.
+     */
+    public void testEmptyConfiguration() {
+        Configuration cf = Configuration.empty();
+
+        assertFalse(cf.parent().isPresent());
+
+        assertTrue(cf.modules().isEmpty());
+        assertFalse(cf.findModule("java.base").isPresent());
+    }
+
+
+    // platform specific modules
+
+    @DataProvider(name = "platformmatch")
+    public Object[][] createPlatformMatches() {
+        return new Object[][]{
+
+            { "linux-*-*",       "*-*-*" },
+            { "*-arm-*",         "*-*-*" },
+            { "*-*-2.6",         "*-*-*" },
+
+            { "linux-arm-*",     "*-*-*" },
+            { "linux-*-2.6",     "*-*-*" },
+            { "*-arm-2.6",       "*-*-*" },
+
+            { "linux-arm-2.6",   "*-*-*" },
+
+            { "linux-*-*",       "linux-*-*" },
+            { "*-arm-*",         "*-arm-*"   },
+            { "*-*-2.6",         "*-*-2.6"   },
+
+            { "linux-arm-*",     "linux-arm-*" },
+            { "linux-arm-*",     "linux-*-*"   },
+            { "linux-*-2.6",     "linux-*-2.6" },
+            { "linux-*-2.6",     "linux-arm-*" },
+
+            { "linux-arm-2.6",   "linux-arm-2.6" },
+
+        };
+
+    };
+
+    @DataProvider(name = "platformmismatch")
+    public Object[][] createBad() {
+        return new Object[][] {
+
+            { "linux-*-*",        "solaris-*-*"   },
+            { "linux-x86-*",      "linux-arm-*"   },
+            { "linux-*-2.4",      "linux-x86-2.6" },
+        };
+    }
+
+    /**
+     * Test creating a configuration containing platform specific modules.
+     */
+    @Test(dataProvider = "platformmatch")
+    public void testPlatformMatch(String s1, String s2) {
+
+        ModuleDescriptor.Builder builder
+            = new ModuleDescriptor.Builder("m1").requires("m2");
+
+        String[] s = s1.split("-");
+        if (!s[0].equals("*"))
+            builder.osName(s[0]);
+        if (!s[1].equals("*"))
+            builder.osArch(s[1]);
+        if (!s[2].equals("*"))
+            builder.osVersion(s[2]);
+
+        ModuleDescriptor descriptor1 = builder.build();
+
+        builder = new ModuleDescriptor.Builder("m2");
+
+        s = s2.split("-");
+        if (!s[0].equals("*"))
+            builder.osName(s[0]);
+        if (!s[1].equals("*"))
+            builder.osArch(s[1]);
+        if (!s[2].equals("*"))
+            builder.osVersion(s[2]);
+
+        ModuleDescriptor descriptor2 = builder.build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m1").isPresent());
+        assertTrue(cf.findModule("m2").isPresent());
+    }
+
+    /**
+     * Test attempting to create a configuration with modules for different
+     * platforms.
+     */
+    @Test(dataProvider = "platformmismatch",
+          expectedExceptions = ResolutionException.class )
+    public void testPlatformMisMatch(String s1, String s2) {
+        testPlatformMatch(s1, s2);
+    }
+
+
+    // null handling
+
+    // finder1, finder2, roots
+
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull1() {
+        resolveRequires((ModuleFinder)null, ModuleFinder.empty());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull2() {
+        resolveRequires(ModuleFinder.empty(), (ModuleFinder)null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull1() {
+        resolveRequiresAndUses((ModuleFinder) null, ModuleFinder.empty());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull2() {
+        resolveRequiresAndUses(ModuleFinder.empty(), (ModuleFinder) null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testFindModuleWithNull() {
+        Configuration.empty().findModule(null);
+    }
+
+    // immutable sets
+
+    @Test(expectedExceptions = { UnsupportedOperationException.class })
+    public void testImmutableSet1() {
+        Configuration cf = Layer.boot().configuration();
+        ResolvedModule base = cf.findModule("java.base").get();
+        cf.modules().add(base);
+    }
+
+    @Test(expectedExceptions = { UnsupportedOperationException.class })
+    public void testImmutableSet2() {
+        Configuration cf = Layer.boot().configuration();
+        ResolvedModule base = cf.findModule("java.base").get();
+        base.reads().add(base);
+    }
+
+
+    /**
+     * Invokes parent.resolveRequires(...)
+     */
+    private Configuration resolveRequires(Configuration parent,
+                                          ModuleFinder before,
+                                          ModuleFinder after,
+                                          String... roots) {
+        return parent.resolveRequires(before, after, Set.of(roots));
+    }
+
+    private Configuration resolveRequires(Configuration parent,
+                                          ModuleFinder before,
+                                          String... roots) {
+        return resolveRequires(parent, before, ModuleFinder.empty(), roots);
+    }
+
+    private Configuration resolveRequires(ModuleFinder before,
+                                          ModuleFinder after,
+                                          String... roots) {
+        return resolveRequires(Configuration.empty(), before, after, roots);
+    }
+
+    private Configuration resolveRequires(ModuleFinder before,
+                                          String... roots) {
+        return resolveRequires(Configuration.empty(), before, roots);
+    }
+
+
+    /**
+     * Invokes parent.resolveRequiresAndUses(...)
+     */
+    private Configuration resolveRequiresAndUses(Configuration parent,
+                                                 ModuleFinder before,
+                                                 ModuleFinder after,
+                                                 String... roots) {
+        return parent.resolveRequiresAndUses(before, after, Set.of(roots));
+    }
+
+    private Configuration resolveRequiresAndUses(Configuration parent,
+                                                 ModuleFinder before,
+                                                 String... roots) {
+        return resolveRequiresAndUses(parent, before, ModuleFinder.empty(), roots);
+    }
+
+    private Configuration resolveRequiresAndUses(ModuleFinder before,
+                                                 ModuleFinder after,
+                                                 String... roots) {
+        return resolveRequiresAndUses(Configuration.empty(), before, after, roots);
+    }
+
+    private Configuration resolveRequiresAndUses(ModuleFinder before,
+                                                 String... roots) {
+        return resolveRequiresAndUses(Configuration.empty(), before, roots);
+    }
+
+
+    /**
+     * Returns {@code true} if the configuration contains module mn1
+     * that reads module mn2.
+     */
+    static boolean reads(Configuration cf, String mn1, String mn2) {
+        Optional<ResolvedModule> om1 = cf.findModule(mn1);
+        if (!om1.isPresent())
+            return false;
+
+        return om1.get().reads().stream()
+                .map(ResolvedModule::name)
+                .anyMatch(mn2::equals);
+    }
+
+
+}
diff --git a/jdk/test/java/lang/module/ModuleDescriptorTest.java b/jdk/test/java/lang/module/ModuleDescriptorTest.java
new file mode 100644
index 0000000..61dfc4e
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleDescriptorTest.java
@@ -0,0 +1,727 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @run testng ModuleDescriptorTest
+ * @summary Basic test for java.lang.module.ModuleDescriptor and its builder
+ */
+
+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.Requires;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.reflect.Module;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModuleDescriptorTest {
+
+    @DataProvider(name = "invalidjavaidentifiers")
+    public Object[][] invalidJavaIdentifiers() {
+        return new Object[][]{
+
+            { null,         null },
+            { ".foo",       null },
+            { "foo.",       null },
+            { "[foo]",      null },
+
+        };
+    }
+
+
+    // requires
+
+    private Requires requires(Set<Modifier> mods, String mn) {
+        return new Builder("m")
+            .requires(mods, mn)
+            .build()
+            .requires()
+            .iterator()
+            .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);
+    }
+
+    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 testRequiresWithNoModifiers() {
+        Requires r = requires(EnumSet.noneOf(Requires.Modifier.class), "foo");
+        assertEquals(r, r);
+        assertTrue(r.compareTo(r) == 0);
+        assertTrue(r.modifiers().isEmpty());
+        assertEquals(r.name(), "foo");
+    }
+
+    public void testRequiresWithOneModifier() {
+        Requires r = requires(EnumSet.of(PUBLIC), "foo");
+        assertEquals(r, r);
+        assertTrue(r.compareTo(r) == 0);
+        assertEquals(r.modifiers(), EnumSet.of(PUBLIC));
+        assertEquals(r.name(), "foo");
+    }
+
+    public void testRequiresWithTwoModifiers() {
+        Requires r = requires(EnumSet.of(PUBLIC, SYNTHETIC), "foo");
+        assertEquals(r, r);
+        assertTrue(r.compareTo(r) == 0);
+        assertEquals(r.modifiers(), EnumSet.of(PUBLIC, SYNTHETIC));
+        assertEquals(r.name(), "foo");
+    }
+
+    public void testRequiresWithAllModifiers() {
+        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.name(), "foo");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testRequiresWithDuplicatesRequires() {
+        Requires r = requires(null, "foo");
+        new Builder("m").requires(r).requires(r);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testRequiresSelfWithRequires() {
+        Requires r = requires(null, "m");
+        new Builder("m").requires(r);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testRequiresSelfWithNoModifier() {
+        new Builder("m").requires("m");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testRequiresSelfWithOneModifier() {
+        new Builder("m").requires(PUBLIC, "m");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testRequiresSelfWithAllModifiers() {
+        new Builder("m").requires(EnumSet.allOf(Modifier.class), "m");
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testRequiresWithBadModuleName(String mn, String ignore) {
+        requires(EnumSet.noneOf(Modifier.class), mn);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testRequiresWithNullRequires() {
+        new Builder("m").requires((Requires) null);
+    }
+
+    public void testRequiresCompare() {
+        Requires r1 = requires(EnumSet.noneOf(Modifier.class), "foo");
+        Requires r2 = requires(EnumSet.noneOf(Modifier.class), "bar");
+        int n = "foo".compareTo("bar");
+        assertTrue(r1.compareTo(r2) == n);
+        assertTrue(r2.compareTo(r1) == -n);
+    }
+
+    public void testRequiresToString() {
+        Requires r = requires(EnumSet.noneOf(Modifier.class), "foo");
+        assertTrue(r.toString().contains("foo"));
+    }
+
+
+    // exports
+
+    private Exports exports(String pn) {
+        return new Builder("foo")
+            .exports(pn)
+            .build()
+            .exports()
+            .iterator()
+            .next();
+    }
+
+    private Exports exports(String pn, String target) {
+        return new Builder("foo")
+            .exports(pn, target)
+            .build()
+            .exports()
+            .iterator()
+            .next();
+    }
+
+    public void testExportsExports() {
+        Exports e1 = exports("p");
+        ModuleDescriptor descriptor = new Builder("m").exports(e1).build();
+        Exports e2 = descriptor.exports().iterator().next();
+        assertEquals(e1, e2);
+    }
+
+    public void testExportsToAll() {
+        Exports e = exports("p");
+        assertEquals(e, e);
+        assertEquals(e.source(), "p");
+        assertFalse(e.isQualified());
+        assertTrue(e.targets().isEmpty());
+    }
+
+    public void testExportsToTarget() {
+        Exports e = exports("p", "bar");
+        assertEquals(e, e);
+        assertEquals(e.source(), "p");
+        assertTrue(e.isQualified());
+        assertTrue(e.targets().size() == 1);
+        assertTrue(e.targets().contains("bar"));
+    }
+
+    public void testExportsToTargets() {
+        Set<String> targets = new HashSet<>();
+        targets.add("bar");
+        targets.add("gus");
+        Exports e
+            = new Builder("foo")
+                .exports("p", targets)
+                .build()
+                .exports()
+                .iterator()
+                .next();
+        assertEquals(e, e);
+        assertEquals(e.source(), "p");
+        assertTrue(e.isQualified());
+        assertTrue(e.targets().size() == 2);
+        assertTrue(e.targets().contains("bar"));
+        assertTrue(e.targets().contains("gus"));
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testExportsWithDuplicate1() {
+        Exports e = exports("p");
+        new Builder("foo").exports(e).exports(e);
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testExportsWithDuplicate2() {
+        new Builder("foo").exports("p").exports("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testExportsWithConcealedPackage() {
+        new Builder("foo").conceals("p").exports("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testExportsToTargetWithConcealedPackage() {
+        new Builder("foo").conceals("p").exports("p", "bar");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class )
+    public void testExportsWithEmptySet() {
+        new Builder("foo").exports("p", Collections.emptySet());
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testExportsWithBadName(String pn, String ignore) {
+        new Builder("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);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testExportsWithNullTargets() {
+        new Builder("foo").exports("p", (Set<String>) null);
+    }
+
+    public void testExportsToString() {
+        String s = new Builder("foo")
+            .exports("p1", "bar")
+            .build()
+            .exports()
+            .iterator()
+            .next()
+            .toString();
+        assertTrue(s.contains("p1"));
+        assertTrue(s.contains("bar"));
+    }
+
+
+    // uses
+
+    public void testUses() {
+        Set<String> uses
+            = new Builder("foo")
+                .uses("p.S")
+                .uses("q.S")
+                .build()
+                .uses();
+        assertTrue(uses.size() == 2);
+        assertTrue(uses.contains("p.S"));
+        assertTrue(uses.contains("q.S"));
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testUsesWithDuplicate() {
+        new Builder("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);
+    }
+
+
+    // provides
+
+    private Provides provides(String st, String pc) {
+        return new Builder("foo")
+            .provides("p.S", 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");
+        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)
+                .build()
+                .provides();
+        assertTrue(map.size() == 1);
+
+        Provides p = map.values().iterator().next();
+        assertEquals(p, p);
+        assertTrue(p.providers().size() == 2);
+        assertTrue(p.providers().contains("q.P1"));
+        assertTrue(p.providers().contains("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);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class )
+    public void testProvidesWithEmptySet() {
+        new Builder("foo").provides("p.Service", Collections.emptySet());
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testProvidesWithBadService(String service, String ignore) {
+        new Builder("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);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testProvidesWithNullProvides() {
+        new Builder("foo").provides((Provides)null);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testProvidesWithNullProviders() {
+        new Builder("foo").provides("p.S", (Set<String>) null);
+    }
+
+
+    // conceals
+
+    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"));
+    }
+
+    public void testConcealsWithEmptySet() {
+        Set<String> conceals
+            = new Builder("foo").conceals(Collections.emptySet()).build().conceals();
+        assertTrue(conceals.size() == 0);
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testConcealsWithDuplicate() {
+        new Builder("foo").conceals("p").conceals("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testConcealsWithExportedPackage() {
+        new Builder("foo").exports("p").conceals("p");
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testConcealsWithBadName(String pn, String ignore) {
+        new Builder("foo").conceals(pn);
+    }
+
+
+    // packages
+
+    public void testPackages() {
+        Set<String> packages
+            = new Builder("foo").exports("p").conceals("q").build().packages();
+        assertTrue(packages.size() == 2);
+        assertTrue(packages.contains("p"));
+        assertTrue(packages.contains("q"));
+    }
+
+
+    // name
+
+    public void testModuleName() {
+        String mn = new Builder("foo").build().name();
+        assertEquals(mn, "foo");
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testBadModuleName(String mn, String ignore) {
+        new Builder(mn);
+    }
+
+
+    // version
+
+    public void testVersion1() {
+        Version v1 = Version.parse("1.0");
+        Version v2 = new Builder("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 v2 = Version.parse(vs);
+        assertEquals(v1, v2);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testNullVersion1() {
+        new Builder("foo").version((Version)null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class )
+    public void testNullVersion2() {
+        new Builder("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");
+    }
+
+
+    // toNameAndVersion
+
+    public void testToNameAndVersion() {
+        ModuleDescriptor md1 = new Builder("foo").build();
+        assertEquals(md1.toNameAndVersion(), "foo");
+
+        ModuleDescriptor md2 = new Builder("foo").version("1.0").build();
+        assertEquals(md2.toNameAndVersion(), "foo@1.0");
+    }
+
+
+    // isAutomatic
+    public void testIsAutomatic() {
+        ModuleDescriptor descriptor = new Builder("foo").build();
+        assertFalse(descriptor.isAutomatic());
+    }
+
+    // isSynthetic
+    public void testIsSynthetic() {
+        assertFalse(Object.class.getModule().getDescriptor().isSynthetic());
+
+        ModuleDescriptor descriptor = new Builder("foo").build();
+        assertFalse(descriptor.isSynthetic());
+    }
+
+
+    // mainClass
+
+    public void testMainClass() {
+        String mainClass
+            = new Builder("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.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();
+        assertEquals(osName, "Linux");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testNullOsName() {
+        new Builder("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");
+    }
+
+
+    // osArch
+
+    public void testOsArch() {
+        String osArch = new Builder("foo").osName("arm").build().osName().get();
+        assertEquals(osArch, "arm");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testNullOsArch() {
+        new Builder("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");
+    }
+
+
+    // osVersion
+
+    public void testOsVersion() {
+        String osVersion = new Builder("foo").osName("11.2").build().osName().get();
+        assertEquals(osVersion, "11.2");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testNullOsVersion() {
+        new Builder("foo").osVersion(null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testEmptyOsVersion() {
+        new Builder("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() {
+        @Override
+        public int read() {
+            return -1;
+        }
+    };
+
+    private static InputStream FAILING_INPUT_STREAM = new InputStream() {
+        @Override
+        public int read() throws IOException {
+            throw new IOException();
+        }
+    };
+
+    public void testRead() throws Exception {
+        Module base = Object.class.getModule();
+
+        try (InputStream in = base.getResourceAsStream("module-info.class")) {
+            ModuleDescriptor descriptor = ModuleDescriptor.read(in);
+            assertTrue(in.read() == -1); // all bytes read
+            assertEquals(descriptor.name(), "java.base");
+        }
+
+        try (InputStream in = base.getResourceAsStream("module-info.class")) {
+            ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
+            ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
+            assertFalse(bb.hasRemaining()); // no more remaining bytes
+            assertEquals(descriptor.name(), "java.base");
+        }
+    }
+
+    public void testReadsWithPackageFinder() {
+        // TBD: Need way to write a module-info.class without a
+        // ConcealedPackages attribute
+    }
+
+    @Test(expectedExceptions = InvalidModuleDescriptorException.class)
+    public void testReadFromEmptyInputStream() throws Exception {
+        ModuleDescriptor.read(EMPTY_INPUT_STREAM);
+    }
+
+    @Test(expectedExceptions = IOException.class)
+    public void testReadFromFailingInputStream() throws Exception {
+        ModuleDescriptor.read(FAILING_INPUT_STREAM);
+    }
+
+    @Test(expectedExceptions = InvalidModuleDescriptorException.class)
+    public void testReadFromEmptyBuffer() {
+        ByteBuffer bb = ByteBuffer.allocate(0);
+        ModuleDescriptor.read(bb);
+    }
+
+    public void testReadWithNull() throws Exception {
+        Module base = Object.class.getModule();
+
+        try {
+            ModuleDescriptor.read((InputStream)null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+
+        try (InputStream in = base.getResourceAsStream("module-info.class")) {
+            try {
+                ModuleDescriptor.read(in, null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+        }
+
+        try {
+            ModuleDescriptor.read((ByteBuffer)null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+
+        try (InputStream in = base.getResourceAsStream("module-info.class")) {
+            ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
+            try {
+                ModuleDescriptor.read(bb, null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+        }
+    }
+
+
+    // equals/hashCode/compareTo/toString
+
+    public void testEqualsAndHashCode() {
+        ModuleDescriptor md1 = new Builder("foo").build();
+        ModuleDescriptor md2 = new Builder("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();
+        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();
+        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
new file mode 100644
index 0000000..2306ba3
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleFinderTest.java
@@ -0,0 +1,568 @@
+/*
+ * 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
+ * @modules java.base/jdk.internal.module
+ * @build ModuleFinderTest
+ * @run testng ModuleFinderTest
+ * @summary Basic tests for java.lang.module.ModuleFinder
+ */
+
+import java.io.OutputStream;
+import java.lang.module.FindException;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+
+import jdk.internal.module.ModuleInfoWriter;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModuleFinderTest {
+
+    private static final Path USER_DIR
+        = Paths.get(System.getProperty("user.dir"));
+
+
+    /**
+     * Test ModuleFinder.ofSystem
+     */
+    public void testOfSystem() {
+        ModuleFinder finder = ModuleFinder.ofSystem();
+
+        assertTrue(finder.find("java.se").isPresent());
+        assertTrue(finder.find("java.base").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        Set<String> names = finder.findAll().stream()
+            .map(ModuleReference::descriptor)
+            .map(ModuleDescriptor::name)
+            .collect(Collectors.toSet());
+        assertTrue(names.contains("java.se"));
+        assertTrue(names.contains("java.base"));
+        assertFalse(names.contains("java.rhubarb"));
+    }
+
+
+    /**
+     * Test ModuleFinder.of with zero entries
+     */
+    public void testOfZeroEntries() {
+        ModuleFinder finder = ModuleFinder.of();
+        assertTrue(finder.findAll().isEmpty());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with one directory of modules
+     */
+    public void testOfOneDirectory() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createExplodedModule(dir.resolve("m1"), "m1");
+        createModularJar(dir.resolve("m2.jar"), "m2");
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+        assertTrue(finder.findAll().size() == 2);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with two directories
+     */
+    public void testOfTwoDirectories() throws Exception {
+        Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
+        createExplodedModule(dir1.resolve("m1"), "m1@1.0");
+        createModularJar(dir1.resolve("m2.jar"), "m2@1.0");
+
+        Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
+        createExplodedModule(dir2.resolve("m1"), "m1@2.0");
+        createModularJar(dir2.resolve("m2.jar"), "m2@2.0");
+        createExplodedModule(dir2.resolve("m3"), "m3");
+        createModularJar(dir2.resolve("m4.jar"), "m4");
+
+        ModuleFinder finder = ModuleFinder.of(dir1, dir2);
+        assertTrue(finder.findAll().size() == 4);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.find("m3").isPresent());
+        assertTrue(finder.find("m4").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        // check that m1@1.0 (and not m1@2.0) is found
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertEquals(m1.version().get().toString(), "1.0");
+
+        // check that m2@1.0 (and not m2@2.0) is found
+        ModuleDescriptor m2 = finder.find("m2").get().descriptor();
+        assertEquals(m2.version().get().toString(), "1.0");
+    }
+
+
+    /**
+     * Test ModuleFinder.of with one JAR file
+     */
+    public void testOfOneJarFile() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1");
+
+        ModuleFinder finder = ModuleFinder.of(jar1);
+        assertTrue(finder.findAll().size() == 1);
+        assertTrue(finder.find("m1").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with two JAR files
+     */
+    public void testOfTwoJarFiles() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+
+        Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1");
+        Path jar2 = createModularJar(dir.resolve("m2.jar"), "m2");
+
+        ModuleFinder finder = ModuleFinder.of(jar1, jar2);
+        assertTrue(finder.findAll().size() == 2);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with many JAR files
+     */
+    public void testOfManyJarFiles() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+
+        Path jar1 = createModularJar(dir.resolve("m1@1.0.jar"), "m1@1.0");
+        Path jar2 = createModularJar(dir.resolve("m2@1.0.jar"), "m2");
+        Path jar3 = createModularJar(dir.resolve("m1@2.0.jar"), "m1@2.0"); // shadowed
+        Path jar4 = createModularJar(dir.resolve("m3@1.0.jar"), "m3");
+
+        ModuleFinder finder = ModuleFinder.of(jar1, jar2, jar3, jar4);
+        assertTrue(finder.findAll().size() == 3);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.find("m3").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        // check that m1@1.0 (and not m1@2.0) is found
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertEquals(m1.version().get().toString(), "1.0");
+    }
+
+
+    /**
+     * Test ModuleFinder.of with one exploded module.
+     */
+    public void testOfOneExplodedModule() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1");
+
+        ModuleFinder finder = ModuleFinder.of(m1_dir);
+        assertTrue(finder.findAll().size() == 1);
+        assertTrue(finder.find("m1").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with two exploded modules.
+     */
+    public void testOfTwoExplodedModules() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1");
+        Path m2_dir = createExplodedModule(dir.resolve("m2"), "m2");
+
+        ModuleFinder finder = ModuleFinder.of(m1_dir, m2_dir);
+        assertTrue(finder.findAll().size() == 2);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a mix of module directories and JAR files.
+     */
+    public void testOfMixDirectoriesAndJars() throws Exception {
+
+        // directory with m1@1.0 and m2@1.0
+        Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
+        createExplodedModule(dir1.resolve("m1"), "m1@1.0");
+        createModularJar(dir1.resolve("m2.jar"), "m2@1.0");
+
+        // JAR files: m1@2.0, m2@2.0, m3@2.0, m4@2.0
+        Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
+        Path jar1 = createModularJar(dir2.resolve("m1.jar"), "m1@2.0");
+        Path jar2 = createModularJar(dir2.resolve("m2.jar"), "m2@2.0");
+        Path jar3 = createModularJar(dir2.resolve("m3.jar"), "m3@2.0");
+        Path jar4 = createModularJar(dir2.resolve("m4.jar"), "m4@2.0");
+
+        // directory with m3@3.0 and m4@3.0
+        Path dir3 = Files.createTempDirectory(USER_DIR, "mods3");
+        createExplodedModule(dir3.resolve("m3"), "m3@3.0");
+        createModularJar(dir3.resolve("m4.jar"), "m4@3.0");
+
+        // JAR files: m5 and m6
+        Path dir4 = Files.createTempDirectory(USER_DIR, "mods4");
+        Path jar5 = createModularJar(dir4.resolve("m5.jar"), "m5@4.0");
+        Path jar6 = createModularJar(dir4.resolve("m6.jar"), "m6@4.0");
+
+
+        ModuleFinder finder
+            = ModuleFinder.of(dir1, jar1, jar2, jar3, jar4, dir3, jar5, jar6);
+        assertTrue(finder.findAll().size() == 6);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.find("m3").isPresent());
+        assertTrue(finder.find("m4").isPresent());
+        assertTrue(finder.find("m5").isPresent());
+        assertTrue(finder.find("m6").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        // m1 and m2 should be located in dir1
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertEquals(m1.version().get().toString(), "1.0");
+        ModuleDescriptor m2 = finder.find("m2").get().descriptor();
+        assertEquals(m2.version().get().toString(), "1.0");
+
+        // m3 and m4 should be located in JAR files
+        ModuleDescriptor m3 = finder.find("m3").get().descriptor();
+        assertEquals(m3.version().get().toString(), "2.0");
+        ModuleDescriptor m4 = finder.find("m4").get().descriptor();
+        assertEquals(m4.version().get().toString(), "2.0");
+
+        // m5 and m6 should be located in JAR files
+        ModuleDescriptor m5 = finder.find("m5").get().descriptor();
+        assertEquals(m5.version().get().toString(), "4.0");
+        ModuleDescriptor m6 = finder.find("m6").get().descriptor();
+        assertEquals(m6.version().get().toString(), "4.0");
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a mix of module directories and exploded
+     * modules.
+     */
+    public void testOfMixDirectoriesAndExplodedModules() throws Exception {
+        // directory with m1@1.0 and m2@1.0
+        Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
+        createExplodedModule(dir1.resolve("m1"), "m1@1.0");
+        createModularJar(dir1.resolve("m2.jar"), "m2@1.0");
+
+        // exploded modules: m1@2.0, m2@2.0, m3@2.0, m4@2.0
+        Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
+        Path m1_dir = createExplodedModule(dir2.resolve("m1"), "m1@2.0");
+        Path m2_dir = createExplodedModule(dir2.resolve("m2"), "m2@2.0");
+        Path m3_dir = createExplodedModule(dir2.resolve("m3"), "m3@2.0");
+        Path m4_dir = createExplodedModule(dir2.resolve("m4"), "m4@2.0");
+
+        ModuleFinder finder = ModuleFinder.of(dir1, m1_dir, m2_dir, m3_dir, m4_dir);
+        assertTrue(finder.findAll().size() == 4);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.find("m3").isPresent());
+        assertTrue(finder.find("m4").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        // m1 and m2 should be located in dir1
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertEquals(m1.version().get().toString(), "1.0");
+        ModuleDescriptor m2 = finder.find("m2").get().descriptor();
+        assertEquals(m2.version().get().toString(), "1.0");
+
+        // m3 and m4 should be located in dir2
+        ModuleDescriptor m3 = finder.find("m3").get().descriptor();
+        assertEquals(m3.version().get().toString(), "2.0");
+        ModuleDescriptor m4 = finder.find("m4").get().descriptor();
+        assertEquals(m4.version().get().toString(), "2.0");
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a path to a file that does not exist.
+     */
+    public void testOfWithDoesNotExistEntry() throws Exception {
+        Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
+
+        Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
+        createModularJar(dir2.resolve("m2.jar"), "m2@1.0");
+
+        Files.delete(dir1);
+
+        ModuleFinder finder = ModuleFinder.of(dir1, dir2);
+
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.findAll().size() == 1);
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a file path to an unrecognized file type.
+     */
+    public void testOfWithUnrecognizedEntry() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path mod = Files.createTempFile(dir, "m", "mod");
+
+        ModuleFinder finder = ModuleFinder.of(mod);
+        try {
+            finder.find("java.rhubarb");
+            assertTrue(false);
+        } catch (FindException e) {
+            // expected
+        }
+
+        finder = ModuleFinder.of(mod);
+        try {
+            finder.findAll();
+            assertTrue(false);
+        } catch (FindException e) {
+            // expected
+        }
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a directory that contains two
+     * versions of the same module
+     */
+    public void testOfDuplicateModulesInDirectory() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createModularJar(dir.resolve("m1@1.0.jar"), "m1");
+        createModularJar(dir.resolve("m1@2.0.jar"), "m1");
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+        try {
+            finder.find("m1");
+            assertTrue(false);
+        } catch (FindException expected) { }
+
+        finder = ModuleFinder.of(dir);
+        try {
+            finder.findAll();
+            assertTrue(false);
+        } catch (FindException expected) { }
+    }
+
+
+    /**
+     * Test ModuleFinder.of with a truncated module-info.class
+     */
+    public void testOfWithTruncatedModuleInfo() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+
+        // create an empty <dir>/rhubarb/module-info.class
+        Path subdir = Files.createDirectory(dir.resolve("rhubarb"));
+        Files.createFile(subdir.resolve("module-info.class"));
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+        try {
+            finder.find("rhubarb");
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+
+        finder = ModuleFinder.of(dir);
+        try {
+            finder.findAll();
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+    }
+
+
+    /**
+     * Test ModuleFinder.compose
+     */
+    public void testCompose() throws Exception {
+        Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
+        createExplodedModule(dir1.resolve("m1"), "m1@1.0");
+        createExplodedModule(dir1.resolve("m2"), "m2@1.0");
+
+        Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
+        createExplodedModule(dir2.resolve("m1"), "m1@2.0");
+        createExplodedModule(dir2.resolve("m2"), "m2@2.0");
+        createExplodedModule(dir2.resolve("m3"), "m3");
+        createExplodedModule(dir2.resolve("m4"), "m4");
+
+        ModuleFinder finder1 = ModuleFinder.of(dir1);
+        ModuleFinder finder2 = ModuleFinder.of(dir2);
+
+        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
+        assertTrue(finder.findAll().size() == 4);
+        assertTrue(finder.find("m1").isPresent());
+        assertTrue(finder.find("m2").isPresent());
+        assertTrue(finder.find("m3").isPresent());
+        assertTrue(finder.find("m4").isPresent());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+
+        // check that m1@1.0 (and not m1@2.0) is found
+        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertEquals(m1.version().get().toString(), "1.0");
+
+        // check that m2@1.0 (and not m2@2.0) is found
+        ModuleDescriptor m2 = finder.find("m2").get().descriptor();
+        assertEquals(m2.version().get().toString(), "1.0");
+    }
+
+
+    /**
+     * Test ModuleFinder.empty
+     */
+    public void testEmpty() {
+        ModuleFinder finder = ModuleFinder.empty();
+        assertTrue(finder.findAll().isEmpty());
+        assertFalse(finder.find("java.rhubarb").isPresent());
+    }
+
+
+    /**
+     * Test null handling
+     */
+    public void testNulls() {
+
+        try {
+            ModuleFinder.ofSystem().find(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            ModuleFinder.of().find(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            ModuleFinder.empty().find(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            ModuleFinder.of((Path[])null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            ModuleFinder.of((Path)null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        // compose
+        ModuleFinder finder = ModuleFinder.of();
+        try {
+            ModuleFinder.compose(finder, null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+        try {
+            ModuleFinder.compose(null, finder);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+    }
+
+
+    /**
+     * Parses a string of the form {@code name[@version]} and returns a
+     * ModuleDescriptor with that name and version. The ModuleDescriptor
+     * will have a requires on java.base.
+     */
+    static ModuleDescriptor newModuleDescriptor(String mid) {
+        String mn;
+        String vs;
+        int i = mid.indexOf("@");
+        if (i == -1) {
+            mn = mid;
+            vs = null;
+        } else {
+            mn = mid.substring(0, i);
+            vs = mid.substring(i+1);
+        }
+        ModuleDescriptor.Builder builder
+                = new ModuleDescriptor.Builder(mn).requires("java.base");
+        if (vs != null)
+            builder.version(vs);
+        return builder.build();
+    }
+
+    /**
+     * Creates an exploded module in the given directory and containing a
+     * module descriptor with the given module name/version.
+     */
+    static Path createExplodedModule(Path dir, String mid) throws Exception {
+        ModuleDescriptor descriptor = newModuleDescriptor(mid);
+        Files.createDirectories(dir);
+        Path mi = dir.resolve("module-info.class");
+        try (OutputStream out = Files.newOutputStream(mi)) {
+            ModuleInfoWriter.write(descriptor, out);
+        }
+        return dir;
+    }
+
+    /**
+     * Creates a JAR file with the given file path and containing a module
+     * descriptor with the given module name/version.
+     */
+    static Path createModularJar(Path file, String mid, String ... entries)
+        throws Exception
+    {
+        ModuleDescriptor descriptor = newModuleDescriptor(mid);
+        try (OutputStream out = Files.newOutputStream(file)) {
+            try (JarOutputStream jos = new JarOutputStream(out)) {
+
+                JarEntry je = new JarEntry("module-info.class");
+                jos.putNextEntry(je);
+                ModuleInfoWriter.write(descriptor, jos);
+                jos.closeEntry();
+
+                for (String entry : entries) {
+                    je = new JarEntry(entry);
+                    jos.putNextEntry(je);
+                    jos.closeEntry();
+                }
+            }
+
+        }
+        return file;
+    }
+
+}
+
diff --git a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java
new file mode 100644
index 0000000..ecaf6f4
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @library /lib/testlibrary
+ * @modules java.base/jdk.internal.module
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build ModuleReaderTest CompilerUtils JarUtils
+ * @run testng ModuleReaderTest
+ * @summary Basic tests for java.lang.module.ModuleReader
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Optional;
+
+import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.ConfigurableModuleFinder.Phase;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModuleReaderTest {
+
+    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, "src");
+    private static final Path MODS_DIR   = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE = "m";
+
+    // resources in test module (can't use module-info.class as a test
+    // resource as it will be modified by the jmod tool)
+    private static final String[] RESOURCES = {
+        "p/Main.class"
+    };
+
+    // a resource that is not in the test module
+    private static final String NOT_A_RESOURCE = "NotAResource";
+
+
+    @BeforeTest
+    public void compileTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                                    MODS_DIR.resolve(TEST_MODULE));
+        assertTrue(compiled, "test module did not compile");
+    }
+
+
+    /**
+     * Test exploded module
+     */
+    public void testExplodedModule() throws Exception {
+        test(MODS_DIR);
+    }
+
+
+    /**
+     * Test modular JAR
+     */
+    public void testModularJar() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
+
+        // jar cf mlib/${TESTMODULE}.jar -C mods .
+        JarUtils.createJarFile(dir.resolve("m.jar"),
+                               MODS_DIR.resolve(TEST_MODULE));
+
+        test(dir);
+    }
+
+
+    /**
+     * Test JMOD
+     */
+    public void testJMod() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
+
+        // jmod create --class-path mods/${TESTMODULE}  mlib/${TESTMODULE}.jmod
+        String cp = MODS_DIR.resolve(TEST_MODULE).toString();
+        String jmod = dir.resolve("m.jmod").toString();
+        String[] args = { "create", "--class-path", cp, jmod };
+        jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask();
+        assertEquals(task.run(args), 0);
+
+        test(dir);
+    }
+
+
+    /**
+     * The test module is found on the given module path. Open a ModuleReader
+     * to the test module and test the reader.
+     */
+    void test(Path mp) throws Exception {
+
+        ModuleFinder finder = ModuleFinder.of(mp);
+        if (finder instanceof ConfigurableModuleFinder) {
+            // need ModuleFinder to be in the phase to find JMOD files
+            ((ConfigurableModuleFinder)finder).configurePhase(Phase.LINK_TIME);
+        }
+
+        ModuleReference mref = finder.find(TEST_MODULE).get();
+        ModuleReader reader = mref.open();
+
+        try (reader) {
+
+            // test each of the known resources in the module
+            for (String name : RESOURCES) {
+                byte[] expectedBytes
+                    = Files.readAllBytes(MODS_DIR
+                        .resolve(TEST_MODULE)
+                        .resolve(name.replace('/', File.separatorChar)));
+
+                testFind(reader, name, expectedBytes);
+                testOpen(reader, name, expectedBytes);
+                testRead(reader, name, expectedBytes);
+            }
+
+            // test "not found"
+            assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
+            assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
+
+            // test nulls
+            try {
+                reader.find(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.open(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.read(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            // should release(null) throw NPE?
+
+        }
+
+        // test closed ModuleReader
+        try {
+            reader.open(RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+
+
+        try {
+            reader.read(RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+    }
+
+    /**
+     * Test ModuleReader#find
+     */
+    void testFind(ModuleReader reader, String name, byte[] expectedBytes)
+        throws Exception
+    {
+        Optional<URI> ouri = reader.find(name);
+        assertTrue(ouri.isPresent());
+
+        URL url = ouri.get().toURL();
+        if (!url.getProtocol().equalsIgnoreCase("jmod")) {
+            URLConnection uc = url.openConnection();
+            uc.setUseCaches(false);
+            try (InputStream in = uc.getInputStream()) {
+                byte[] bytes = in.readAllBytes();
+                assertTrue(Arrays.equals(bytes, expectedBytes));
+            }
+        }
+    }
+
+    /**
+     * Test ModuleReader#open
+     */
+    void testOpen(ModuleReader reader, String name, byte[] expectedBytes)
+        throws Exception
+    {
+        Optional<InputStream> oin = reader.open(name);
+        assertTrue(oin.isPresent());
+
+        InputStream in = oin.get();
+        try (in) {
+            byte[] bytes = in.readAllBytes();
+            assertTrue(Arrays.equals(bytes, expectedBytes));
+        }
+    }
+
+    /**
+     * Test ModuleReader#read
+     */
+    void testRead(ModuleReader reader, String name, byte[] expectedBytes)
+        throws Exception
+    {
+        Optional<ByteBuffer> obb = reader.read(name);
+        assertTrue(obb.isPresent());
+
+        ByteBuffer bb = obb.get();
+        try {
+            int rem = bb.remaining();
+            assertTrue(rem == expectedBytes.length);
+            byte[] bytes = new byte[rem];
+            bb.get(bytes);
+            assertTrue(Arrays.equals(bytes, expectedBytes));
+        } finally {
+            reader.release(bb);
+        }
+    }
+
+}
diff --git a/jdk/test/java/lang/module/ModuleReader/src/m/module-info.java b/jdk/test/java/lang/module/ModuleReader/src/m/module-info.java
new file mode 100644
index 0000000..cf46bcc
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleReader/src/m/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 m {
+}
diff --git a/jdk/test/java/lang/module/ModuleReader/src/m/p/Main.java b/jdk/test/java/lang/module/ModuleReader/src/m/p/Main.java
new file mode 100644
index 0000000..b0be05f
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleReader/src/m/p/Main.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * Main class for dummy module.
+ */
+
+public class Main {
+    public static void main(String[] args) {
+    }
+}
diff --git a/jdk/test/java/lang/module/ModuleReferenceTest.java b/jdk/test/java/lang/module/ModuleReferenceTest.java
new file mode 100644
index 0000000..25b9277
--- /dev/null
+++ b/jdk/test/java/lang/module/ModuleReferenceTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @run testng ModuleReferenceTest
+ * @summary Basic tests for java.lang.module.ModuleReference
+ */
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModuleReferenceTest {
+
+    private Supplier<ModuleReader> makeSupplier() {
+        return () -> { throw new UnsupportedOperationException(); };
+    }
+
+    public void testBasic() throws Exception {
+        ModuleDescriptor descriptor
+            = new ModuleDescriptor.Builder("m")
+                .exports("p")
+                .exports("q")
+                .conceals("p.internal")
+                .build();
+
+        URI uri = URI.create("module:/m");
+
+        Supplier<ModuleReader> supplier = makeSupplier();
+
+        ModuleReference mref = new ModuleReference(descriptor, uri, supplier);
+
+        assertTrue(mref.descriptor().equals(descriptor));
+        assertTrue(mref.location().get().equals(uri));
+
+        // check that the supplier is called
+        try {
+            mref.open();
+            assertTrue(false);
+        } catch (UnsupportedOperationException expected) { }
+    }
+
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testNullDescriptor() throws Exception {
+        URI location = URI.create("module:/m");
+        new ModuleReference(null, location, makeSupplier());
+    }
+
+    public void testNullLocation() {
+        ModuleDescriptor descriptor
+            = new ModuleDescriptor.Builder("m")
+                .exports("p")
+                .build();
+        Supplier<ModuleReader> supplier = makeSupplier();
+        ModuleReference mref = new ModuleReference(descriptor, null, supplier);
+        assertTrue(!mref.location().isPresent());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testNullSupplier() throws Exception {
+        ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m").build();
+        URI location = URI.create("module:/m");
+        new ModuleReference(descriptor, location, null);
+    }
+
+
+    public void testEqualsAndHashCode() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .build();
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m1")
+                .exports("p")
+                .build();
+
+        URI uri = URI.create("module:/m1");
+        Supplier<ModuleReader> supplier = makeSupplier();
+
+        ModuleReference mref1 = new ModuleReference(descriptor1, uri, supplier);
+        ModuleReference mref2 = new ModuleReference(descriptor2, uri, supplier);
+        ModuleReference mref3 = new ModuleReference(descriptor1, null, supplier);
+
+        assertTrue(mref1.equals(mref1));
+        assertTrue(mref1.equals(mref1));
+        assertTrue(mref2.equals(mref1));
+        assertTrue(mref1.hashCode() == mref2.hashCode());
+
+        assertTrue(mref3.equals(mref3));
+        assertFalse(mref3.equals(mref1));
+        assertFalse(mref1.equals(mref3));
+    }
+
+
+    public void testToString() {
+        ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1").build();
+        URI uri = URI.create("module:/m1");
+        Supplier<ModuleReader> supplier = makeSupplier();
+        ModuleReference mref = new ModuleReference(descriptor, uri, supplier);
+        String s = mref.toString();
+        assertTrue(s.contains("m1"));
+        assertTrue(s.contains(uri.toString()));
+    }
+
+}
diff --git a/jdk/test/java/lang/module/VersionTest.java b/jdk/test/java/lang/module/VersionTest.java
new file mode 100644
index 0000000..41d4530
--- /dev/null
+++ b/jdk/test/java/lang/module/VersionTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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
+ * @run testng VersionTest
+ * @summary Basic tests for java.lang.module.ModuleDescriptor.Version.
+ */
+
+import java.lang.module.ModuleDescriptor.Version;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+@Test
+public class VersionTest {
+
+    // valid version strings
+    @DataProvider(name = "validVersions")
+    public Object[][] validVersions() {
+        return new Object[][]{
+
+            { "1.0",            null },
+            { "1.0.0",          null },
+            { "1.0.0.0",        null },
+
+            { "99",             null },
+            { "99.99",          null },
+            { "99.99.99",       null },
+
+            { "1-SNAPSHOT",     null },
+            { "1.0-SNAPSHOT",   null },
+            { "1.0.0-SNAPSHOT", null },
+
+            { "9-ea",           null },
+            { "9-ea+110",       null },
+            { "9.3.2.1+42-8839942", null}
+
+        };
+    }
+
+    // invalid version strings
+    @DataProvider(name = "invalidVersions")
+    public Object[][] invalidVersions() {
+        return new Object[][]{
+
+            { null,            null },
+            { "",              null },
+            { "A1",            null },  // does not start with number
+            { "1.0-",          null },  // empty branch
+
+        };
+    }
+
+    // Test parsing valid version strings
+    @Test(dataProvider = "validVersions")
+    public void testParseValidVersions(String vs, String ignore) {
+        Version v = Version.parse(vs);
+        assertEquals(v.toString(), vs);
+    }
+
+    // Test parsing an invalid version strings
+    @Test(dataProvider = "invalidVersions",
+          expectedExceptions = IllegalArgumentException.class )
+    public void testParseInvalidVersions(String vs, String ignore) {
+        Version.parse(vs);
+    }
+
+    // Test equals and hashCode
+    @Test(dataProvider = "validVersions")
+    public void testEqualsAndHashCode(String vs, String ignore) {
+
+        Version v1 = Version.parse(vs);
+        Version v2 = Version.parse(vs);
+        assertEquals(v1, v2);
+        assertEquals(v2, v1);
+        assertEquals(v1.hashCode(), v2.hashCode());
+
+        Version v3 = Version.parse("1.0-rhubarb");
+        assertNotEquals(v1, v3);
+        assertNotEquals(v2, v3);
+        assertNotEquals(v3, v1);
+        assertNotEquals(v3, v2);
+
+    }
+
+    // ordered version strings
+    @DataProvider(name = "orderedVersions")
+    public Object[][] orderedVersions() {
+        return new Object[][]{
+
+            { "1.0",     "2.0" },
+            { "1.0-SNAPSHOT", "1.0" },
+            { "1.0-SNAPSHOT2", "1.0" },
+            { "1.2.3-ea", "1.2.3" },
+            { "1.2.3-ea+104", "1.2.3-ea+105" },
+            { "1.2.3-ea+104-4084552", "1.2.3-ea+104-4084552+8849330" },
+            { "1+104", "1+105" },
+            { "1.0-alpha1", "1.0-alpha2" }
+
+        };
+    }
+
+    /**
+     * Test compareTo with ordered versions.
+     */
+    @Test(dataProvider = "orderedVersions")
+    public void testCompareOrderedVersions(String vs1, String vs2) {
+
+        Version v1 = Version.parse(vs1);
+        assertTrue(v1.compareTo(v1) == 0);
+
+        Version v2 = Version.parse(vs2);
+        assertTrue(v2.compareTo(v2) == 0);
+
+        // v1 < v2
+        assertTrue(v1.compareTo(v2) < 0);
+        assertTrue(v2.compareTo(v1) > 0);
+
+    }
+
+    // equal version strings
+    @DataProvider(name = "equalVersions")
+    public Object[][] equalVersions() {
+        return new Object[][]{
+
+            { "1",             "1.0.0" },
+            { "1.0",           "1.0.0" },
+            { "1.0-beta",      "1.0.0-beta" },
+
+        };
+    }
+
+    /**
+     * Test compareTo with equal versions.
+     */
+    @Test(dataProvider = "equalVersions")
+    public void testCompareEqualsVersions(String vs1, String vs2) {
+
+        Version v1 = Version.parse(vs1);
+        assertTrue(v1.compareTo(v1) == 0);
+
+        Version v2 = Version.parse(vs2);
+        assertTrue(v2.compareTo(v2) == 0);
+
+        assertTrue(v1.compareTo(v2) == 0);
+        assertTrue(v2.compareTo(v1) == 0);
+        assertEquals(v1, v2);
+        assertEquals(v2, v1);
+
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
new file mode 100644
index 0000000..17d8c19
--- /dev/null
+++ b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @build ModuleSetAccessibleTest
+ * @modules java.base/sun.misc
+ * @run testng ModuleSetAccessibleTest
+ * @summary Test java.lang.reflect.AccessibleObject with modules
+ */
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InaccessibleObjectException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+
+import sun.misc.Unsafe;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ModuleSetAccessibleTest {
+
+    /**
+     * Invoke a private constructor on a public class in an exported package
+     */
+    public void testPrivateConstructorInExportedPackage() throws Exception {
+        Constructor<?> ctor = Unsafe.class.getDeclaredConstructor();
+
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        ctor.setAccessible(true);
+        Unsafe unsafe = (Unsafe) ctor.newInstance();
+    }
+
+
+    /**
+     * Invoke a private method on a public class in an exported package
+     */
+    public void testPrivateMethodInExportedPackage() throws Exception {
+        Method m = Unsafe.class.getDeclaredMethod("throwIllegalAccessError");
+        try {
+            m.invoke(null);
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        m.setAccessible(true);
+        try {
+            m.invoke(null);
+            assertTrue(false);
+        } catch (InvocationTargetException e) {
+            // thrown by throwIllegalAccessError
+            assertTrue(e.getCause() instanceof IllegalAccessError);
+        }
+    }
+
+
+    /**
+     * Access a private field in a public class that is an exported package
+     */
+    public void testPrivateFieldInExportedPackage() throws Exception {
+        Field f = Unsafe.class.getDeclaredField("theUnsafe");
+
+        try {
+            f.get(null);
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        f.setAccessible(true);
+        Unsafe unsafe = (Unsafe) f.get(null);
+    }
+
+
+    /**
+     * Invoke a public constructor on a public class in a non-exported package
+     */
+    public void testPublicConstructorInNonExportedPackage() throws Exception {
+        Class<?> clazz = Class.forName("sun.security.x509.X500Name");
+        Constructor<?> ctor = clazz.getConstructor(String.class);
+
+        try {
+            ctor.newInstance("cn=duke");
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        try {
+            ctor.setAccessible(true);
+            assertTrue(false);
+        } catch (InaccessibleObjectException expected) { }
+
+        ctor.setAccessible(false); // should succeed
+    }
+
+
+    /**
+     * Access a public field in a public class that in a non-exported package
+     */
+    public void testPublicFieldInNonExportedPackage() throws Exception {
+        Class<?> clazz = Class.forName("sun.security.x509.X500Name");
+        Field f = clazz.getField("SERIALNUMBER_OID");
+
+        try {
+            f.get(null);
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        try {
+            f.setAccessible(true);
+            assertTrue(false);
+        } catch (InaccessibleObjectException expected) { }
+
+        f.setAccessible(false); // should succeed
+    }
+
+
+    /**
+     * 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 {
+
+        // non-public constructor
+        Constructor<?> ctor
+            = Class.class.getDeclaredConstructor(ClassLoader.class, Class.class);
+        AccessibleObject[] ctors = { ctor };
+
+        try {
+            ctor.setAccessible(true);
+            assertTrue(false);
+        } catch (SecurityException expected) { }
+
+        try {
+            AccessibleObject.setAccessible(ctors, true);
+            assertTrue(false);
+        } catch (SecurityException expected) { }
+
+        // should succeed
+        ctor.setAccessible(false);
+        AccessibleObject.setAccessible(ctors, false);
+
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java
new file mode 100644
index 0000000..f54a320
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java
@@ -0,0 +1,867 @@
+/*
+ * 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
+ * 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 BasicLayerTest ModuleUtils
+ * @compile layertest/Test.java
+ * @run testng BasicLayerTest
+ * @summary Basic tests for java.lang.reflect.Layer
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import static java.lang.module.ModuleFinder.empty;
+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.Set;
+import java.util.stream.Collectors;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class BasicLayerTest {
+
+    /**
+     * Exercise Layer.empty()
+     */
+    public void testEmpty() {
+        Layer emptyLayer = Layer.empty();
+
+        assertFalse(emptyLayer.parent().isPresent());
+
+        assertTrue(emptyLayer.configuration() == Configuration.empty());
+
+        assertTrue(emptyLayer.modules().isEmpty());
+
+        assertFalse(emptyLayer.findModule("java.base").isPresent());
+
+        try {
+            emptyLayer.findLoader("java.base");
+            assertTrue(false);
+        } catch (IllegalArgumentException expected) { }
+    }
+
+
+    /**
+     * Exercise Layer.boot()
+     */
+    public void testBoot() {
+        Layer bootLayer = Layer.boot();
+
+        // configuration
+        Configuration cf = bootLayer.configuration();
+        assertTrue(cf.findModule("java.base").get()
+                .reference()
+                .descriptor()
+                .exports()
+                .stream().anyMatch(e -> (e.source().equals("java.lang")
+                                         && !e.isQualified())));
+
+        // modules
+        Set<Module> modules = bootLayer.modules();
+        assertTrue(modules.contains(Object.class.getModule()));
+        int count = (int) modules.stream().map(Module::getName).count();
+        assertEquals(count, modules.size()); // module names are unique
+
+        // findModule
+        Module base = Object.class.getModule();
+        assertTrue(bootLayer.findModule("java.base").get() == base);
+        assertTrue(base.getLayer() == bootLayer);
+
+        // findLoader
+        assertTrue(bootLayer.findLoader("java.base") == null);
+
+        // parent
+        assertTrue(bootLayer.parent().get() == Layer.empty());
+    }
+
+
+    /**
+     * Exercise Layer.create, created on an empty layer
+     */
+    public void testLayerOnEmpty() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .exports("p1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("m3")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        // map each module to its own class loader for this test
+        ClassLoader loader1 = new ClassLoader() { };
+        ClassLoader loader2 = new ClassLoader() { };
+        ClassLoader loader3 = new ClassLoader() { };
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", loader1);
+        map.put("m2", loader2);
+        map.put("m3", loader3);
+
+        Layer layer = Layer.empty().defineModules(cf, map::get);
+
+        // configuration
+        assertTrue(layer.configuration() == cf);
+        assertTrue(layer.configuration().modules().size() == 3);
+
+        // modules
+        Set<Module> modules = layer.modules();
+        assertTrue(modules.size() == 3);
+        Set<String> names = modules.stream()
+            .map(Module::getName)
+            .collect(Collectors.toSet());
+        assertTrue(names.contains("m1"));
+        assertTrue(names.contains("m2"));
+        assertTrue(names.contains("m3"));
+
+        // findModule
+        Module m1 = layer.findModule("m1").get();
+        Module m2 = layer.findModule("m2").get();
+        Module m3 = layer.findModule("m3").get();
+        assertEquals(m1.getName(), "m1");
+        assertEquals(m2.getName(), "m2");
+        assertEquals(m3.getName(), "m3");
+        assertTrue(m1.getDescriptor() == descriptor1);
+        assertTrue(m2.getDescriptor() == descriptor2);
+        assertTrue(m3.getDescriptor() == descriptor3);
+        assertTrue(m1.getLayer() == layer);
+        assertTrue(m2.getLayer() == layer);
+        assertTrue(m3.getLayer() == layer);
+        assertTrue(modules.contains(m1));
+        assertTrue(modules.contains(m2));
+        assertTrue(modules.contains(m3));
+        assertFalse(layer.findModule("godot").isPresent());
+
+        // findLoader
+        assertTrue(layer.findLoader("m1") == loader1);
+        assertTrue(layer.findLoader("m2") == loader2);
+        assertTrue(layer.findLoader("m3") == loader3);
+        try {
+            ClassLoader loader = layer.findLoader("godot");
+            assertTrue(false);
+        } catch (IllegalArgumentException ignore) { }
+
+        // parent
+        assertTrue(layer.parent().get() == Layer.empty());
+    }
+
+
+    /**
+     * Exercise Layer.create, created over the boot layer
+     */
+    public void testLayerOnBoot() {
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .requires("java.base")
+                .exports("p1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires("java.base")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = resolveRequires(parent, finder, "m1");
+
+        ClassLoader loader = new ClassLoader() { };
+
+        Layer layer = Layer.boot().defineModules(cf, mn -> loader);
+
+        // configuration
+        assertTrue(layer.configuration() == cf);
+        assertTrue(layer.configuration().modules().size() == 2);
+
+        // modules
+        Set<Module> modules = layer.modules();
+        assertTrue(modules.size() == 2);
+        Set<String> names = modules.stream()
+            .map(Module::getName)
+            .collect(Collectors.toSet());
+        assertTrue(names.contains("m1"));
+        assertTrue(names.contains("m2"));
+
+        // findModule
+        Module m1 = layer.findModule("m1").get();
+        Module m2 = layer.findModule("m2").get();
+        assertEquals(m1.getName(), "m1");
+        assertEquals(m2.getName(), "m2");
+        assertTrue(m1.getDescriptor() == descriptor1);
+        assertTrue(m2.getDescriptor() == descriptor2);
+        assertTrue(m1.getLayer() == layer);
+        assertTrue(m2.getLayer() == layer);
+        assertTrue(modules.contains(m1));
+        assertTrue(modules.contains(m2));
+        assertTrue(layer.findModule("java.base").get() == Object.class.getModule());
+        assertFalse(layer.findModule("godot").isPresent());
+
+        // findLoader
+        assertTrue(layer.findLoader("m1") == loader);
+        assertTrue(layer.findLoader("m2") == loader);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // parent
+        assertTrue(layer.parent().get() == Layer.boot());
+    }
+
+
+    /**
+     * Layer.create with a configuration of two modules that have the same
+     * module-private package.
+     */
+    public void testSameConcealedPackage() {
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .conceals("p")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .conceals("p")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequires(finder, "m1");
+        assertTrue(cf.modules().size() == 2);
+
+        // one loader per module, should be okay
+        Layer.empty().defineModules(cf, mn -> new ClassLoader() { });
+
+        // same class loader
+        try {
+            ClassLoader loader = new ClassLoader() { };
+            Layer.empty().defineModules(cf, mn -> loader);
+            assertTrue(false);
+        } catch (LayerInstantiationException expected) { }
+    }
+
+
+    /**
+     * Layer.create with a configuration with a partitioned graph. The same
+     * package is exported in both partitions.
+     */
+    public void testSameExportInPartitionedGraph() {
+
+        // m1 reads m2, m2 exports p to m1
+        ModuleDescriptor descriptor1
+            =  new ModuleDescriptor.Builder("m1")
+                .requires("m2")
+                .build();
+        ModuleDescriptor descriptor2
+            =  new ModuleDescriptor.Builder("m2")
+                .exports("p", "m1")
+                .build();
+
+        // m3 reads m4, m4 exports p to m3
+        ModuleDescriptor descriptor3
+            =  new ModuleDescriptor.Builder("m3")
+                .requires("m4")
+                .build();
+        ModuleDescriptor descriptor4
+            =  new ModuleDescriptor.Builder("m4")
+                .exports("p", "m3")
+                .build();
+
+        ModuleFinder finder
+            = ModuleUtils.finderOf(descriptor1,
+                                   descriptor2,
+                                   descriptor3,
+                                   descriptor4);
+
+        Configuration cf = resolveRequires(finder, "m1", "m3");
+        assertTrue(cf.modules().size() == 4);
+
+        // one loader per module
+        Layer.empty().defineModules(cf, mn -> new ClassLoader() { });
+
+        // m1 & m2 in one loader, m3 & m4 in another loader
+        ClassLoader loader1 = new ClassLoader() { };
+        ClassLoader loader2 = new ClassLoader() { };
+        Map<String, ClassLoader> map = new HashMap<>();
+        map.put("m1", loader1);
+        map.put("m2", loader1);
+        map.put("m3", loader2);
+        map.put("m3", loader2);
+        Layer.empty().defineModules(cf, map::get);
+
+        // same loader
+        try {
+            ClassLoader loader = new ClassLoader() { };
+            Layer.empty().defineModules(cf, mn -> loader);
+            assertTrue(false);
+        } catch (LayerInstantiationException expected) { }
+    }
+
+
+    /**
+     * Layer.create 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.
+     */
+    public void testConcealSamePackageAsBootLayer() {
+
+        // check assumption that java.base contains sun.launcher
+        ModuleDescriptor base = Object.class.getModule().getDescriptor();
+        assertTrue(base.conceals().contains("sun.launcher"));
+
+        ModuleDescriptor descriptor
+            = new ModuleDescriptor.Builder("m1")
+               .requires("java.base")
+               .conceals("sun.launcher")
+               .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m1"));
+        assertTrue(cf.modules().size() == 1);
+
+        ClassLoader loader = new ClassLoader() { };
+        Layer layer = Layer.boot().defineModules(cf, mn -> loader);
+        assertTrue(layer.modules().size() == 1);
+   }
+
+
+    /**
+     * Test layers with implied readability.
+     *
+     * The test consists of three configurations:
+     * - Configuration/layer1: m1, m2 requires public m1
+     * - Configuration/layer2: m3 requires m1
+     */
+    public void testImpliedReadabilityWithLayers1() {
+
+        // cf1: m1 and m2, m2 requires public m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf1 = resolveRequires(finder1, "m2");
+
+        ClassLoader cl1 = new ClassLoader() { };
+        Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
+
+
+        // cf2: m3, m3 requires m2
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        ClassLoader cl2 = new ClassLoader() { };
+        Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
+
+        assertTrue(layer1.parent().get() == Layer.empty());
+        assertTrue(layer2.parent().get() == layer1);
+
+        Module m1 = layer2.findModule("m1").get();
+        Module m2 = layer2.findModule("m2").get();
+        Module m3 = layer2.findModule("m3").get();
+
+        assertTrue(m1.getLayer() == layer1);
+        assertTrue(m2.getLayer() == layer1);
+        assertTrue(m3.getLayer() == layer2);
+
+        assertTrue(m1.getClassLoader() == cl1);
+        assertTrue(m2.getClassLoader() == cl1);
+        assertTrue(m3.getClassLoader() == cl2);
+
+        assertTrue(m1.canRead(m1));
+        assertFalse(m1.canRead(m2));
+        assertFalse(m1.canRead(m3));
+
+        assertTrue(m2.canRead(m1));
+        assertTrue(m2.canRead(m2));
+        assertFalse(m2.canRead(m3));
+
+        assertTrue(m3.canRead(m1));
+        assertTrue(m3.canRead(m2));
+        assertTrue(m3.canRead(m3));
+    }
+
+
+    /**
+     * Test layers with implied readability.
+     *
+     * The test consists of three configurations:
+     * - Configuration/layer1: m1
+     * - Configuration/layer2: m2 requires public m3, m3 requires m2
+     */
+    public void testImpliedReadabilityWithLayers2() {
+
+        // cf1: m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        ClassLoader cl1 = new ClassLoader() { };
+        Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
+
+
+        // cf2: m2, m3: m2 requires public m1, m3 requires m2
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2, descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        ClassLoader cl2 = new ClassLoader() { };
+        Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
+
+        assertTrue(layer1.parent().get() == Layer.empty());
+        assertTrue(layer2.parent().get() == layer1);
+
+        Module m1 = layer2.findModule("m1").get();
+        Module m2 = layer2.findModule("m2").get();
+        Module m3 = layer2.findModule("m3").get();
+
+        assertTrue(m1.getLayer() == layer1);
+        assertTrue(m2.getLayer() == layer2);
+        assertTrue(m3.getLayer() == layer2);
+
+        assertTrue(m1.canRead(m1));
+        assertFalse(m1.canRead(m2));
+        assertFalse(m1.canRead(m3));
+
+        assertTrue(m2.canRead(m1));
+        assertTrue(m2.canRead(m2));
+        assertFalse(m2.canRead(m3));
+
+        assertTrue(m3.canRead(m1));
+        assertTrue(m3.canRead(m2));
+        assertTrue(m3.canRead(m3));
+    }
+
+
+    /**
+     * Test layers with implied readability.
+     *
+     * The test consists of three configurations:
+     * - Configuration/layer1: m1
+     * - Configuration/layer2: m2 requires public m1
+     * - Configuration/layer3: m3 requires m1
+     */
+    public void testImpliedReadabilityWithLayers3() {
+
+        // cf1: m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        ClassLoader cl1 = new ClassLoader() { };
+        Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
+
+
+        // cf2: m2 requires public m1
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m2");
+
+        ClassLoader cl2 = new ClassLoader() { };
+        Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
+
+
+        // cf3: m3 requires m2
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder3 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf3 = resolveRequires(cf2, finder3, "m3");
+
+        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);
+
+        Module m1 = layer3.findModule("m1").get();
+        Module m2 = layer3.findModule("m2").get();
+        Module m3 = layer3.findModule("m3").get();
+
+        assertTrue(m1.getLayer() == layer1);
+        assertTrue(m2.getLayer() == layer2);
+        assertTrue(m3.getLayer() == layer3);
+
+        assertTrue(m1.canRead(m1));
+        assertFalse(m1.canRead(m2));
+        assertFalse(m1.canRead(m3));
+
+        assertTrue(m2.canRead(m1));
+        assertTrue(m2.canRead(m2));
+        assertFalse(m2.canRead(m3));
+
+        assertTrue(m3.canRead(m1));
+        assertTrue(m3.canRead(m2));
+        assertTrue(m3.canRead(m3));
+    }
+
+
+    /**
+     * 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
+     */
+    public void testImpliedReadabilityWithLayers4() {
+
+        // cf1: m1, m2 requires public m1
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2")
+                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf1 = resolveRequires(finder1, "m2");
+
+        ClassLoader cl1 = new ClassLoader() { };
+        Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
+
+
+        // cf2: m3 requires public m2, m4 requires m3
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3")
+                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m2")
+                .build();
+
+        ModuleDescriptor descriptor4
+            = new ModuleDescriptor.Builder("m4")
+                .requires("m3")
+                .build();
+
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3", "m4");
+
+        ClassLoader cl2 = new ClassLoader() { };
+        Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
+
+        assertTrue(layer1.parent().get() == Layer.empty());
+        assertTrue(layer2.parent().get() == layer1);
+
+        Module m1 = layer2.findModule("m1").get();
+        Module m2 = layer2.findModule("m2").get();
+        Module m3 = layer2.findModule("m3").get();
+        Module m4 = layer2.findModule("m4").get();
+
+        assertTrue(m1.getLayer() == layer1);
+        assertTrue(m2.getLayer() == layer1);
+        assertTrue(m3.getLayer() == layer2);
+        assertTrue(m4.getLayer() == layer2);
+
+        assertTrue(m1.canRead(m1));
+        assertFalse(m1.canRead(m2));
+        assertFalse(m1.canRead(m3));
+        assertFalse(m1.canRead(m4));
+
+        assertTrue(m2.canRead(m1));
+        assertTrue(m2.canRead(m2));
+        assertFalse(m1.canRead(m3));
+        assertFalse(m1.canRead(m4));
+
+        assertTrue(m3.canRead(m1));
+        assertTrue(m3.canRead(m2));
+        assertTrue(m3.canRead(m3));
+        assertFalse(m3.canRead(m4));
+
+        assertTrue(m4.canRead(m1));
+        assertTrue(m4.canRead(m2));
+        assertTrue(m4.canRead(m3));
+        assertTrue(m4.canRead(m4));
+    }
+
+
+    /**
+     * Attempt to use Layer.create to create a layer with a module defined to a
+     * class loader that already has a module of the same name defined to the
+     * class loader.
+     */
+    @Test(expectedExceptions = { LayerInstantiationException.class })
+    public void testModuleAlreadyDefinedToLoader() {
+
+        ModuleDescriptor md
+            = new ModuleDescriptor.Builder("m")
+                .requires("java.base")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(md);
+
+        Configuration parent = Layer.boot().configuration();
+
+        Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m"));
+
+        ClassLoader loader = new ClassLoader() { };
+
+        Layer.boot().defineModules(cf, mn -> loader);
+
+        // should throw LayerInstantiationException as m1 already defined to loader
+        Layer.boot().defineModules(cf, mn -> loader);
+
+    }
+
+
+    /**
+     * Attempt to use Layer.create to create a Layer with a module containing
+     * package {@code p} where the class loader already has a module defined
+     * to it containing package {@code p}.
+     */
+    @Test(expectedExceptions = { LayerInstantiationException.class })
+    public void testPackageAlreadyInNamedModule() {
+
+        ModuleDescriptor md1
+            = new ModuleDescriptor.Builder("m1")
+                .conceals("p")
+                .requires("java.base")
+                .build();
+
+        ModuleDescriptor md2
+            = new ModuleDescriptor.Builder("m2")
+                .conceals("p")
+                .requires("java.base")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(md1, md2);
+
+        ClassLoader loader = new ClassLoader() { };
+
+        // define m1 containing package p to class loader
+
+        Configuration parent = Layer.boot().configuration();
+
+        Configuration cf1 = parent.resolveRequires(finder, empty(), Set.of("m1"));
+
+        Layer layer1 = Layer.boot().defineModules(cf1, mn -> loader);
+
+        // attempt to define m2 containing package p to class loader
+
+        Configuration cf2 = parent.resolveRequires(finder, empty(), Set.of("m2"));
+
+        // should throw exception because p already in m1
+        Layer layer2 = Layer.boot().defineModules(cf2, mn -> loader);
+
+    }
+
+
+    /**
+     * Attempt to use Layer.create to create a Layer with a module containing
+     * a package in which a type is already loaded by the class loader.
+     */
+    @Test(expectedExceptions = { LayerInstantiationException.class })
+    public void testPackageAlreadyInUnnamedModule() throws Exception {
+
+        Class<?> c = layertest.Test.class;
+        assertFalse(c.getModule().isNamed());  // in unnamed module
+
+        ModuleDescriptor md
+            = new ModuleDescriptor.Builder("m")
+                .conceals(c.getPackageName())
+                .requires("java.base")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(md);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m"));
+
+        Layer.boot().defineModules(cf, mn -> c.getClassLoader());
+    }
+
+
+    /**
+     * Parent of configuration != configuration of parent Layer
+     */
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testIncorrectParent1() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .requires("java.base")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration parent = Layer.boot().configuration();
+        Configuration cf = parent.resolveRequires(finder, empty(), Set.of("m1"));
+
+        ClassLoader loader = new ClassLoader() { };
+        Layer.empty().defineModules(cf, mn -> loader);
+    }
+
+
+    /**
+     * Parent of configuration != configuration of parent Layer
+     */
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testIncorrectParent2() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        ClassLoader loader = new ClassLoader() { };
+        Layer.boot().defineModules(cf, mn -> loader);
+    }
+
+
+    // null handling
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testCreateWithNull1() {
+        ClassLoader loader = new ClassLoader() { };
+        Layer.empty().defineModules(null, mn -> loader);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testCreateWithNull2() {
+        ClassLoader loader = new ClassLoader() { };
+        Configuration cf = resolveRequires(Layer.boot().configuration(), empty());
+        Layer.boot().defineModules(cf, null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testCreateWithNull3() {
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer.empty().defineModulesWithOneLoader(null, scl);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testCreateWithNull4() {
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer.empty().defineModulesWithManyLoaders(null, scl);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testFindModuleWithNull() {
+        Layer.boot().findModule(null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testFindLoaderWithNull() {
+        Layer.boot().findLoader(null);
+    }
+
+
+    // immutable sets
+
+    @Test(expectedExceptions = { UnsupportedOperationException.class })
+    public void testImmutableSet() {
+        Module base = Object.class.getModule();
+        Layer.boot().modules().add(base);
+    }
+
+
+    /**
+     * Resolve the given modules, by name, and returns the resulting
+     * Configuration.
+     */
+    private static Configuration resolveRequires(Configuration cf,
+                                                 ModuleFinder finder,
+                                                 String... roots) {
+        return cf.resolveRequires(finder, empty(), Set.of(roots));
+    }
+
+    private static Configuration resolveRequires(ModuleFinder finder,
+                                                 String... roots) {
+        return resolveRequires(Configuration.empty(), finder, roots);
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
new file mode 100644
index 0000000..b37813f
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
@@ -0,0 +1,673 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @build LayerAndLoadersTest CompilerUtils ModuleUtils
+ * @run testng LayerAndLoadersTest
+ * @summary Tests for java.lang.reflect.Layer@createWithXXX methods
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import static java.lang.module.ModuleFinder.empty;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Layer;
+import java.lang.reflect.LayerInstantiationException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class LayerAndLoadersTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    @BeforeTest
+    public void setup() throws Exception {
+
+        // javac -d mods -modulesourcepath src src/**
+        assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR,
+                "-modulesourcepath", SRC_DIR.toString()));
+    }
+
+
+    /**
+     * Basic test of Layer.createWithOneLoader
+     *
+     * Test scenario:
+     *   m1 requires m2 and m3
+     */
+    public void testWithOneLoader() throws Exception {
+
+        Configuration cf = resolveRequires("m1");
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
+
+        checkLayer(layer, "m1", "m2", "m3");
+
+        ClassLoader cl1 = layer.findLoader("m1");
+        ClassLoader cl2 = layer.findLoader("m2");
+        ClassLoader cl3 = layer.findLoader("m3");
+
+        assertTrue(cl1.getParent() == scl);
+        assertTrue(cl2 == cl1);
+        assertTrue(cl3 == cl1);
+
+        invoke(layer, "m1", "p.Main");
+
+    }
+
+
+    /**
+     * Basic test of Layer.createWithManyLoaders
+     *
+     * Test scenario:
+     *   m1 requires m2 and m3
+     */
+    public void testWithManyLoaders() throws Exception {
+
+        Configuration cf = resolveRequires("m1");
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl);
+
+        checkLayer(layer, "m1", "m2", "m3");
+
+        ClassLoader cl1 = layer.findLoader("m1");
+        ClassLoader cl2 = layer.findLoader("m2");
+        ClassLoader cl3 = layer.findLoader("m3");
+
+        assertTrue(cl1.getParent() == scl);
+        assertTrue(cl2.getParent() == scl);
+        assertTrue(cl3.getParent() == scl);
+        assertTrue(cl2 != cl1);
+        assertTrue(cl3 != cl1);
+        assertTrue(cl3 != cl2);
+
+        invoke(layer, "m1", "p.Main");
+
+    }
+
+
+    /**
+     * Basic test of Layer.createWithOneLoader where one of the modules
+     * is a service provider module.
+     *
+     * Test scenario:
+     *    m1 requires m2 and m3
+     *    m1 uses S
+     *    m4 provides S with ...
+     */
+    public void testServicesWithOneLoader() throws Exception {
+
+        Configuration cf = resolveRequiresAndUses("m1");
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
+
+        checkLayer(layer, "m1", "m2", "m3", "m4");
+
+        ClassLoader cl1 = layer.findLoader("m1");
+        ClassLoader cl2 = layer.findLoader("m2");
+        ClassLoader cl3 = layer.findLoader("m3");
+        ClassLoader cl4 = layer.findLoader("m4");
+
+        assertTrue(cl1.getParent() == scl);
+        assertTrue(cl2 == cl1);
+        assertTrue(cl3 == cl1);
+        assertTrue(cl4 == cl1);
+
+        Class<?> serviceType = cl1.loadClass("p.Service");
+        assertTrue(serviceType.getClassLoader() == cl1);
+
+        Iterator<?> iter = ServiceLoader.load(serviceType, cl1).iterator();
+        Object provider = iter.next();
+        assertTrue(serviceType.isInstance(provider));
+        assertTrue(provider.getClass().getClassLoader() == cl1);
+        assertFalse(iter.hasNext());
+
+    }
+
+
+    /**
+     * Basic test of Layer.createWithManyLoaders where one of the modules
+     * is a service provider module.
+     *
+     * Test scenario:
+     *    m1 requires m2 and m3
+     *    m1 uses S
+     *    m4 provides S with ...
+     */
+    public void testServicesWithManyLoaders() throws Exception {
+
+        Configuration cf = resolveRequiresAndUses("m1");
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl);
+
+        checkLayer(layer, "m1", "m2", "m3", "m4");
+
+        ClassLoader cl1 = layer.findLoader("m1");
+        ClassLoader cl2 = layer.findLoader("m2");
+        ClassLoader cl3 = layer.findLoader("m3");
+        ClassLoader cl4 = layer.findLoader("m4");
+
+        assertTrue(cl1.getParent() == scl);
+        assertTrue(cl2.getParent() == scl);
+        assertTrue(cl3.getParent() == scl);
+        assertTrue(cl4.getParent() == scl);
+        assertTrue(cl2 != cl1);
+        assertTrue(cl3 != cl1);
+        assertTrue(cl3 != cl2);
+        assertTrue(cl4 != cl1);
+        assertTrue(cl4 != cl2);
+        assertTrue(cl4 != cl3);
+
+        Class<?> serviceType = cl1.loadClass("p.Service");
+        assertTrue(serviceType.getClassLoader() == cl1);
+
+        // Test that the service provider can be located via any of
+        // the class loaders in the layer
+        for (Module m : layer.modules()) {
+            ClassLoader loader = m.getClassLoader();
+            Iterator<?> iter = ServiceLoader.load(serviceType, loader).iterator();
+            Object provider = iter.next();
+            assertTrue(serviceType.isInstance(provider));
+            assertTrue(provider.getClass().getClassLoader() == cl4);
+            assertFalse(iter.hasNext());
+        }
+
+    }
+
+
+    /**
+     * Tests that the class loaders created by Layer.createWithXXX delegate
+     * to the given parent class loader.
+     */
+    public void testDelegationToParent() throws Exception {
+
+        Configuration cf = resolveRequires("m1");
+
+        ClassLoader parent = this.getClass().getClassLoader();
+        String cn = this.getClass().getName();
+
+        // one loader
+        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, parent);
+        testLoad(layer, cn);
+
+         // one loader with boot loader as parent
+        layer = Layer.boot().defineModulesWithOneLoader(cf, null);
+        testLoadFail(layer, cn);
+
+        // many loaders
+        layer = Layer.boot().defineModulesWithManyLoaders(cf, parent);
+        testLoad(layer, cn);
+
+        // many loader with boot loader as parent
+        layer = Layer.boot().defineModulesWithManyLoaders(cf, null);
+        testLoadFail(layer, cn);
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX when modules that have overlapping packages.
+     *
+     * Test scenario:
+     *   m1 exports p
+     *   m2 exports p
+     */
+    public void testOverlappingPackages() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1").exports("p").build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2").exports("p").build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = Layer.boot()
+            .configuration()
+            .resolveRequires(finder, empty(), Set.of("m1", "m2"));
+
+        // cannot define both module m1 and m2 to the same class loader
+        try {
+            Layer.boot().defineModulesWithOneLoader(cf, null);
+            assertTrue(false);
+        } catch (LayerInstantiationException expected) { }
+
+        // should be okay to have one module per class loader
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, null);
+        checkLayer(layer, "m1", "m2");
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX with split delegation.
+     *
+     * Test scenario:
+     *   layer1: m1 exports p, m2 exports p
+     *   layer2: m3 reads m1, m4 reads m2
+     */
+    public void testSplitDelegation() {
+
+        ModuleDescriptor descriptor1
+            = new ModuleDescriptor.Builder("m1").exports("p").build();
+
+        ModuleDescriptor descriptor2
+            = new ModuleDescriptor.Builder("m2").exports("p").build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf1 = Layer.boot()
+            .configuration()
+            .resolveRequires(finder1, empty(), Set.of("m1", "m2"));
+
+        Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null);
+        checkLayer(layer1, "m1", "m2");
+
+        ModuleDescriptor descriptor3
+            = new ModuleDescriptor.Builder("m3").requires("m1").build();
+
+        ModuleDescriptor descriptor4
+            = new ModuleDescriptor.Builder("m4").requires("m2").build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
+
+        Configuration cf2 = cf1.resolveRequires(finder2, empty(), Set.of("m3", "m4"));
+
+        // package p cannot be supplied by two class loaders
+        try {
+            layer1.defineModulesWithOneLoader(cf2, null);
+            assertTrue(false);
+        } catch (LayerInstantiationException expected) { }
+
+        // no split delegation when modules have their own class loader
+        Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
+        checkLayer(layer2, "m3", "m4");
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX when the modules that override same named
+     * modules in the parent layer.
+     *
+     * Test scenario:
+     *   layer1: m1, m2, m3 => same loader
+     *   layer2: m1, m2, m4 => same loader
+     */
+    public void testOverriding1() throws Exception {
+
+        Configuration cf1 = resolveRequires("m1");
+
+        Layer layer1 = Layer.boot().defineModulesWithOneLoader(cf1, null);
+        checkLayer(layer1, "m1", "m2", "m3");
+
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1"));
+
+        Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
+        checkLayer(layer2, "m1", "m2", "m3");
+        invoke(layer1, "m1", "p.Main");
+
+        ClassLoader loader1 = layer1.findLoader("m1");
+        ClassLoader loader2 = layer1.findLoader("m2");
+        ClassLoader loader3 = layer1.findLoader("m3");
+
+        ClassLoader loader4 = layer2.findLoader("m1");
+        ClassLoader loader5 = layer2.findLoader("m2");
+        ClassLoader loader6 = layer2.findLoader("m3");
+
+        assertTrue(loader1 == loader2);
+        assertTrue(loader1 == loader3);
+
+        assertTrue(loader4 == loader5);
+        assertTrue(loader4 == loader6);
+        assertTrue(loader4 != loader1);
+
+        assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1);
+
+        assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
+        assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4);
+        assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4);
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX when the modules that override same named
+     * modules in the parent layer.
+     *
+     * Test scenario:
+     *   layer1: m1, m2, m3 => loader pool
+     *   layer2: m1, m2, m3 => loader pool
+     */
+    public void testOverriding2() throws Exception {
+
+        Configuration cf1 = resolveRequires("m1");
+
+        Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null);
+        checkLayer(layer1, "m1", "m2", "m3");
+
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1"));
+
+        Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
+        checkLayer(layer2, "m1", "m2", "m3");
+        invoke(layer1, "m1", "p.Main");
+
+        ClassLoader loader1 = layer1.findLoader("m1");
+        ClassLoader loader2 = layer1.findLoader("m2");
+        ClassLoader loader3 = layer1.findLoader("m3");
+
+        ClassLoader loader4 = layer2.findLoader("m1");
+        ClassLoader loader5 = layer2.findLoader("m2");
+        ClassLoader loader6 = layer2.findLoader("m3");
+
+        assertTrue(loader4 != loader1);
+        assertTrue(loader5 != loader2);
+        assertTrue(loader6 != loader3);
+
+        assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2);
+        assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3);
+
+        // p.Main is not visible via loader2
+        try {
+            loader2.loadClass("p.Main");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // w.Hello is not visible via loader2
+        try {
+            loader2.loadClass("w.Hello");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // p.Main is not visible via loader3
+        try {
+            loader3.loadClass("p.Main");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // q.Hello is not visible via loader3
+        try {
+            loader3.loadClass("q.Hello");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+
+        assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
+        assertTrue(loader5.loadClass("q.Hello").getClassLoader() == loader5);
+        assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
+
+        // p.Main is not visible via loader5
+        try {
+            loader5.loadClass("p.Main");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // w.Hello is not visible via loader5
+        try {
+            loader5.loadClass("w.Hello");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // p.Main is not visible via loader6
+        try {
+            loader6.loadClass("p.Main");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+        // q.Hello is not visible via loader6
+        try {
+            loader6.loadClass("q.Hello");
+            assertTrue(false);
+        } catch (ClassNotFoundException expected) { }
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX when the modules that override same named
+     * modules in the parent layer.
+     *
+     * layer1: m1, m2, m3 => same loader
+     * layer2: m1, m3 => same loader
+     */
+    public void testOverriding3() throws Exception {
+
+        Configuration cf1 = resolveRequires("m1");
+
+        Layer layer1 = Layer.boot().defineModulesWithOneLoader(cf1, null);
+        checkLayer(layer1, "m1", "m2", "m3");
+
+        ModuleFinder finder = finderFor("m1", "m3");
+
+        Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1"));
+
+        Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
+        checkLayer(layer2, "m1", "m3");
+        invoke(layer1, "m1", "p.Main");
+
+        ClassLoader loader1 = layer1.findLoader("m1");
+        ClassLoader loader2 = layer2.findLoader("m1");
+
+        assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1);
+
+        assertTrue(loader2.loadClass("p.Main").getClassLoader() == loader2);
+        assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader1);
+        assertTrue(loader2.loadClass("w.Hello").getClassLoader() == loader2);
+
+    }
+
+
+    /**
+     * Test Layer.createWithXXX when the modules that override same named
+     * modules in the parent layer.
+     *
+     * layer1: m1, m2, m3 => loader pool
+     * layer2: m1, m3 => loader pool
+     */
+    public void testOverriding4() throws Exception {
+
+        Configuration cf1 = resolveRequires("m1");
+
+        Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null);
+        checkLayer(layer1, "m1", "m2", "m3");
+
+        ModuleFinder finder = finderFor("m1", "m3");
+
+        Configuration cf2 = cf1.resolveRequires(finder, empty(), Set.of("m1"));
+
+        Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
+        checkLayer(layer2, "m1", "m3");
+        invoke(layer1, "m1", "p.Main");
+
+        ClassLoader loader1 = layer1.findLoader("m1");
+        ClassLoader loader2 = layer1.findLoader("m2");
+        ClassLoader loader3 = layer1.findLoader("m3");
+
+        ClassLoader loader4 = layer2.findLoader("m1");
+        ClassLoader loader5 = layer2.findLoader("m2");
+        ClassLoader loader6 = layer2.findLoader("m3");
+
+        assertTrue(loader4 != loader1);
+        assertTrue(loader5 == loader2);  // m2 not overridden
+        assertTrue(loader6 != loader3);
+
+        assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
+        assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2);
+        assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3);
+
+        assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader2);
+
+        assertTrue(loader3.loadClass("w.Hello").getClassLoader() == loader3);
+
+        assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
+        assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader2);
+        assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader6);
+
+        assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
+
+    }
+
+
+    // -- supporting methods --
+
+
+    /**
+     * Resolve the given modules, by name, and returns the resulting
+     * Configuration.
+     */
+    private static Configuration resolveRequires(String... roots) {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        return Layer.boot()
+            .configuration()
+            .resolveRequires(finder, empty(), Set.of(roots));
+    }
+
+    /**
+     * Resolve the given modules, by name, and returns the resulting
+     * Configuration.
+     */
+    private static Configuration resolveRequiresAndUses(String... roots) {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        return Layer.boot()
+            .configuration()
+            .resolveRequiresAndUses(finder, empty(), Set.of(roots));
+    }
+
+
+    /**
+     * Invokes the static void main(String[]) method on the given class
+     * in the given module.
+     */
+    private static void invoke(Layer layer, String mn, String mc) throws Exception {
+        ClassLoader loader = layer.findLoader(mn);
+        Class<?> c = loader.loadClass(mc);
+        Method mainMethod = c.getMethod("main", String[].class);
+        mainMethod.invoke(null, (Object)new String[0]);
+    }
+
+
+    /**
+     * Checks that the given layer contains exactly the expected modules
+     * (by name).
+     */
+    private void checkLayer(Layer layer, String ... expected) {
+        Set<String> names = layer.modules().stream()
+                .map(Module::getName)
+                .collect(Collectors.toSet());
+        assertTrue(names.size() == expected.length);
+        for (String name : expected) {
+            assertTrue(names.contains(name));
+        }
+    }
+
+
+    /**
+     * Test that a class can be loaded via the class loader of all modules
+     * in the given layer.
+     */
+    static void testLoad(Layer layer, String cn) throws Exception {
+        for (Module m : layer.modules()) {
+            ClassLoader l = m.getClassLoader();
+            l.loadClass(cn);
+        }
+    }
+
+
+    /**
+     * Test that a class cannot be loaded via any of the class loaders of
+     * the modules in the given layer.
+     */
+    static void testLoadFail(Layer layer, String cn) throws Exception {
+        for (Module m : layer.modules()) {
+            ClassLoader l = m.getClassLoader();
+            try {
+                l.loadClass(cn);
+                assertTrue(false);
+            } catch (ClassNotFoundException expected) { }
+        }
+    }
+
+
+    /**
+     * Returns a ModuleFinder that only finds the given test modules
+     */
+    static ModuleFinder finderFor(String... names) {
+
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+
+        Map<String, ModuleReference> mrefs = new HashMap<>();
+        for (String name : names) {
+            Optional<ModuleReference> omref = finder.find(name);
+            assert omref.isPresent();
+            mrefs.put(name, omref.get());
+        }
+
+        return new ModuleFinder() {
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                ModuleReference mref = mrefs.get(name);
+                return Optional.ofNullable(mref);
+            }
+            @Override
+            public Set<ModuleReference> findAll() {
+                return mrefs.values().stream().collect(Collectors.toSet());
+            }
+        };
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Layer/layertest/Test.java b/jdk/test/java/lang/reflect/Layer/layertest/Test.java
new file mode 100644
index 0000000..f5c76cc
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/layertest/Test.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Supporting class for tests of java.lang.reflect.Layer.
+ */
+
+package layertest;
+
+public class Test { }
+
diff --git a/jdk/test/java/lang/reflect/Layer/src/m1/module-info.java b/jdk/test/java/lang/reflect/Layer/src/m1/module-info.java
new file mode 100644
index 0000000..d989339
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m1/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    requires m2;
+    requires m3;
+    exports p;
+    uses p.Service;
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m1/p/Main.java b/jdk/test/java/lang/reflect/Layer/src/m1/p/Main.java
new file mode 100644
index 0000000..51f9407
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m1/p/Main.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import java.net.URL;
+
+public class Main {
+    public static void main(String[] args) {
+
+        URL url1 = Main.class.getResource("Main.class");
+        if (url1 == null) throw new RuntimeException();
+        URL url2 = Main.class.getResource("/p/Main.class");
+        if (url2 == null) throw new RuntimeException();
+
+        q.Hello.hello();
+        w.Hello.hello();
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m1/p/Service.java b/jdk/test/java/lang/reflect/Layer/src/m1/p/Service.java
new file mode 100644
index 0000000..0cbc7d0
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m1/p/Service.java
@@ -0,0 +1,26 @@
+/*
+ * 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 interface Service { }
diff --git a/jdk/test/java/lang/reflect/Layer/src/m2/module-info.java b/jdk/test/java/lang/reflect/Layer/src/m2/module-info.java
new file mode 100644
index 0000000..3e0ed03
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports q;
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m2/q/Hello.java b/jdk/test/java/lang/reflect/Layer/src/m2/q/Hello.java
new file mode 100644
index 0000000..50c9bf0
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m2/q/Hello.java
@@ -0,0 +1,40 @@
+/*
+ * 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 q;
+
+import java.net.URL;
+
+public class Hello {
+
+    public static void hello() {
+
+        URL url1 = Hello.class.getResource("Hello.class");
+        if (url1 == null) throw new RuntimeException();
+        URL url2 = Hello.class.getResource("/q/Hello.class");
+        if (url2 == null) throw new RuntimeException();
+
+        System.out.println("Hello!");
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m3/module-info.java b/jdk/test/java/lang/reflect/Layer/src/m3/module-info.java
new file mode 100644
index 0000000..292c919
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m3/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 {
+    // qualified export
+    exports w to m1;
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m3/w/Hello.java b/jdk/test/java/lang/reflect/Layer/src/m3/w/Hello.java
new file mode 100644
index 0000000..353493c
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m3/w/Hello.java
@@ -0,0 +1,40 @@
+/*
+ * 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 w;
+
+import java.net.URL;
+
+public class Hello {
+
+    public static void hello() {
+
+        URL url1 = Hello.class.getResource("Hello.class");
+        if (url1 == null) throw new RuntimeException();
+        URL url2 = Hello.class.getResource("/w/Hello.class");
+        if (url2 == null) throw new RuntimeException();
+
+        System.out.println("Hello!");
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m4/impl/ServiceImpl.java b/jdk/test/java/lang/reflect/Layer/src/m4/impl/ServiceImpl.java
new file mode 100644
index 0000000..ae63701
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m4/impl/ServiceImpl.java
@@ -0,0 +1,27 @@
+/*
+ * 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 impl;
+
+public class ServiceImpl implements p.Service {
+}
diff --git a/jdk/test/java/lang/reflect/Layer/src/m4/module-info.java b/jdk/test/java/lang/reflect/Layer/src/m4/module-info.java
new file mode 100644
index 0000000..ec106f4
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/src/m4/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 m4 {
+    requires m1;
+    provides p.Service with impl.ServiceImpl;
+}
diff --git a/jdk/test/java/lang/reflect/Module/AddExportsTest.java b/jdk/test/java/lang/reflect/Module/AddExportsTest.java
new file mode 100644
index 0000000..020f38e
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/AddExportsTest.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
+ * @run main/othervm -XaddExports:java.desktop/sun.awt=java.base AddExportsTest
+ * @run main/othervm -XaddExports:java.desktop/sun.awt=ALL-UNNAMED AddExportsTest
+ * @summary Test Module isExported methods with exports changed by -AddExportsTest
+ */
+
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.Optional;
+
+public class AddExportsTest {
+
+    public static void main(String[] args) {
+
+        String addExports = System.getProperty("jdk.launcher.addexports.0");
+        assertTrue(addExports != null, "Expected to be run with -XaddExports");
+
+        Layer bootLayer = Layer.boot();
+
+        Module unnamedModule = AddExportsTest.class.getModule();
+        assertFalse(unnamedModule.isNamed());
+
+        for (String expr : addExports.split(",")) {
+
+            String[] s = expr.split("=");
+            assertTrue(s.length == 2);
+
+            // $MODULE/$PACKAGE
+            String[] moduleAndPackage = s[0].split("/");
+            assertTrue(moduleAndPackage.length == 2);
+
+            String mn = moduleAndPackage[0];
+            String pn = moduleAndPackage[1];
+
+            // source module
+            Module source;
+            Optional<Module> om = bootLayer.findModule(mn);
+            assertTrue(om.isPresent(), mn + " not in boot layer");
+            source = om.get();
+
+            // package should not be exported unconditionally
+            assertFalse(source.isExported(pn),
+                        pn + " should not be exported unconditionally");
+
+            // $TARGET
+            String tn = s[1];
+            if ("ALL-UNNAMED".equals(tn)) {
+
+                // package is exported to all unnamed modules
+                assertTrue(source.isExported(pn, unnamedModule),
+                           pn + " should be exported to all unnamed modules");
+
+            } else {
+
+                om = bootLayer.findModule(tn);
+                assertTrue(om.isPresent());
+                Module target = om.get();
+
+                // package should be exported to target module
+                assertTrue(source.isExported(pn, target),
+                           pn + " should be exported to " + target);
+
+                // package should not be exported to unnamed modules
+                assertFalse(source.isExported(pn, unnamedModule),
+                            pn + " should not be exported to unnamed modules");
+
+            }
+
+        }
+    }
+
+    static void assertTrue(boolean cond) {
+        if (!cond) throw new RuntimeException();
+    }
+
+    static void assertTrue(boolean cond, String msg) {
+        if (!cond) throw new RuntimeException(msg);
+    }
+
+    static void assertFalse(boolean cond) {
+        if (cond) throw new RuntimeException();
+    }
+
+    static void assertFalse(boolean cond, String msg) {
+        if (cond) throw new RuntimeException(msg);
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Module/BasicModuleTest.java b/jdk/test/java/lang/reflect/Module/BasicModuleTest.java
new file mode 100644
index 0000000..32a945a5
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/BasicModuleTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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
+ * 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.module.ModuleDescriptor.Exports;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @summary Basic test of java.lang.reflect.Module
+ * @modules java.desktop java.xml
+ * @run testng BasicModuleTest
+ */
+
+public class BasicModuleTest {
+
+    /**
+     * Tests that the given module reads all modules in the boot Layer.
+     */
+    private void testReadsAllBootModules(Module m) {
+        Layer bootLayer = Layer.boot();
+        bootLayer.configuration()
+            .modules()
+            .stream()
+            .map(ResolvedModule::name)
+            .map(bootLayer::findModule)
+            .forEach(target -> assertTrue(m.canRead(target.get())));
+    }
+
+    /**
+     * Returns {@code true} if the array contains the given object.
+     */
+    private <T> boolean contains(T[] array, T obj) {
+        return Stream.of(array).anyMatch(obj::equals);
+    }
+
+    /**
+     * Returns a {@code Predicate} to test if a package is exported.
+     */
+    private Predicate<Exports> doesExport(String pn) {
+        return e -> (e.source().equals(pn) && !e.isQualified());
+    }
+
+
+
+    @Test
+    public void testThisModule() {
+        Module thisModule = BasicModuleTest.class.getModule();
+        Module baseModule = Object.class.getModule();
+
+        assertFalse(thisModule.isNamed());
+        assertTrue(thisModule.getName() == null);
+        assertTrue(thisModule.getDescriptor() == null);
+        assertTrue(thisModule.getLayer() == null);
+        assertTrue(thisModule.toString().startsWith("unnamed module "));
+
+        ClassLoader thisLoader = BasicModuleTest.class.getClassLoader();
+        assertTrue(thisLoader == thisModule.getClassLoader());
+        assertTrue(thisLoader.getUnnamedModule() == thisModule);
+
+        // unnamed modules read all other modules
+        ClassLoader cl;
+        cl = ClassLoader.getPlatformClassLoader();
+        assertTrue(thisModule.canRead(cl.getUnnamedModule()));
+        cl = ClassLoader.getSystemClassLoader();
+        assertTrue(thisModule.canRead(cl.getUnnamedModule()));
+        testReadsAllBootModules(thisModule);
+
+        // unnamed modules export all packages
+        assertTrue(thisModule.isExported(""));
+        assertTrue(thisModule.isExported("", thisModule));
+        assertTrue(thisModule.isExported("", baseModule));
+        assertTrue(thisModule.isExported("p"));
+        assertTrue(thisModule.isExported("p", thisModule));
+        assertTrue(thisModule.isExported("p", baseModule));
+
+        // this test is in the unnamed package
+        assertTrue(contains(thisModule.getPackages(), ""));
+    }
+
+
+    @Test
+    public void testUnnamedModules() {
+        Module thisModule = BasicModuleTest.class.getModule();
+        Module baseModule = Object.class.getModule();
+
+        ClassLoader loader1 = ClassLoader.getSystemClassLoader();
+        ClassLoader loader2 = loader1.getParent();
+
+        Module m1 = loader1.getUnnamedModule();
+        Module m2 = loader2.getUnnamedModule();
+
+        assertTrue(m1 != m2);
+
+        assertFalse(m1.isNamed());
+        assertFalse(m2.isNamed());
+
+        assertTrue(m1.getLayer() == null);
+        assertTrue(m2.getLayer() == null);
+
+        assertTrue(m1.toString().startsWith("unnamed module "));
+        assertTrue(m2.toString().startsWith("unnamed module "));
+
+        // unnamed module reads all modules
+        assertTrue(m1.canRead(m2));
+        assertTrue(m2.canRead(m1));
+
+        testReadsAllBootModules(m1);
+        testReadsAllBootModules(m2);
+
+        assertTrue(m1.isExported(""));
+        assertTrue(m1.isExported("", thisModule));
+        assertTrue(m1.isExported("", baseModule));
+        assertTrue(m1.isExported("p"));
+        assertTrue(m1.isExported("p", thisModule));
+        assertTrue(m1.isExported("p", baseModule));
+    }
+
+
+
+    @Test
+    public void testBaseModule() {
+        Module base = Object.class.getModule();
+        Module thisModule = BasicModuleTest.class.getModule();
+
+        // getName
+        assertTrue(base.getName().equals("java.base"));
+
+        // getDescriptor
+        assertTrue(base.getDescriptor().exports().stream()
+                .anyMatch(doesExport("java.lang")));
+
+        // getClassLoader
+        assertTrue(base.getClassLoader() == null);
+
+        // getLayer
+        assertTrue(base.getLayer() == Layer.boot());
+
+        // toString
+        assertEquals(base.toString(), "module java.base");
+
+        // getPackages
+        assertTrue(contains(base.getPackages(), "java.lang"));
+
+        // canRead
+        assertTrue(base.canRead(base));
+
+        // isExported
+        assertTrue(base.isExported("java.lang"));
+        assertTrue(base.isExported("java.lang", thisModule));
+        assertFalse(base.isExported("java.wombat"));
+        assertFalse(base.isExported("java.wombat", thisModule));
+    }
+
+
+    @Test
+    public void testDesktopModule() {
+        Module desktop = java.awt.Component.class.getModule();
+        Module base = Object.class.getModule();
+        Module xml = javax.xml.XMLConstants.class.getModule();
+        Module thisModule = BasicModuleTest.class.getModule();
+
+        // name
+        assertTrue(desktop.getName().equals("java.desktop"));
+
+        // descriptor
+        assertTrue(desktop.getDescriptor().exports().stream()
+                   .anyMatch(doesExport("java.awt")));
+
+        // getClassLoader
+        assertTrue(desktop.getClassLoader() == null);
+
+        // getLayer
+        assertTrue(desktop.getLayer() == Layer.boot());
+
+        // toString
+        assertEquals(desktop.toString(), "module java.desktop");
+
+        // getPackages
+        assertTrue(contains(desktop.getPackages(), "java.awt"));
+        assertTrue(contains(desktop.getPackages(), "sun.awt"));
+
+        // canRead
+        assertTrue(desktop.canRead(base));
+        assertTrue(desktop.canRead(xml));
+
+        // isExported
+        assertTrue(desktop.isExported("java.awt"));
+        assertTrue(desktop.isExported("java.awt", thisModule));
+        assertFalse(desktop.isExported("java.wombat"));
+        assertFalse(desktop.isExported("java.wombat", thisModule));
+    }
+
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testIsExportedNull() {
+        Module thisModule = this.getClass().getModule();
+        thisModule.isExported(null, thisModule);
+    }
+
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testIsExportedToNull() {
+        Module thisModule = this.getClass().getModule();
+        thisModule.isExported("", null);
+    }
+
+
+}
diff --git a/jdk/test/java/lang/reflect/Module/access/AccessTest.java b/jdk/test/java/lang/reflect/Module/access/AccessTest.java
new file mode 100644
index 0000000..35e58a9
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/AccessTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+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.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.
+ */
+
+@Test
+public class AccessTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("test", "target");
+
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path src = SRC_DIR.resolve(mn);
+            Path mods = MODS_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(src, mods));
+        }
+    }
+
+    /**
+     * Run the test
+     */
+    public void runTest() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "target",
+                              "-m", "test/test.Main")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+}
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
new file mode 100644
index 0000000..9c987c7
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 target {
+    exports p;
+}
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
new file mode 100644
index 0000000..73bdb34
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/p/Exported.java
@@ -0,0 +1,43 @@
+/*
+ * 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/p/Helper.java
new file mode 100644
index 0000000..b834364
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/p/Helper.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import java.lang.reflect.Module;
+
+public class Helper {
+    Helper() { }
+
+    public static void exportPackage(String pn, Module who) {
+        Helper.class.getModule().addExports(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/q/Internal.java
new file mode 100644
index 0000000..f0dabdd1
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
@@ -0,0 +1,43 @@
+/*
+ * 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 q;
+
+public class Internal {
+
+    /**
+     * Public constructor
+     */
+    public Internal() { }
+
+    /**
+     * Public field
+     */
+    public static Object field;
+
+    /**
+     * Public method
+     */
+    public static void run() {
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Module/access/src/test/module-info.java b/jdk/test/java/lang/reflect/Module/access/src/test/module-info.java
new file mode 100644
index 0000000..bcdacb2
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/test/module-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 test { }
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
new file mode 100644
index 0000000..0ba28a7
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/access/src/test/test/Main.java
@@ -0,0 +1,194 @@
+/*
+ * 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 test;
+
+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.
+ */
+
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+
+        Module thisModule = Main.class.getModule();
+        assertTrue(thisModule.isNamed());
+
+        Optional<Module> om = Layer.boot().findModule("target");
+        assertTrue(om.isPresent());
+
+        Module target = om.get();
+
+        assertTrue(target.isExported("p"));
+        assertTrue(target.isExported("p", thisModule));
+
+        assertFalse(target.isExported("q"));
+        assertFalse(target.isExported("q", thisModule));
+
+
+        // thisModule does not read the target module
+
+        assertFalse(thisModule.canRead(target));
+
+        tryAccessPublicMembers("p.Exported", true);
+        tryAccessPublicMembers("q.Internal", false);
+
+
+
+        // thisModule reads the target module
+
+        thisModule.addReads(target);
+        assertTrue(thisModule.canRead(target));
+
+        tryAccessPublicMembers("p.Exported", true);
+        tryAccessPublicMembers("q.Internal", false);
+
+
+
+        // change target module to export its internal package to thisModule
+
+        targetAddExports("q", thisModule);
+        assertFalse(target.isExported("q"));
+        assertTrue(target.isExported("q", thisModule));
+
+        tryAccessPublicMembers("p.Exported", true);
+        tryAccessPublicMembers("q.Internal", true);
+    }
+
+
+    /**
+     * Attempt to access public members in a target class.
+     */
+    static void tryAccessPublicMembers(String cn, boolean shouldSucceed)
+        throws Exception
+    {
+
+        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();
+        try {
+            ctor.newInstance();
+            assertTrue(shouldSucceed);
+        } catch (IllegalAccessException e) {
+            assertTrue(shouldFail);
+        }
+        try {
+            ctor.setAccessible(true);
+            assertTrue(shouldSucceed);
+            ctor.newInstance();
+        } catch (InaccessibleObjectException e) {
+            assertTrue(shouldFail);
+        }
+
+
+        // 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");
+        try {
+            f.get(null);
+            assertTrue(shouldSucceed);
+        } catch (IllegalAccessException e) {
+            assertTrue(shouldFail);
+        }
+        try {
+            f.set(null, 100);
+            assertTrue(shouldSucceed);
+        } catch (IllegalAccessException e) {
+            assertTrue(shouldFail);
+        }
+        try {
+            f.setAccessible(true);
+            f.get(null);
+            f.set(null, 100);
+            assertTrue(shouldSucceed);
+        } catch (InaccessibleObjectException e) {
+            assertTrue(shouldFail);
+        }
+
+    }
+
+    /**
+     * 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);
+        m.invoke(null, pn, who);
+    }
+
+
+    static void assertTrue(boolean expr) {
+        if (!expr) throw new RuntimeException();
+    }
+
+    static void assertFalse(boolean expr) {
+        assertTrue(!expr);
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/Basic1.java b/jdk/test/java/lang/reflect/Proxy/Basic1.java
index 41233f9..b2440cc 100644
--- a/jdk/test/java/lang/reflect/Proxy/Basic1.java
+++ b/jdk/test/java/lang/reflect/Proxy/Basic1.java
@@ -108,7 +108,7 @@
              * Verify that its protection domain is the bootstrap domain.
              */
             ProtectionDomain pd = proxyClass.getProtectionDomain();
-            System.err.println("+ proxy class's protextion domain: " + pd);
+            System.err.println("+ proxy class's protection domain: " + pd);
             if (!pd.implies(new AllPermission())) {
                 throw new RuntimeException(
                     "proxy class does not have AllPermission");
@@ -143,7 +143,7 @@
             /*
              * Invoke a method on a proxy instance.
              */
-            Method m = Runnable.class.getMethod("run", null);
+            Method m = Runnable.class.getMethod("run");
             ((Runnable) proxy).run();
             if (!handler.lastMethod.equals(m)) {
                 throw new RuntimeException(
diff --git a/jdk/test/java/lang/reflect/Proxy/NullClassLoader.java b/jdk/test/java/lang/reflect/Proxy/NullClassLoader.java
index 861a274..244af00 100644
--- a/jdk/test/java/lang/reflect/Proxy/NullClassLoader.java
+++ b/jdk/test/java/lang/reflect/Proxy/NullClassLoader.java
@@ -42,8 +42,8 @@
             "\nTest creating proxy class with the null class loader.\n");
 
         try {
-            Class p = Proxy.getProxyClass(null,
-                new Class[] { Runnable.class, Observer.class });
+            ClassLoader ld = null;
+            Class p = Proxy.getProxyClass(ld, new Class[] { Runnable.class, Observer.class });
             System.err.println("proxy class: " + p);
 
             ClassLoader loader = p.getClassLoader();
diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java b/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java
new file mode 100644
index 0000000..529f294
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyClassAccessTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Proxy;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+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 jdk.compiler
+ * @build ProxyClassAccessTest q.NP CompilerUtils jdk.testlibrary.*
+ * @run testng ProxyClassAccessTest
+ * @summary Driver for testing proxy class doesn't have access to
+ *          types referenced by proxy interfaces
+ */
+
+public class ProxyClassAccessTest {
+
+    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");
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("m1", "m2", "m3", "test");
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+    }
+
+    /**
+     * Run the modular test
+     */
+    @Test
+    public void runTest() throws Exception {
+        int exitValue = executeTestJava("-mp", MODS_DIR.toString(),
+                                        "-m", "test/jdk.test.ProxyClassAccess")
+                            .outputTo(System.out)
+                            .errorTo(System.out)
+                            .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Test unnamed module has no access to other proxy interface
+     */
+    @Test
+    public void testNoReadAccess() throws Exception {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Layer bootLayer = Layer.boot();
+        Configuration cf = bootLayer
+                .configuration()
+                .resolveRequiresAndUses(ModuleFinder.empty(), finder, modules);
+        ClassLoader parentLoader = this.getClass().getClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, parentLoader);
+
+        ClassLoader loader = layer.findLoader("m1");
+        Class<?>[] interfaces = new Class<?>[] {
+                Class.forName("p.one.I", false, loader),
+                Class.forName("q.NP", false, loader)     // non-public interface in unnamed module
+        };
+        checkIAE(loader, interfaces);
+    }
+
+    private void checkIAE(ClassLoader loader, Class<?>[] interfaces) {
+        try {
+            Proxy.getProxyClass(loader, interfaces);
+            throw new RuntimeException("Expected IllegalArgumentException thrown");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            Proxy.newProxyInstance(loader, interfaces,
+                (proxy, m, params) -> { throw new RuntimeException(m.toString()); });
+            throw new RuntimeException("Expected IllegalArgumentException thrown");
+        } catch (IllegalArgumentException e) {}
+    }
+
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyForMethodHandle.java b/jdk/test/java/lang/reflect/Proxy/ProxyForMethodHandle.java
new file mode 100644
index 0000000..bbe74b6
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyForMethodHandle.java
@@ -0,0 +1,86 @@
+/*
+ * 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.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleProxies;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @summary test MethodHandleProxies that adds qualified export of sun.invoke
+ * from java.base to a dynamic module
+ * @run testng ProxyForMethodHandle
+ */
+public class ProxyForMethodHandle {
+    /**
+     * MethodHandleProxies will add qualified export of sun.invoke from java.base
+     * to a dynamic module
+     */
+    @Test
+    static void testRunnableMethodHandle() throws Exception {
+        MethodHandles.Lookup lookup = MethodHandles.lookup();
+        MethodType mt = MethodType.methodType(void.class);
+        MethodHandle mh = lookup.findStatic(ProxyForMethodHandle.class, "runForRunnable", mt);
+        Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh);
+        proxy.run();
+
+        Class<?> proxyClass = proxy.getClass();
+        Module target = proxyClass.getModule();
+        assertDynamicModule(target, proxyClass.getClassLoader(), proxyClass);
+    }
+
+    static void runForRunnable() {
+        System.out.println("runForRunnable");
+    }
+
+    public static void assertDynamicModule(Module m, ClassLoader ld, Class<?> proxyClass) {
+        if (!m.isNamed() || !m.getName().startsWith("jdk.proxy")) {
+            throw new RuntimeException(m.getName() + " not dynamic module");
+        }
+
+        if (ld != m.getClassLoader() || proxyClass.getClassLoader() != ld) {
+            throw new RuntimeException("unexpected class loader");
+        }
+
+        try {
+            Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
+            cons.newInstance(handler);
+            throw new RuntimeException("Expected IllegalAccessException: " + proxyClass);
+        } catch (IllegalAccessException e) {
+            // expected
+        } catch (NoSuchMethodException|InstantiationException|InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    private final static InvocationHandler handler =
+            (proxy, m, params) -> { throw new RuntimeException(m.toString()); };
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java b/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.java
new file mode 100644
index 0000000..4ee43ea
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyLayerTest.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.
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Proxy;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+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 jdk.compiler
+ * @build ProxyTest CompilerUtils jdk.testlibrary.ProcessTools
+ * @run testng ProxyLayerTest
+ * @summary Test proxies to implement interfaces in a layer
+ */
+
+public class ProxyLayerTest {
+
+    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");
+    private static final Path CPATH_DIR = Paths.get(TEST_CLASSES);
+
+    // the names of the modules in this test
+    private static String[] modules = new String[] {"m1", "m2", "m3"};
+
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+    }
+
+    /**
+     * Test proxy implementing interfaces in a Layer defined in
+     * an unnamed module
+     */
+    @Test
+    public void testProxyInUnnamed() throws Exception {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Layer bootLayer = Layer.boot();
+        Configuration cf = bootLayer
+                .configuration()
+                .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules));
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+
+        ClassLoader loader = layer.findLoader("m1");
+
+        assertTrue(layer.findModule("m1").isPresent());
+        assertTrue(layer.findModule("m2").isPresent());
+        assertTrue(layer.findModule("m3").isPresent());
+
+        Class<?>[] interfaces = new Class<?>[] {
+            Class.forName("p.one.I", false, loader),
+            Class.forName("p.two.A", false, loader),
+            Class.forName("p.three.P", false, loader),
+        };
+        Object o = Proxy.newProxyInstance(loader, interfaces, handler);
+
+        Class<?> proxyClass = o.getClass();
+        Package pkg = proxyClass.getPackage();
+        assertFalse(proxyClass.getModule().isNamed());
+        assertFalse(pkg.isSealed());
+        assertEquals(proxyClass.getModule().getLayer(), null);
+    }
+
+    /**
+     * Test proxy implementing interfaces in a Layer and defined in a
+     * dynamic module
+     */
+    @Test
+    public void testProxyInDynamicModule() throws Exception {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Layer bootLayer = Layer.boot();
+        Configuration cf = bootLayer
+                .configuration()
+                .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules));
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+
+        ClassLoader loader = layer.findLoader("m1");
+
+        assertTrue(layer.findModule("m1").isPresent());
+        assertTrue(layer.findModule("m2").isPresent());
+        assertTrue(layer.findModule("m3").isPresent());
+
+        Class<?>[] interfaces = new Class<?>[] {
+            Class.forName("p.one.internal.J", false, loader),
+        };
+        Object o = Proxy.newProxyInstance(loader, interfaces, handler);
+        Class<?> proxyClass = o.getClass();
+        Package pkg = proxyClass.getPackage();
+        assertTrue(proxyClass.getModule().isNamed());
+        assertTrue(pkg.isSealed());
+        assertEquals(proxyClass.getModule().getLayer(), null);
+    }
+
+    /**
+     * Test proxy implementing interfaces that the target module has no access
+     */
+    @Test
+    public void testNoReadAccess() throws Exception {
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Layer bootLayer = Layer.boot();
+        Configuration cf = bootLayer
+                .configuration()
+                .resolveRequiresAndUses(ModuleFinder.empty(), finder, Arrays.asList(modules));
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+
+        ClassLoader loader = layer.findLoader("m1");
+
+        assertTrue(layer.findModule("m1").isPresent());
+        assertTrue(layer.findModule("m2").isPresent());
+        assertTrue(layer.findModule("m3").isPresent());
+
+        Class<?>[] interfaces = new Class<?>[] {
+                Class.forName("p.one.I", false, loader),
+                Class.forName("p.two.B", false, loader)   // non-public interface but exported package
+        };
+        checkIAE(loader, interfaces);
+    }
+
+    private void checkIAE(ClassLoader loader, Class<?>[] interfaces) {
+        try {
+            Proxy.getProxyClass(loader, interfaces);
+            throw new RuntimeException("Expected IllegalArgumentException thrown");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            Proxy.newProxyInstance(loader, interfaces, handler);
+            throw new RuntimeException("Expected IllegalArgumentException thrown");
+        } catch (IllegalArgumentException e) {}
+    }
+
+    private final static InvocationHandler handler =
+            (proxy, m, params) -> { throw new RuntimeException(m.toString()); };
+
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyModuleMapping.java b/jdk/test/java/lang/reflect/Proxy/ProxyModuleMapping.java
new file mode 100644
index 0000000..db3af7d
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyModuleMapping.java
@@ -0,0 +1,105 @@
+/*
+ * 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.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Module;
+import java.lang.reflect.Proxy;
+
+/*
+ * @test
+ * @summary Basic test of proxy module mapping and the access to Proxy class
+ * @modules java.base/sun.invoke
+ */
+
+public class ProxyModuleMapping {
+    public static void main(String... args) throws Exception {
+        ClassLoader ld = ProxyModuleMapping.class.getClassLoader();
+        Module unnamed = ld.getUnnamedModule();
+        new ProxyModuleMapping(unnamed, Runnable.class).test();
+
+        // unnamed module gets access to sun.invoke package (e.g. via -XaddExports)
+        new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test();
+
+        Class<?> modulePrivateIntf = Class.forName("sun.net.ProgressListener");
+        new ProxyModuleMapping(modulePrivateIntf).test();
+    }
+
+    final Module target;
+    final ClassLoader loader;
+    final Class<?>[] interfaces;
+    ProxyModuleMapping(Module m, Class<?>... interfaces) {
+        this.target = m;
+        this.loader = m.getClassLoader();
+        this.interfaces = interfaces;
+    }
+
+    ProxyModuleMapping(Class<?>... interfaces) {
+        this.target = null;  // expected to be dynamic module
+        this.loader = interfaces[0].getClassLoader();   // same class loader
+        this.interfaces = interfaces;
+    }
+
+    void test() throws Exception {
+        verifyProxyClass();
+        verifyNewProxyInstance();
+    }
+
+    void verifyProxyClass() throws Exception {
+        Class<?> c = Proxy.getProxyClass(loader, interfaces);
+        Module m = c.getModule();
+        if (target != null && m != target) {
+            throw new RuntimeException(c.getModule() + " not expected: " + target);
+        }
+        // expect dynamic module
+        if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
+            throw new RuntimeException("Unexpected:" + m);
+        }
+
+        Module module = c.getModule();
+        try {
+            Constructor<?> cons = c.getConstructor(InvocationHandler.class);
+            cons.newInstance(ih);
+            if (module.isNamed()) {
+                throw new RuntimeException("expected IAE not thrown");
+            }
+        } catch (IllegalAccessException e) {
+            if (!module.isNamed()) {
+                throw e;
+            }
+        }
+    }
+
+    void verifyNewProxyInstance() throws Exception {
+        Object o = Proxy.newProxyInstance(loader, interfaces, ih);
+        Module m = o.getClass().getModule();
+        if (target != null && m != target) {
+            throw new RuntimeException(m + " not expected: " + target);
+        }
+        if (target == null && (!m.isNamed() || !m.getName().startsWith("jdk.proxy"))) {
+            throw new RuntimeException(m + " not expected: dynamic module");
+        }
+    }
+    private final static InvocationHandler ih =
+        (proxy, m, params) -> { System.out.println(m); return null; };
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/ProxyTest.java b/jdk/test/java/lang/reflect/Proxy/ProxyTest.java
new file mode 100644
index 0000000..80c8b76
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+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 jdk.compiler
+ * @build ProxyTest q.U CompilerUtils jdk.testlibrary.*
+ * @run testng ProxyTest
+ * @summary Driver for testing proxies accessing interfaces in named modules
+ */
+
+public class ProxyTest {
+
+    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");
+    private static final Path CPATH_DIR = Paths.get(TEST_CLASSES);
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("test", "m1", "m2", "m3");
+
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+    }
+
+    /**
+     * Run the modular test
+     */
+    @Test
+    public void runTest() throws Exception {
+        int exitValue = executeTestJava("-cp", CPATH_DIR.toString(),
+                                        "-mp", MODS_DIR.toString(),
+                                        "-m", "test/jdk.test.Main")
+                            .outputTo(System.out)
+                            .errorTo(System.out)
+                            .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/q/NP.java b/jdk/test/java/lang/reflect/Proxy/q/NP.java
new file mode 100644
index 0000000..da41a5d
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/q/NP.java
@@ -0,0 +1,27 @@
+/*
+ * 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 q;
+
+interface NP {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/q/U.java b/jdk/test/java/lang/reflect/Proxy/q/U.java
new file mode 100644
index 0000000..c217cbe
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/q/U.java
@@ -0,0 +1,27 @@
+/*
+ * 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 q;
+
+public interface U {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m1/module-info.java b/jdk/test/java/lang/reflect/Proxy/src/m1/module-info.java
new file mode 100644
index 0000000..dd84f09
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m1/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    exports p.one;
+    exports p.one.internal to test;
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/I.java b/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/I.java
new file mode 100644
index 0000000..09e6887
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/I.java
@@ -0,0 +1,28 @@
+/*
+ * 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.one;
+
+public interface I {
+    void run();
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/internal/J.java b/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/internal/J.java
new file mode 100644
index 0000000..f6bd6a0
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m1/p/one/internal/J.java
@@ -0,0 +1,27 @@
+/*
+ * 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.one.internal;
+
+public interface J {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m2/module-info.java b/jdk/test/java/lang/reflect/Proxy/src/m2/module-info.java
new file mode 100644
index 0000000..e7541d6
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m2/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports p.two;
+    exports p.two.internal to test;
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/A.java b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/A.java
new file mode 100644
index 0000000..b54f0d8
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/A.java
@@ -0,0 +1,27 @@
+/*
+ * 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.two;
+
+public interface A {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/B.java b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/B.java
new file mode 100644
index 0000000..7ba1454
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/B.java
@@ -0,0 +1,27 @@
+/*
+ * 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.two;
+
+interface B {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/Bar.java b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/Bar.java
new file mode 100644
index 0000000..fedade0
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/Bar.java
@@ -0,0 +1,34 @@
+/*
+ * 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.two;
+
+public class Bar {
+    public Bar() {
+    }
+
+    @Override
+    public String toString() {
+        return this.getClass().getName();
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/internal/C.java b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/internal/C.java
new file mode 100644
index 0000000..f403f5a
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m2/p/two/internal/C.java
@@ -0,0 +1,27 @@
+/*
+ * 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.two.internal;
+
+public interface C {
+}
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
new file mode 100644
index 0000000..cf4da7c
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m3/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 {
+    requires public m2;
+    exports p.three;
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/P.java b/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/P.java
new file mode 100644
index 0000000..3be0bd8
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/P.java
@@ -0,0 +1,32 @@
+/*
+ * 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.three;
+
+import p.two.Bar;
+
+public interface P {
+    public Bar bar();
+
+    public Bar[][][] barArrays();
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/internal/Q.java b/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/internal/Q.java
new file mode 100644
index 0000000..7fe9fd0
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/m3/p/three/internal/Q.java
@@ -0,0 +1,27 @@
+/*
+ * 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.three.internal;
+
+public interface Q {
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/Main.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..188e3d9
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/Main.java
@@ -0,0 +1,163 @@
+/*
+ * 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 jdk.test;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.lang.reflect.Module;
+import static jdk.test.ProxyTest.*;
+
+public class Main {
+    public static void main(String... args) {
+        ProxyTest ptest = new jdk.test.ProxyTest();
+        for (Data d : proxiesForExportedTypes()) {
+            ptest.test(d);
+        }
+
+        for (Data d : proxiesForPackagePrivateTypes()) {
+            ptest.test(d);
+        }
+
+        for (Data d : proxiesForModulePrivateTypes()) {
+            ptest.test(d);
+        }
+
+        for (Data d : proxiesWithAddReads()) {
+            ptest.test(d);
+        }
+
+        for (Data d : proxiesWithAddExports()) {
+            ptest.test(d);
+        }
+    }
+
+    private final static Module m1 = p.one.I.class.getModule();
+    private final static Module m2 = p.two.A.class.getModule();
+    private final static Module m3 = p.three.P.class.getModule();
+    private final static Module test = Main.class.getModule();
+    private final static Class<?> unnamedModuleClass = classForName("q.U");
+    private final static Class<?> m3InternalType = classForName("p.three.internal.Q");
+
+    /*
+     * Test cases for proxy class to implement exported proxy interfaces
+     * will result in the unnamed module.
+     *
+     * The proxy class is accessible to unnamed module.
+     */
+    static Data[] proxiesForExportedTypes() {
+        ClassLoader ld = Main.class.getClassLoader();
+        Module unnamed = ld.getUnnamedModule();
+        ClassLoader ld2 = new URLClassLoader(new URL[0], ld);
+        Module unnamed2 = ld2.getUnnamedModule();
+
+        return new Data[] {
+            new Data(unnamed,  ld, Runnable.class),
+            new Data(unnamed,  ld, p.one.I.class),
+            new Data(unnamed,  ld, p.one.I.class, p.two.A.class),
+            new Data(unnamed,  ld, p.one.I.class, unnamedModuleClass),
+            new Data(unnamed2, ld2, Runnable.class),
+            new Data(unnamed2, ld2, p.one.I.class),
+            new Data(unnamed2, ld2, p.one.I.class, p.two.A.class),
+            new Data(unnamed2, ld2, p.one.I.class, unnamedModuleClass),
+            new Data(unnamed, m1.getClassLoader(), p.one.I.class),
+            new Data(unnamed, m2.getClassLoader(), p.two.A.class),
+            new Data(unnamed, m3.getClassLoader(), p.three.P.class),
+        };
+    }
+
+    /*
+     * Test cases for proxy class to implement package-private proxy interface
+     * will result in same runtime package and same module as the proxy interface
+     *
+     * The proxy class is accessible to classes in the same runtime package
+     */
+    static Data[] proxiesForPackagePrivateTypes() {
+        Class<?> bClass = classForName("p.two.B");  // package-private type
+
+        return new Data[] {
+            new Data(m2, m2.getClassLoader(), p.two.A.class, bClass),
+            new Data(m2, m2.getClassLoader(), p.two.A.class, bClass, p.two.internal.C.class)
+        };
+    }
+
+    /*
+     * Test cases for proxy class to implement one or more module-private types.
+     *
+     * This will result in a dynamic module which can read the modules of the interfaces
+     * and their dependences and also qualified exports to the module-private packages.
+     * The proxy class is not accessible to any module.
+     */
+    static Data[] proxiesForModulePrivateTypes() {
+        ClassLoader ld = Main.class.getClassLoader();
+        ClassLoader customLoader = new URLClassLoader(new URL[0], ld);
+        return new Data[] {
+            // different loaders
+            new Data(m1.getClassLoader(), p.one.internal.J.class),
+            new Data(customLoader, p.one.internal.J.class),
+            new Data(m2.getClassLoader(), p.two.internal.C.class, Runnable.class),
+            // interfaces from m2 only
+            new Data(m2.getClassLoader(), p.two.internal.C.class, p.two.A.class),
+            // p.two.A is accessible to m3
+            new Data(m3.getClassLoader(), m3InternalType, p.two.A.class),
+            new Data(customLoader, unnamedModuleClass, jdk.test.internal.R.class, p.one.I.class),
+            // two module-private types in two different modules
+            new Data(m3.getClassLoader(), p.two.internal.C.class, m3InternalType),
+            new Data(m3.getClassLoader(), p.three.P.class, m3InternalType, jdk.test.internal.R.class),
+        };
+    }
+
+    /*
+     * Test cases for proxy class to implement accessible proxy interfaces
+     * after addReads. That does not change the target module.
+     */
+    static Data[] proxiesWithAddReads() {
+        Module unnamed = test.getClassLoader().getUnnamedModule();
+        test.addReads(unnamed);
+        return new Data[] {
+             new Data(test.getClassLoader(),
+                      unnamedModuleClass, p.one.I.class,
+                      jdk.test.internal.R.class), // module-private interface in test
+        };
+    }
+
+    /*
+     * Test cases for proxy class to implement accessible proxy interfaces
+     * after addExports.  That does not change the target module.
+     */
+    static Data[] proxiesWithAddExports() {
+        return new Data[] {
+                new Data(test.getClassLoader(),
+                         p.one.internal.J.class,
+                         p.two.internal.C.class), // module-private interfaces in m2 and m3
+        };
+    }
+
+    static Class<?> classForName(String cn) {
+        try {
+            return Class.forName(cn);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/NP.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/NP.java
new file mode 100644
index 0000000..6ddf7ad
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/NP.java
@@ -0,0 +1,31 @@
+/*
+ * 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 jdk.test;
+
+/*
+ * Non-public interface
+ */
+interface NP {
+    void test();
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyClassAccess.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyClassAccess.java
new file mode 100644
index 0000000..1593aa9
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyClassAccess.java
@@ -0,0 +1,109 @@
+/*
+ * 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 jdk.test;
+
+import jdk.test.internal.*;
+import jdk.test.internal.foo.*;
+import p.two.Bar;
+import p.three.P;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * Test proxy class to have access to types referenced in the public methods.
+ */
+public class ProxyClassAccess {
+    public static void main(String... args) throws Exception {
+        testImplClass();
+        testProxyClass1();
+        testProxyClass2();
+        testNonPublicProxy();
+    }
+
+    /*
+     * Invoke methods from implementation class
+     */
+    static void testImplClass() {
+        R impl = new RImpl();
+        impl.foo();
+        Bar[][] bars = new Bar[0][0];
+        impl.setBarArray(bars);
+        try {
+            impl.throwException();
+            throw new RuntimeException("FooException not thrown");
+        } catch (FooException e) { }
+    }
+
+    /*
+     * Invoke methods via proxy
+     */
+    static void testProxyClass1() {
+        R proxy = (R) Proxy.newProxyInstance(R.class.getClassLoader(),
+                                             new Class<?>[] { R.class }, handler);
+        proxy.foo();
+        Bar[][] bars = new Bar[0][0];
+        proxy.setBarArray(bars);
+    }
+
+    /*
+     * Invoke methods via proxy defined with a custom class loader
+     */
+    static void testProxyClass2() {
+        URLClassLoader loader = new URLClassLoader(new URL[0]);
+        P proxy = (P) Proxy.newProxyInstance(loader,
+                new Class<?>[] { R.class, P.class }, handler);
+        proxy.bar();
+        proxy.barArrays();
+    }
+
+    static void testNonPublicProxy() {
+        NP proxy = (NP) Proxy.newProxyInstance(NP.class.getClassLoader(),
+                                               new Class<?>[]{NP.class}, handler);
+        proxy.test();
+
+        try {
+            URLClassLoader loader = new URLClassLoader(new URL[0]);
+            proxy = (NP) Proxy.newProxyInstance(loader,
+                    new Class<?>[]{NP.class}, handler);
+            throw new RuntimeException("IllegalArgumentException not thrown");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    static InvocationHandler handler = new InvocationHandler() {
+        final R impl = new RImpl();
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getDeclaringClass() == R.class) {
+                return method.invoke(impl, args);
+            } else {
+                return null;
+            }
+        }
+    };
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyTest.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyTest.java
new file mode 100644
index 0000000..bbe260b
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/ProxyTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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 jdk.test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+
+public class ProxyTest {
+    public static class Data {
+        private static int count = 0;
+        final int testcase;
+        final ClassLoader loader;
+        final Module module;
+        final Class<?>[] interfaces;
+        // Expected the proxy class in the specified module
+        public Data(Module m, ClassLoader loader, Class<?>... interfaces) {
+            this.module = m;
+            this.loader = loader;
+            this.interfaces = interfaces;
+            this.testcase = ++count;
+        }
+        // Expected the proxy class in a dynamic module
+        public Data(ClassLoader loader, Class<?>... interfaces) {
+            this(null, loader, interfaces);
+        }
+
+        @Override
+        public String toString() {
+            String expected = module != null
+                    ? (module.isNamed() ? module.getName() : "unnamed")
+                    : "dynamic";
+            return String.format("%2d: Expected: %s %s loader: %s", testcase, expected,
+                    Arrays.toString(interfaces), loader);
+        }
+    }
+
+    public void test(Data d) {
+        System.out.println(d);
+
+        if (d.module != null) {
+            testProxyClass(d.module, d.loader, d.interfaces);
+        } else {
+            testDynamicModule(d);
+        }
+    }
+
+    private void testDynamicModule(Data d) {
+        Class<?> proxyClass = Proxy.getProxyClass(d.loader, d.interfaces);
+        assertDynamicModule(proxyClass.getModule(), d.loader, proxyClass);
+
+        Object proxy = Proxy.newProxyInstance(d.loader, d.interfaces, handler);
+        assertDynamicModule(proxy.getClass().getModule(), d.loader, proxy.getClass());
+    }
+
+    private static void testProxyClass(Module module, ClassLoader ld, Class<?>... interfaces) {
+        Class<?> proxyClass = Proxy.getProxyClass(ld, interfaces);
+        assertEquals(proxyClass.getModule(), module);
+
+        Object proxy = Proxy.newProxyInstance(ld, interfaces, handler);
+        assertEquals(proxy.getClass().getModule(), module);
+    }
+
+    public static void assertDynamicModule(Module m, ClassLoader ld, Class<?> proxyClass) {
+        if (!m.isNamed() || !m.getName().startsWith("jdk.proxy")) {
+            throw new RuntimeException(m.getName() + " not dynamic module");
+        }
+
+        if (ld != m.getClassLoader() || proxyClass.getClassLoader() != ld) {
+            throw new RuntimeException("unexpected class loader");
+        }
+
+        try {
+            Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class);
+            cons.newInstance(handler);
+            throw new RuntimeException("Expected IllegalAccessException: " + proxyClass);
+        } catch (IllegalAccessException e) {
+            // expected
+        } catch (NoSuchMethodException|InstantiationException|InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static void assertEquals(Object o1, Object o2) {
+        if (o1 != o2) {
+            throw new RuntimeException(o1 + " != " + o2);
+        }
+    }
+    private final static InvocationHandler handler =
+        (proxy, m, params) -> { throw new RuntimeException(m.toString()); };
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/R.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/R.java
new file mode 100644
index 0000000..40f4219
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/R.java
@@ -0,0 +1,34 @@
+/*
+ * 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 jdk.test.internal;
+
+import jdk.test.internal.foo.*;
+import p.two.Bar;
+
+public interface R {
+    public Foo foo();
+    public void throwException() throws FooException;
+
+    public void setBarArray(Bar[][] array);
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/RImpl.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/RImpl.java
new file mode 100644
index 0000000..0770c09
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/RImpl.java
@@ -0,0 +1,38 @@
+/*
+ * 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 jdk.test.internal;
+
+import jdk.test.internal.foo.*;
+import p.two.Bar;
+
+public class RImpl implements R {
+    public Foo foo() {
+        return new Foo();
+    }
+    public void throwException() throws FooException {
+        throw new FooException();
+    }
+    public void setBarArray(Bar[][] array) {
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/Foo.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/Foo.java
new file mode 100644
index 0000000..1773ba8
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/Foo.java
@@ -0,0 +1,31 @@
+/*
+ * 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 jdk.test.internal.foo;
+
+public class Foo {
+    @Override
+    public String toString() {
+        return this.getClass().getName();
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/FooException.java b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/FooException.java
new file mode 100644
index 0000000..3270476
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/jdk/test/internal/foo/FooException.java
@@ -0,0 +1,29 @@
+/*
+ * 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 jdk.test.internal.foo;
+
+public class FooException extends RuntimeException {
+    public FooException() {
+    }
+}
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
new file mode 100644
index 0000000..75c2d33
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 test {
+    requires m1;
+    requires m3;   // requires public m2
+
+    exports jdk.test;
+}
diff --git a/jdk/test/java/net/Authenticator/B4933582.sh b/jdk/test/java/net/Authenticator/B4933582.sh
index c696f41..728de44a 100644
--- a/jdk/test/java/net/Authenticator/B4933582.sh
+++ b/jdk/test/java/net/Authenticator/B4933582.sh
@@ -43,8 +43,12 @@
     exit 1;
     ;;
 esac
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \
+
+EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED,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} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 first
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 second
+${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/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.java b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.java
index df4d9b0..fe6874b 100644
--- a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.java
+++ b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.java
@@ -25,8 +25,8 @@
  * @bug 4132931
  * @summary DatagramSocket should use a factory for its impl
  *
- * @build ADatagramSocket
- * @run shell ADatagramSocket.sh
+ * @compile/module=java.base java/net/MyDatagramSocketImplFactory.java
+ * @run main ADatagramSocket
  */
 import java.io.*;
 import java.net.*;
diff --git a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh
deleted file mode 100644
index eac0315..0000000
--- a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#! /bin/sh
-
-#
-# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Darwin | AIX )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  Linux )
-    PATHSEP=":"
-    FILESEP="/"
-    ;;
-  CYGWIN* )
-    PATHSEP=";"
-    FILESEP="/"
-    ;;
-  Windows* )
-    PATHSEP=";"
-    FILESEP="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} -Xbootclasspath/p:${TESTCLASSES} ADatagramSocket true
diff --git a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java/net/MyDatagramSocketImplFactory.java b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java
similarity index 100%
rename from jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java/net/MyDatagramSocketImplFactory.java
rename to jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java
diff --git a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java
index 6659cd8..7d8646d 100644
--- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java
+++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java
@@ -24,8 +24,8 @@
 /* @test
  * @bug 8081678 8131155
  * @summary Tests for stream returning methods
- * @library ../../util/stream/bootlib/java.base
- * @build java.util.stream.OpTestCase
+ * @library ../../util/stream/bootlib
+ * @build java.base/java.util.stream.OpTestCase
  * @run testng/othervm NetworkInterfaceStreamTest
  * @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest
  * @key intermittent
diff --git a/jdk/test/java/net/URI/URItoURLTest.java b/jdk/test/java/net/URI/URItoURLTest.java
index 05fadeb..0b97f24 100644
--- a/jdk/test/java/net/URI/URItoURLTest.java
+++ b/jdk/test/java/net/URI/URItoURLTest.java
@@ -38,9 +38,7 @@
 
     public static void main(String args[]) throws Exception {
 
-        URItoURLTest testClass = new URItoURLTest();
-        URL classUrl = testClass.getClass().
-                                    getResource("/java/lang/Object.class");
+        URL classUrl = new URL("jrt:/java.base/java/lang/Object.class");
 
         String[] uris = {
                         "mailto:xyz@abc.de",
diff --git a/jdk/test/java/net/URLPermission/nstest/lookup.sh b/jdk/test/java/net/URLPermission/nstest/lookup.sh
index eefd73c..ac00c50 100644
--- a/jdk/test/java/net/URLPermission/nstest/lookup.sh
+++ b/jdk/test/java/net/URLPermission/nstest/lookup.sh
@@ -24,6 +24,7 @@
 
 # @test
 # @library /lib/testlibrary
+# @modules java.base/sun.net.spi.nameservice
 # @build jdk.testlibrary.*
 # @compile -XDignore.symbol.file=true SimpleNameService.java
 #            LookupTest.java SimpleNameServiceDescriptor.java
@@ -57,6 +58,7 @@
 POLICY
 
 ${TESTJAVA}/bin/java ${TESTVMOPTS} \
+    -XaddExports:java.base/sun.net.spi.nameservice=ALL-UNNAMED \
     -Djava.security.policy=file:./policy \
     -Dsun.net.spi.nameservice.provider.1=simple,sun \
     -cp ${TESTCLASSPATH}${PS}${TESTSRC} LookupTest -runtest ${port}
diff --git a/jdk/test/java/net/httpclient/whitebox/Driver.java b/jdk/test/java/net/httpclient/whitebox/Driver.java
new file mode 100644
index 0000000..fbbdb05
--- /dev/null
+++ b/jdk/test/java/net/httpclient/whitebox/Driver.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8151299
+ * @run testng java.httpclient/java.net.http.SelectorTest
+ */
diff --git a/jdk/test/java/net/httpclient/whitebox/TEST.properties b/jdk/test/java/net/httpclient/whitebox/TEST.properties
deleted file mode 100644
index 1d78475..0000000
--- a/jdk/test/java/net/httpclient/whitebox/TEST.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-TestNG.dirs = .
-
-bootclasspath.dirs = /java/net/httpclient
diff --git a/jdk/test/java/net/httpclient/whitebox/java.httpclient/java/net/http/SelectorTest.java b/jdk/test/java/net/httpclient/whitebox/java.httpclient/java/net/http/SelectorTest.java
new file mode 100644
index 0000000..001e7a4
--- /dev/null
+++ b/jdk/test/java/net/httpclient/whitebox/java.httpclient/java/net/http/SelectorTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+package java.net.http;
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import org.testng.annotations.Test;
+
+/**
+ * Whitebox test of selector mechanics. Currently only a simple test
+ * setting one read and one write event is done. It checks that the
+ * write event occurs first, followed by the read event and then no
+ * further events occur despite the conditions actually still existing.
+ */
+@Test
+public class SelectorTest {
+
+    AtomicInteger counter = new AtomicInteger();
+    volatile boolean error;
+    static final CountDownLatch finishingGate = new CountDownLatch(1);
+
+    String readSomeBytes(RawChannel chan) {
+        try {
+            ByteBuffer buf = ByteBuffer.allocate(1024);
+            int t = chan.read(buf);
+            if (t <= 0) {
+                out.printf("chan read returned %d\n", t);
+                return null;
+            }
+            byte[] bb = new byte[t];
+            buf.get(bb);
+            return new String(bb, US_ASCII);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    @Test(timeOut = 10000)
+    public void test() throws Exception {
+
+        try (ServerSocket server = new ServerSocket(0)) {
+            int port = server.getLocalPort();
+
+            out.println("Listening on port " + server.getLocalPort());
+
+            TestServer t = new TestServer(server);
+            t.start();
+            out.println("Started server thread");
+
+            final RawChannel chan = getARawChannel(port);
+
+            chan.registerEvent(new RawChannel.NonBlockingEvent() {
+                @Override
+                public int interestOps() {
+                    return SelectionKey.OP_READ;
+                }
+
+                @Override
+                public void handle() {
+                    readSomeBytes(chan);
+                    out.printf("OP_READ\n");
+                    if (counter.get() != 1) {
+                        out.printf("OP_READ error counter = %d\n", counter);
+                        error = true;
+                    }
+                }
+            });
+
+            chan.registerEvent(new RawChannel.NonBlockingEvent() {
+                @Override
+                public int interestOps() {
+                    return SelectionKey.OP_WRITE;
+                }
+
+                @Override
+                public void handle() {
+                    out.printf("OP_WRITE\n");
+                    if (counter.get() != 0) {
+                        out.printf("OP_WRITE error counter = %d\n", counter);
+                        error = true;
+                    } else {
+                        ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT);
+                        counter.incrementAndGet();
+                        try {
+                            chan.write(bb);
+                        } catch (IOException e) {
+                            throw new UncheckedIOException(e);
+                        }
+                    }
+                }
+
+            });
+            out.println("Events registered. Waiting");
+            finishingGate.await(30, SECONDS);
+            if (error)
+                throw new RuntimeException("Error");
+            else
+                out.println("No error");
+        }
+    }
+
+    static RawChannel getARawChannel(int port) throws Exception {
+        URI uri = URI.create("http://127.0.0.1:" + port + "/");
+        out.println("client connecting to " + uri.toString());
+        HttpRequest req = HttpRequest.create(uri).GET();
+        HttpResponse r = req.response();
+        r.body(HttpResponse.ignoreBody());
+        return ((HttpResponseImpl) r).rawChannel();
+    }
+
+    static class TestServer extends Thread {
+        static final byte[] INPUT = "Hello world".getBytes(US_ASCII);
+        static final byte[] OUTPUT = "Goodbye world".getBytes(US_ASCII);
+        static final String FIRST_RESPONSE = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n";
+        final ServerSocket server;
+
+        TestServer(ServerSocket server) throws IOException {
+            this.server = server;
+        }
+
+        public void run() {
+            try (Socket s = server.accept();
+                 InputStream is = s.getInputStream();
+                 OutputStream os = s.getOutputStream()) {
+
+                out.println("Got connection");
+                readRequest(is);
+                os.write(FIRST_RESPONSE.getBytes());
+                read(is);
+                write(os);
+                Thread.sleep(1000);
+                // send some more data, and make sure WRITE op does not get called
+                write(os);
+                out.println("TestServer exiting");
+                SelectorTest.finishingGate.countDown();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        // consumes the HTTP request
+        static void readRequest(InputStream is) throws IOException {
+            out.println("starting readRequest");
+            byte[] buf = new byte[1024];
+            String s = "";
+            while (true) {
+                int n = is.read(buf);
+                if (n <= 0)
+                    throw new IOException("Error");
+                s = s + new String(buf, 0, n);
+                if (s.indexOf("\r\n\r\n") != -1)
+                    break;
+            }
+            out.println("returning from readRequest");
+        }
+
+        static void read(InputStream is) throws IOException {
+            out.println("starting read");
+            for (int i = 0; i < INPUT.length; i++) {
+                int c = is.read();
+                if (c == -1)
+                    throw new IOException("closed");
+                if (INPUT[i] != (byte) c)
+                    throw new IOException("Error. Expected:" + INPUT[i] + ", got:" + c);
+            }
+            out.println("returning from read");
+        }
+
+        static void write(OutputStream os) throws IOException {
+            out.println("doing write");
+            os.write(OUTPUT);
+        }
+    }
+}
diff --git a/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java b/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java
deleted file mode 100644
index 74ef4ff..0000000
--- a/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java
+++ /dev/null
@@ -1,208 +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.
- */
-
-/**
- * @test
- * @bug 8151299
- * @summary Http client SelectorManager overwriting read and write events
- */
-package java.net.http;
-
-import java.net.*;
-import java.io.*;
-import java.nio.channels.*;
-import java.nio.ByteBuffer;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicInteger;
-import static java.lang.System.out;
-import static java.nio.charset.StandardCharsets.US_ASCII;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import org.testng.annotations.Test;
-
-/**
- * Whitebox test of selector mechanics. Currently only a simple test
- * setting one read and one write event is done. It checks that the
- * write event occurs first, followed by the read event and then no
- * further events occur despite the conditions actually still existing.
- */
-@Test
-public class SelectorTest {
-
-    AtomicInteger counter = new AtomicInteger();
-    volatile boolean error;
-    static final CountDownLatch finishingGate = new CountDownLatch(1);
-
-    String readSomeBytes(RawChannel chan) {
-        try {
-            ByteBuffer buf = ByteBuffer.allocate(1024);
-            int t = chan.read(buf);
-            if (t <= 0) {
-                out.printf("chan read returned %d\n", t);
-                return null;
-            }
-            byte[] bb = new byte[t];
-            buf.get(bb);
-            return new String(bb, US_ASCII);
-        } catch (IOException ioe) {
-            throw new UncheckedIOException(ioe);
-        }
-    }
-
-    @Test(timeOut = 10000)
-    public void test() throws Exception {
-
-        try (ServerSocket server = new ServerSocket(0)) {
-            int port = server.getLocalPort();
-
-            out.println("Listening on port " + server.getLocalPort());
-
-            TestServer t = new TestServer(server);
-            t.start();
-            out.println("Started server thread");
-
-            final RawChannel chan = getARawChannel(port);
-
-            chan.registerEvent(new RawChannel.NonBlockingEvent() {
-                @Override
-                public int interestOps() {
-                    return SelectionKey.OP_READ;
-                }
-
-                @Override
-                public void handle() {
-                    readSomeBytes(chan);
-                    out.printf("OP_READ\n");
-                    if (counter.get() != 1) {
-                        out.printf("OP_READ error counter = %d\n", counter);
-                        error = true;
-                    }
-                }
-            });
-
-            chan.registerEvent(new RawChannel.NonBlockingEvent() {
-                @Override
-                public int interestOps() {
-                    return SelectionKey.OP_WRITE;
-                }
-
-                @Override
-                public void handle() {
-                    out.printf("OP_WRITE\n");
-                    if (counter.get() != 0) {
-                        out.printf("OP_WRITE error counter = %d\n", counter);
-                        error = true;
-                    } else {
-                        ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT);
-                        counter.incrementAndGet();
-                        try {
-                            chan.write(bb);
-                        } catch (IOException e) {
-                            throw new UncheckedIOException(e);
-                        }
-                    }
-                }
-
-            });
-            out.println("Events registered. Waiting");
-            finishingGate.await(30, SECONDS);
-            if (error)
-                throw new RuntimeException("Error");
-            else
-                out.println("No error");
-        }
-    }
-
-    static RawChannel getARawChannel(int port) throws Exception {
-        URI uri = URI.create("http://127.0.0.1:" + port + "/");
-        out.println("client connecting to " + uri.toString());
-        HttpRequest req = HttpRequest.create(uri).GET();
-        HttpResponse r = req.response();
-        r.body(HttpResponse.ignoreBody());
-        return ((HttpResponseImpl) r).rawChannel();
-    }
-
-    static class TestServer extends Thread {
-        static final byte[] INPUT = "Hello world".getBytes(US_ASCII);
-        static final byte[] OUTPUT = "Goodbye world".getBytes(US_ASCII);
-        static final String FIRST_RESPONSE = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n";
-        final ServerSocket server;
-
-        TestServer(ServerSocket server) throws IOException {
-            this.server = server;
-        }
-
-        public void run() {
-            try (Socket s = server.accept();
-                 InputStream is = s.getInputStream();
-                 OutputStream os = s.getOutputStream()) {
-
-                out.println("Got connection");
-                readRequest(is);
-                os.write(FIRST_RESPONSE.getBytes());
-                read(is);
-                write(os);
-                Thread.sleep(1000);
-                // send some more data, and make sure WRITE op does not get called
-                write(os);
-                out.println("TestServer exiting");
-                SelectorTest.finishingGate.countDown();
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-
-        // consumes the HTTP request
-        static void readRequest(InputStream is) throws IOException {
-            out.println("starting readRequest");
-            byte[] buf = new byte[1024];
-            String s = "";
-            while (true) {
-                int n = is.read(buf);
-                if (n <= 0)
-                    throw new IOException("Error");
-                s = s + new String(buf, 0, n);
-                if (s.indexOf("\r\n\r\n") != -1)
-                    break;
-            }
-            out.println("returning from readRequest");
-        }
-
-        static void read(InputStream is) throws IOException {
-            out.println("starting read");
-            for (int i = 0; i < INPUT.length; i++) {
-                int c = is.read();
-                if (c == -1)
-                    throw new IOException("closed");
-                if (INPUT[i] != (byte) c)
-                    throw new IOException("Error. Expected:" + INPUT[i] + ", got:" + c);
-            }
-            out.println("returning from read");
-        }
-
-        static void write(OutputStream os) throws IOException {
-            out.println("doing write");
-            os.write(OUTPUT);
-        }
-    }
-}
diff --git a/jdk/test/java/nio/Buffer/LimitDirectMemory.sh b/jdk/test/java/nio/Buffer/LimitDirectMemory.sh
index f2e7a93..372dc05 100644
--- a/jdk/test/java/nio/Buffer/LimitDirectMemory.sh
+++ b/jdk/test/java/nio/Buffer/LimitDirectMemory.sh
@@ -27,8 +27,8 @@
 # @bug 4627316 6743526
 # @summary Test option to limit direct memory allocation
 #
+# @requires (os.arch == "x86_64") | (os.arch == "amd64") | (os.arch == "sparcv9")
 # @build LimitDirectMemory
-# @ignore JDK-8129343
 # @run shell LimitDirectMemory.sh
 
 TMP1=tmp_$$
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 8c63550..371b62f 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} $DFLAG $1 $2 $3 $4 $5 $6 $7 $8" 2>&1
+    sh -xc "$JAVA ${TESTVMOPTS} -XaddExports: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/Files/StreamLinesTest.java b/jdk/test/java/nio/file/Files/StreamLinesTest.java
index 4f45026..aa4c9ba 100644
--- a/jdk/test/java/nio/file/Files/StreamLinesTest.java
+++ b/jdk/test/java/nio/file/Files/StreamLinesTest.java
@@ -23,8 +23,8 @@
 
 /* @test
  * @bug 8072773
- * @library /lib/testlibrary/ ../../../util/stream/bootlib/java.base
- * @build java.util.stream.OpTestCase
+ * @library /lib/testlibrary/ ../../../util/stream/bootlib
+ * @build java.base/java.util.stream.OpTestCase
  * @build jdk.testlibrary.RandomFactory
  * @run testng/othervm StreamLinesTest
  * @summary Tests streams returned from Files.lines, primarily focused on
diff --git a/jdk/test/java/nio/file/spi/SetDefaultProvider.java b/jdk/test/java/nio/file/spi/SetDefaultProvider.java
index bcb0ae2..10629f8 100644
--- a/jdk/test/java/nio/file/spi/SetDefaultProvider.java
+++ b/jdk/test/java/nio/file/spi/SetDefaultProvider.java
@@ -25,7 +25,6 @@
  * @bug 4313887 7006126
  * @summary Unit test for java.nio.file.spi.FileSystemProvider
  * @build TestProvider SetDefaultProvider
- * @ignore JDK-8129343
  * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider SetDefaultProvider
  */
 
diff --git a/jdk/test/java/nio/file/spi/TestProvider.java b/jdk/test/java/nio/file/spi/TestProvider.java
index b2744f4..f0538e5 100644
--- a/jdk/test/java/nio/file/spi/TestProvider.java
+++ b/jdk/test/java/nio/file/spi/TestProvider.java
@@ -21,20 +21,34 @@
  * questions.
  */
 
-import java.nio.file.spi.FileSystemProvider;
+import java.io.File;
 import java.nio.file.*;
-import java.nio.file.attribute.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.UserPrincipalLookupService;
+import java.nio.file.spi.FileSystemProvider;
 import java.nio.channels.SeekableByteChannel;
 import java.net.URI;
-import java.util.*;
 import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 
 public class TestProvider extends FileSystemProvider {
 
-    private final FileSystem theFileSystem;
+    private final FileSystemProvider defaultProvider;
+    private final TestFileSystem theFileSystem;
 
     public TestProvider(FileSystemProvider defaultProvider) {
-        theFileSystem = new TestFileSystem(this);
+        this.defaultProvider = defaultProvider;
+        FileSystem fs = defaultProvider.getFileSystem(URI.create("file:/"));
+        this.theFileSystem = new TestFileSystem(fs, this);
+    }
+
+    FileSystemProvider defaultProvider() {
+        return defaultProvider;
     }
 
     @Override
@@ -43,8 +57,8 @@
     }
 
     @Override
-    public FileSystem newFileSystem(URI uri, Map<String,?> env) {
-        throw new RuntimeException("not implemented");
+    public FileSystem newFileSystem(URI uri, Map<String,?> env) throws IOException {
+        return defaultProvider.newFileSystem(uri, env);
     }
 
     @Override
@@ -54,7 +68,8 @@
 
     @Override
     public Path getPath(URI uri) {
-        throw new RuntimeException("not implemented");
+        Path path = defaultProvider.getPath(uri);
+        return theFileSystem.wrap(path);
     }
 
     @Override
@@ -62,7 +77,7 @@
                              LinkOption... options)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
@@ -70,7 +85,8 @@
                                              LinkOption... options)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        Path delegate = theFileSystem.unwrap(file);
+        return defaultProvider.readAttributes(delegate, attributes, options);
     }
 
     @Override
@@ -79,7 +95,8 @@
                                                             LinkOption... options)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        Path delegate = theFileSystem.unwrap(file);
+        return defaultProvider.readAttributes(delegate, type, options);
     }
 
     @Override
@@ -87,45 +104,46 @@
                                                                 Class<V> type,
                                                                 LinkOption... options)
     {
-        throw new RuntimeException("not implemented");
+        Path delegate = theFileSystem.unwrap(file);
+        return defaultProvider.getFileAttributeView(delegate, type, options);
     }
 
-
     @Override
     public void delete(Path file) throws IOException {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
     public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
     public void createLink(Path link, Path existing) throws IOException {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
     public Path readSymbolicLink(Path link) throws IOException {
-        throw new RuntimeException("not implemented");
+        Path delegate = theFileSystem.unwrap(link);
+        Path target = defaultProvider.readSymbolicLink(delegate);
+        return theFileSystem.wrap(target);
     }
 
-
     @Override
     public void copy(Path source, Path target, CopyOption... options)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
     public void move(Path source, Path target, CopyOption... options)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
@@ -140,7 +158,7 @@
     public void createDirectory(Path dir, FileAttribute<?>... attrs)
         throws IOException
     {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
@@ -149,13 +167,18 @@
                                               FileAttribute<?>... attrs)
         throws IOException
     {
+        if (options.contains(StandardOpenOption.READ) && options.size() == 1) {
+            Path delegate = theFileSystem.unwrap(file);
+            options = Collections.singleton(StandardOpenOption.READ);
+            return defaultProvider.newByteChannel(delegate, options, attrs);
+        }
+
         throw new RuntimeException("not implemented");
     }
 
-
     @Override
     public boolean isHidden(Path file) throws IOException {
-        throw new RuntimeException("not implemented");
+        throw new ReadOnlyFileSystemException();
     }
 
     @Override
@@ -176,12 +199,26 @@
     }
 
     static class TestFileSystem extends FileSystem {
+        private final FileSystem delegate;
         private final TestProvider provider;
 
-        TestFileSystem(TestProvider provider) {
+        TestFileSystem(FileSystem delegate, TestProvider provider) {
+            this.delegate = delegate;
             this.provider = provider;
         }
 
+        Path wrap(Path path) {
+            return (path != null) ? new TestPath(this, path) : null;
+        }
+
+        Path unwrap(Path wrapper) {
+            if (wrapper == null)
+                throw new NullPointerException();
+            if (!(wrapper instanceof TestPath))
+                throw new ProviderMismatchException();
+            return ((TestPath)wrapper).unwrap();
+        }
+
         @Override
         public FileSystemProvider provider() {
             return provider;
@@ -194,17 +231,17 @@
 
         @Override
         public boolean isOpen() {
-            throw new RuntimeException("not implemented");
+            return true;
         }
 
         @Override
         public boolean isReadOnly() {
-            throw new RuntimeException("not implemented");
+            return true;
         }
 
         @Override
         public String getSeparator() {
-            throw new RuntimeException("not implemented");
+            return delegate.getSeparator();
         }
 
         @Override
@@ -219,27 +256,209 @@
 
         @Override
         public Set<String> supportedFileAttributeViews() {
-            throw new RuntimeException("not implemented");
+            return delegate.supportedFileAttributeViews();
         }
 
         @Override
         public Path getPath(String first, String... more) {
-            throw new RuntimeException("not implemented");
+            Path path = delegate.getPath(first, more);
+            return wrap(path);
         }
 
         @Override
         public PathMatcher getPathMatcher(String syntaxAndPattern) {
-            throw new RuntimeException("not implemented");
+            return delegate.getPathMatcher(syntaxAndPattern);
         }
 
         @Override
         public UserPrincipalLookupService getUserPrincipalLookupService() {
-            throw new RuntimeException("not implemented");
+            return delegate.getUserPrincipalLookupService();
         }
 
         @Override
         public WatchService newWatchService() throws IOException {
-            throw new RuntimeException("not implemented");
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    static class TestPath implements Path {
+        private final TestFileSystem fs;
+        private final Path delegate;
+
+        TestPath(TestFileSystem fs, Path delegate) {
+            this.fs = fs;
+            this.delegate = delegate;
+        }
+
+        Path unwrap() {
+            return delegate;
+        }
+
+        @Override
+        public FileSystem getFileSystem() {
+            return fs;
+        }
+
+        @Override
+        public boolean isAbsolute() {
+            return delegate.isAbsolute();
+        }
+
+        @Override
+        public Path getRoot() {
+            return fs.wrap(delegate.getRoot());
+        }
+
+        @Override
+        public Path getParent() {
+            return fs.wrap(delegate.getParent());
+        }
+
+        @Override
+        public int getNameCount() {
+            return delegate.getNameCount();
+        }
+
+        @Override
+        public Path getFileName() {
+            return fs.wrap(delegate.getFileName());
+        }
+
+        @Override
+        public Path getName(int index) {
+            return fs.wrap(delegate.getName(index));
+        }
+
+        @Override
+        public Path subpath(int beginIndex, int endIndex) {
+            return fs.wrap(delegate.subpath(beginIndex, endIndex));
+        }
+
+        @Override
+        public boolean startsWith(Path other) {
+            return delegate.startsWith(fs.unwrap(other));
+        }
+
+        @Override
+        public boolean startsWith(String other) {
+            return delegate.startsWith(other);
+        }
+
+        @Override
+        public boolean endsWith(Path other) {
+            return delegate.endsWith(fs.unwrap(other));
+        }
+
+        @Override
+        public boolean endsWith(String other) {
+            return delegate.endsWith(other);
+        }
+
+        @Override
+        public Path normalize() {
+            return fs.wrap(delegate.normalize());
+        }
+
+        @Override
+        public Path resolve(Path other) {
+            return fs.wrap(delegate.resolve(fs.unwrap(other)));
+        }
+
+        @Override
+        public Path resolve(String other) {
+            return fs.wrap(delegate.resolve(other));
+        }
+
+        @Override
+        public Path resolveSibling(Path other) {
+            return fs.wrap(delegate.resolveSibling(fs.unwrap(other)));
+        }
+
+        @Override
+        public Path resolveSibling(String other) {
+            return fs.wrap(delegate.resolveSibling(other));
+        }
+
+        @Override
+        public Path relativize(Path other) {
+            return fs.wrap(delegate.relativize(fs.unwrap(other)));
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof TestPath))
+                return false;
+            return delegate.equals(fs.unwrap((TestPath) other));
+        }
+
+        @Override
+        public int hashCode() {
+            return delegate.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+        @Override
+        public URI toUri() {
+            String ssp = delegate.toUri().getSchemeSpecificPart();
+            return URI.create(fs.provider().getScheme() + ":" + ssp);
+        }
+
+        @Override
+        public Path toAbsolutePath() {
+            return fs.wrap(delegate.toAbsolutePath());
+        }
+
+        @Override
+        public Path toRealPath(LinkOption... options) throws IOException {
+            return fs.wrap(delegate.toRealPath(options));
+        }
+
+        @Override
+        public File toFile() {
+            return delegate.toFile();
+        }
+
+        @Override
+        public Iterator<Path> iterator() {
+            final Iterator<Path> itr = delegate.iterator();
+            return new Iterator<Path>() {
+                @Override
+                public boolean hasNext() {
+                    return itr.hasNext();
+                }
+                @Override
+                public Path next() {
+                    return fs.wrap(itr.next());
+                }
+                @Override
+                public void remove() {
+                    itr.remove();
+                }
+            };
+        }
+
+        @Override
+        public int compareTo(Path other) {
+            return delegate.compareTo(fs.unwrap(other));
+        }
+
+        @Override
+        public WatchKey register(WatchService watcher,
+                                 WatchEvent.Kind<?>[] events,
+                                 WatchEvent.Modifier... modifiers)
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public  WatchKey register(WatchService watcher,
+                                  WatchEvent.Kind<?>... events)
+        {
+            throw new UnsupportedOperationException();
         }
     }
 }
diff --git a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh
index 3b6143f..70e9c2b 100644
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh
@@ -51,5 +51,6 @@
 mkdir -p ext
 $COMPILEJAVA/bin/jar ${TESTTOOLVMOPTS} cf ext/ext.jar -C $TESTCLASSES ExtLoadedImpl.class -C $TESTCLASSES ExtLoadedImpl_Stub.class -C $TESTCLASSES CheckLoader.class
 
+TESTVMOPTS="${TESTVMOPTS}  -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
 $TESTJAVA/bin/java ${TESTVMOPTS} -cp classes -Dtest.src=$TESTSRC -Dtest.classes=$TESTCLASSES -Djava.security.policy=$TESTSRC/security.policy -Djava.ext.dirs=ext ExtLoadedImplTest
 
diff --git a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java
index 2752d72..1b2288c 100644
--- a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java
+++ b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -41,13 +41,19 @@
  * @run main/othervm/policy=security.policy/timeout=240 DownloadActivationGroup
  */
 
-import java.io.*;
-import java.rmi.*;
-import java.net.*;
-import java.rmi.activation.*;
-import java.rmi.server.*;
-import java.rmi.registry.*;
-import java.util.Vector;
+import java.net.URL;
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.activation.Activatable;
+import java.rmi.activation.ActivationDesc;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationGroup;
+import java.rmi.activation.ActivationGroupDesc;
+import java.rmi.activation.ActivationGroupDesc.CommandEnvironment;
+import java.rmi.activation.ActivationGroupID;
+import java.rmi.activation.ActivationID;
+import java.rmi.server.UnicastRemoteObject;
 import java.util.Properties;
 
 public class DownloadActivationGroup
@@ -130,11 +136,16 @@
 
             Properties p = new Properties();
             p.put("java.security.policy", TestParams.defaultGroupPolicy);
+            CommandEnvironment cmd = new ActivationGroupDesc.CommandEnvironment(
+                    null,
+                    new String[] { "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
+                            + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
+                            + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
 
             ActivationGroupDesc groupDesc =
                 new ActivationGroupDesc("MyActivationGroupImpl",
                                         groupURL.toExternalForm(),
-                                        null, p, null);
+                                        null, p, cmd);
             ActivationGroupID groupID =
                 ActivationGroup.getSystem().registerGroup(groupDesc);
 
diff --git a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java
index 9de4500..2ee592f 100644
--- a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java
+++ b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -37,14 +37,20 @@
  * @run main/othervm/java.security.policy=security.policy/secure=java.lang.SecurityManager/timeout=240 StubClassesPermitted
  */
 
-import java.io.*;
-import java.rmi.*;
-import java.rmi.server.*;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.rmi.activation.Activatable;
+import java.rmi.activation.ActivationDesc;
+import java.rmi.activation.ActivationGroup;
+import java.rmi.activation.ActivationGroupDesc;
+import java.rmi.activation.ActivationGroupDesc.CommandEnvironment;
+import java.rmi.activation.ActivationGroupID;
+import java.rmi.activation.ActivationID;
+import java.rmi.activation.ActivationSystem;
 import java.rmi.registry.Registry;
-import java.rmi.activation.*;
-import java.security.CodeSource;
 import java.util.Properties;
-import java.util.StringTokenizer;
 
 /**
  * The RMI activation system needs to explicitly allow itself to
@@ -113,8 +119,13 @@
             // sun.rmi.server.Activation$ActivationMonitorImpl_Stub
             //
             System.err.println("Create activation group, in a new VM");
+            CommandEnvironment cmd = new ActivationGroupDesc.CommandEnvironment(null,
+                    new String[] { "-XaddExports:java.base/sun.security.provider=ALL-UNNAMED,"
+                            + "java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,"
+                            + "java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
+
             ActivationGroupDesc groupDesc =
-                new ActivationGroupDesc(p, null);
+                new ActivationGroupDesc(p, cmd);
             ActivationSystem system = ActivationGroup.getSystem();
             ActivationGroupID groupID = system.registerGroup(groupDesc);
 
diff --git a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/rmid.security.policy b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/rmid.security.policy
index 2737974..0c1df59 100644
--- a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/rmid.security.policy
+++ b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/rmid.security.policy
@@ -1,4 +1,7 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=java.lang.SecurityManager";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+
+    // test needs to export a set of internal APIs to access them from unamed module
+    permission com.sun.rmi.rmid.ExecOptionPermission "*";
 };
diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
index 37f9508..72911b9 100644
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
@@ -105,9 +105,9 @@
             RMID.removeLog();
             rmid = RMID.createRMID(System.out, System.err, true, true,
                                    TestLibrary.INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT);
-            rmid.addOptions(new String[]{
-                "-Djava.nio.channels.spi.SelectorProvider=" +
-                "InheritedChannelNotServerSocket$SP"});
+            rmid.addOptions(
+                "-XaddExports:java.base/sun.nio.ch=ALL-UNNAMED",
+                "-Djava.nio.channels.spi.SelectorProvider=InheritedChannelNotServerSocket$SP");
             rmid.start();
 
             /*
diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java
index e34af8c..2501849 100644
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java
@@ -92,8 +92,9 @@
             RMID.removeLog();
             rmid = RMID.createRMID(System.out, System.err, true, false,
                                    TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT);
-            rmid.addOptions(new String[]{
-                "-Djava.nio.channels.spi.SelectorProvider=RmidViaInheritedChannel$RmidSelectorProvider"});
+            rmid.addOptions(
+                "-XaddExports: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."))
             {
diff --git a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
index bc1c2dc..f30be86 100644
--- a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
+++ b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
@@ -30,6 +30,7 @@
  * rather than pinning it indefinitely.
  * @author Peter Jones
  *
+ * @modules java.rmi/sun.rmi.transport
  * @build DGCAckFailure DGCAckFailure_Stub
  * @run main/othervm DGCAckFailure
  */
diff --git a/jdk/test/java/rmi/registry/readTest/readTest.sh b/jdk/test/java/rmi/registry/readTest/readTest.sh
index f397b44..5c5490e 100644
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh
+++ b/jdk/test/java/rmi/registry/readTest/readTest.sh
@@ -23,6 +23,10 @@
 
 # @test
 # @bug 7102369 7094468 7100592
+# @modules java.rmi/sun.rmi.registry
+#          java.rmi/sun.rmi.server
+#          java.rmi/sun.rmi.transport
+#          java.rmi/sun.rmi.transport.tcp
 # @library ../../testlibrary
 # @build TestLibrary
 # @summary remove java.rmi.server.codebase property parsing from registyimpl
@@ -94,6 +98,7 @@
     ;;
 esac
 # trailing / after code base is important for rmi codebase property.
+TESTVMOPTS="${TESTVMOPTS}  -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp $TEST_CLASSPATH ${ARGS} -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 &
 TEST_PID=$!
 #bulk of testcase - let it run for a while
diff --git a/jdk/test/java/rmi/reliability/benchmark/bench/HtmlReporter.java b/jdk/test/java/rmi/reliability/benchmark/bench/HtmlReporter.java
index d305932..d0d302e 100644
--- a/jdk/test/java/rmi/reliability/benchmark/bench/HtmlReporter.java
+++ b/jdk/test/java/rmi/reliability/benchmark/bench/HtmlReporter.java
@@ -41,7 +41,7 @@
     static final int PRECISION = 3;
     static final String[] PROPNAMES = { "os.name", "os.arch", "os.version",
         "java.home", "java.vm.version", "java.vm.vendor", "java.vm.name",
-        "java.compiler", "java.class.path", "sun.boot.class.path" };
+        "java.compiler", "java.class.path" };
 
     OutputStream out;
     String title;
diff --git a/jdk/test/java/rmi/reliability/benchmark/bench/TextReporter.java b/jdk/test/java/rmi/reliability/benchmark/bench/TextReporter.java
index 89d35a6..5ce3af7 100644
--- a/jdk/test/java/rmi/reliability/benchmark/bench/TextReporter.java
+++ b/jdk/test/java/rmi/reliability/benchmark/bench/TextReporter.java
@@ -47,7 +47,7 @@
     static final int PROPNAME_WIDTH = 25;
     static final String[] PROPNAMES = { "os.name", "os.arch", "os.version",
         "java.home", "java.vm.version", "java.vm.vendor", "java.vm.name",
-        "java.compiler", "java.class.path", "sun.boot.class.path" };
+        "java.compiler", "java.class.path" };
 
     OutputStream out;
     String title;
diff --git a/jdk/test/java/rmi/testlibrary/JavaVM.java b/jdk/test/java/rmi/testlibrary/JavaVM.java
index b0c4afd..37faa1e 100644
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java
@@ -78,7 +78,7 @@
     }
 
     // Prepends passed opts array to current options
-    public void addOptions(String[] opts) {
+    public void addOptions(String... opts) {
         String newOpts = "";
         for (int i = 0 ; i < opts.length ; i ++) {
             newOpts += " " + opts[i];
@@ -88,7 +88,7 @@
     }
 
     // Prepends passed arguments array to current args
-    public void addArguments(String[] arguments) {
+    public void addArguments(String... arguments) {
         String newArgs = "";
         for (int i = 0 ; i < arguments.length ; i ++) {
             newArgs += " " + arguments[i];
diff --git a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java
index b9c8f98..1dc6d1f 100644
--- a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java
+++ b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java
@@ -123,6 +123,9 @@
                                     propOption + property +
                                     equal +
                                     propertyValue + extraProp +
+                                    " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
+                                    + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
+                                    + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                                     " -Drmi.registry.port=" +
                                     REGISTRY_PORT,
                                     "");
diff --git a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
index 7cddcd7..a02e6a3 100644
--- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
@@ -74,6 +74,10 @@
         try {
             String options = " -Djava.security.policy=" +
                 TestParams.defaultPolicy +
+                " -XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED," +
+                "java.rmi/sun.rmi.server=ALL-UNNAMED," +
+                "java.rmi/sun.rmi.transport=ALL-UNNAMED," +
+                "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                 " -Djava.rmi.dgc.leaseValue=500000" +
                 "  -Dsun.rmi.dgc.checkInterval=" +
                 (HOLD_TARGET_TIME - 5000) +
diff --git a/jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java b/jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java
index e472ee3..63d962e 100644
--- a/jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java
+++ b/jdk/test/java/security/PermissionCollection/PermissionCollectionStreamTest.java
@@ -24,8 +24,8 @@
 /* @test
  * @bug 8081678
  * @summary Tests for stream returning methods
- * @library ../../util/stream/bootlib/java.base
- * @build java.util.stream.OpTestCase
+ * @library ../../util/stream/bootlib
+ * @build java.base/java.util.stream.OpTestCase
  * @run testng/othervm PermissionCollectionStreamTest
  */
 
diff --git a/jdk/test/java/security/Provider/DefaultProviderList.java b/jdk/test/java/security/Provider/DefaultProviderList.java
new file mode 100644
index 0000000..c283664
--- /dev/null
+++ b/jdk/test/java/security/Provider/DefaultProviderList.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7191662
+ * @summary Ensure non-java.base providers can be found by ServiceLoader
+ * @author Valerie Peng
+ */
+
+import java.util.*;
+import java.security.*;
+
+public class DefaultProviderList {
+
+    public static void main(String[] args) throws Exception {
+        Provider[] defaultProvs = Security.getProviders();
+        System.out.println("Providers: " + Arrays.asList(defaultProvs));
+        System.out.println();
+
+        ServiceLoader<Provider> sl = ServiceLoader.load(Provider.class);
+        boolean failed = false;
+        for (Provider p : defaultProvs) {
+            String pName = p.getName();
+            // only providers outside java.base are loaded by ServiceLoader
+            if (pName.equals("SUN") || pName.equals("SunRsaSign") ||
+                pName.equals("SunJCE") || pName.equals("SunJSSE")) {
+                System.out.println("Skip test for provider " + pName);
+                continue;
+            }
+            String pClassName = p.getClass().getName();
+            // Should be able to find each one through ServiceLoader
+            Iterator<Provider> provIter = sl.iterator();
+            boolean found = false;
+            while (provIter.hasNext()) {
+                Provider pFromSL = provIter.next();
+                if (pFromSL.getClass().getName().equals(pClassName)) {
+                    found = true;
+                    break;
+                }
+            }
+            System.out.println("Found " + p.getName() + " = " + found);
+            if (!found) {
+                failed = true;
+                System.out.println("Error: no provider class " + pClassName +
+                    " found");
+            }
+        }
+        if (!failed) {
+            System.out.println("Test Passed");
+        } else {
+            throw new Exception("One or more provider not loaded by SL");
+        }
+    }
+}
diff --git a/jdk/test/java/security/Provider/SecurityProviderModularTest.java b/jdk/test/java/security/Provider/SecurityProviderModularTest.java
new file mode 100644
index 0000000..bdde99f
--- /dev/null
+++ b/jdk/test/java/security/Provider/SecurityProviderModularTest.java
@@ -0,0 +1,337 @@
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Arrays;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.BeforeTest;
+
+/**
+ * @test
+ * @bug 8130360
+ * @library /lib/testlibrary
+ * @library /java/security/modules
+ * @modules java.base/jdk.internal.module
+ * @build CompilerUtils JarUtils
+ * @summary Test custom security provider module with all possible modular
+ *          condition. The test includes different combination of security
+ *          client/provider modules interaction with or without service
+ *          description.
+ * @run testng SecurityProviderModularTest
+ */
+public class SecurityProviderModularTest extends ModularTest {
+
+    private static final Path S_SRC = SRC.resolve("TestSecurityProvider.java");
+    private static final String S_PKG = "provider";
+    private static final String S_JAR_NAME = S_PKG + JAR_EXTN;
+    private static final String S_WITH_DESCR_JAR_NAME = S_PKG + DESCRIPTOR
+            + JAR_EXTN;
+    private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN;
+    private static final String MS_WITH_DESCR_JAR_NAME = MODULAR + S_PKG
+            + DESCRIPTOR + JAR_EXTN;
+
+    private static final Path C_SRC = SRC.resolve(
+            "TestSecurityProviderClient.java");
+    private static final String C_PKG = "client";
+    private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
+    private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR
+            + C_PKG + AUTO + JAR_EXTN;
+    private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
+
+    private static final Path BUILD_DIR = Paths.get(".").resolve("build");
+    private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin");
+    private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
+    private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve(
+            S_PKG + DESCRIPTOR);
+    private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG);
+    private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
+    private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
+
+    private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG);
+    private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME);
+    private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve(
+            S_WITH_DESCR_JAR_NAME);
+    private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(
+            MS_JAR_NAME);
+    private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve(
+            MS_WITH_DESCR_JAR_NAME);
+
+    private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
+    private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
+    private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
+    private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR
+            .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME);
+
+    private static final String MAIN = C_PKG + ".TestSecurityProviderClient";
+    private static final String S_INTERFACE = "java.security.Provider";
+    private static final String S_IMPL = S_PKG + ".TestSecurityProvider";
+    private static final List<String> M_REQUIRED = Arrays.asList("java.base");
+    private static final Path META_DESCR_PATH = Paths.get("META-INF")
+            .resolve("services").resolve(S_INTERFACE);
+    private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR
+            .resolve(META_DESCR_PATH);
+
+    private static final boolean WITH_S_DESCR = true;
+    private static final boolean WITHOUT_S_DESCR = false;
+    private static final String CLASS_NOT_FOUND_MSG = "NoClassDefFoundError:"
+            + " provider/TestSecurityProvider";
+    private static final String PROVIDER_NOT_FOUND_MSG = "Unable to find Test"
+            + " Security Provider";
+    private static final String CAN_NOT_ACCESS_MSG = "cannot access class";
+    private static final String NO_FAILURE = null;
+    private static final String SERVICE_LOADER = "SERVICE_LOADER";
+    private static final String CLASS_LOADER = "CLASS_LOADER";
+    private static final String SECURITY_PROP = "SECURITY_PROP";
+    private static final List<String> MECHANISMS = Arrays.asList(SERVICE_LOADER,
+            CLASS_LOADER, SECURITY_PROP);
+    private static final Path SECURE_PROP_EXTN = Paths.get("./java.secure.ext");
+
+    /**
+     * Generates Test specific input parameters.
+     */
+    @Override
+    public Object[][] getTestInput() {
+
+        List<List<Object>> params = new ArrayList<>();
+        MECHANISMS.stream().forEach((mechanism) -> {
+            boolean useCLoader = CLASS_LOADER.equals(mechanism);
+            boolean useSLoader = SERVICE_LOADER.equals(mechanism);
+            String[] args = new String[]{mechanism};
+            //PARAMETER ORDERS -
+            //client Module Type, Service Module Type,
+            //Service META Descriptor Required,
+            //Expected Failure message, mech used to find the provider
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
+                    WITHOUT_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
+                    WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
+                            : NO_FAILURE), args));
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
+                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
+                    WITH_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
+                            : NO_FAILURE), args));
+            params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
+                    WITHOUT_S_DESCR, ((useCLoader) ? CAN_NOT_ACCESS_MSG
+                            : ((useSLoader) ? PROVIDER_NOT_FOUND_MSG
+                                    : NO_FAILURE)), args));
+
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
+                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
+                    WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG
+                            : NO_FAILURE), args));
+
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
+                    WITHOUT_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
+                    WITHOUT_S_DESCR, CLASS_NOT_FOUND_MSG, args));
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
+                    WITH_S_DESCR, NO_FAILURE, args));
+            params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
+                    WITHOUT_S_DESCR, ((useSLoader) ? PROVIDER_NOT_FOUND_MSG
+                            : NO_FAILURE), args));
+        });
+        return params.stream().map(p -> p.toArray()).toArray(Object[][]::new);
+    }
+
+    /**
+     * Pre-compile and generate the artifacts required to run this test before
+     * running each test cases.
+     */
+    @BeforeTest
+    public void buildArtifacts() {
+
+        boolean done = true;
+        try {
+
+            done &= CompilerUtils.compile(S_SRC, S_BUILD_DIR);
+            done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR);
+            done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL);
+            //Generate regular/modular jars with(out) META-INF
+            //Service descriptor
+            generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR,
+                    S_WITH_META_DESCR_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR,
+                    S_WITH_META_DESCR_BUILD_DIR, false);
+            //Generate regular/modular(depends on explicit/auto Service)
+            //jars for client
+            done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR, "-cp",
+                    S_JAR.toFile().getCanonicalPath());
+            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true);
+            generateJar(false, MODULE_TYPE.EXPLICIT,
+                    MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false);
+            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false);
+            System.out.format("%nArtifacts generated successfully? %s", done);
+            if (!done) {
+                throw new RuntimeException("Artifacts generation failed");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Generate modular/regular jar based on module type for this test.
+     */
+    private void generateJar(boolean isService, MODULE_TYPE moduleType,
+            Path jar, Path compilePath, boolean depends) throws IOException {
+
+        ModuleDescriptor mDescriptor = null;
+        if (isService) {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG,
+                    S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends);
+        } else {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG,
+                    C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends);
+        }
+        generateJar(mDescriptor, jar, compilePath);
+    }
+
+    /**
+     * Holds Logic for the test. This method will get called with each test
+     * parameter.
+     */
+    @Override
+    public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType,
+            Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath,
+            String... args) throws Exception {
+
+        OutputAnalyzer output = null;
+        try {
+
+            //For automated/explicit module type copy the corresponding
+            //jars to module base folder, which will be considered as
+            //module base path during execution.
+            if (!(cModuleType == MODULE_TYPE.UNNAMED
+                    && sModuletype == MODULE_TYPE.UNNAMED)) {
+                copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
+                copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH);
+            }
+
+            System.out.format("%nExecuting java client with required"
+                    + " custom security provider in class/module path.");
+            String mName = getModuleName(cModuleType, cJarPath, C_PKG);
+            Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED
+                    || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null;
+            String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
+                    sJarPath);
+
+            Map<String, String> VM_ARGS = getVMArgs(sModuletype, args);
+            output = ProcessTools.executeTestJava(
+                    getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS,
+                            args)).outputTo(System.out).errorTo(System.out);
+        } finally {
+            //clean module path so that the modulepath can hold only
+            //the required jars for next run.
+            cleanModuleBasePath(M_BASE_PATH);
+            System.out.println("--------------------------------------------");
+        }
+        return output;
+    }
+
+    /**
+     * Decide the pre-generated client/service jar path for each test case
+     * based on client/service module type.
+     */
+    @Override
+    public Path findJarPath(boolean isService, MODULE_TYPE moduleType,
+            boolean addMetaDesc, boolean dependsOnServiceModule) {
+        if (isService) {
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                if (addMetaDesc) {
+                    return MS_WITH_DESCR_JAR;
+                } else {
+                    return MS_JAR;
+                }
+            } else {
+                if (addMetaDesc) {
+                    return S_WITH_DESCRIPTOR_JAR;
+                } else {
+                    return S_JAR;
+                }
+            }
+        } else {
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                if (dependsOnServiceModule) {
+                    return MC_JAR;
+                } else {
+                    return MC_DEPENDS_ON_AUTO_SERVICE_JAR;
+                }
+            } else {
+                return C_JAR;
+            }
+        }
+    }
+
+    /**
+     * VM argument required for the test.
+     */
+    private Map<String, String> getVMArgs(MODULE_TYPE sModuletype,
+            String... args) throws IOException {
+        final Map<String, String> VM_ARGS = new LinkedHashMap<>();
+        VM_ARGS.put("-Duser.language=", "en");
+        VM_ARGS.put("-Duser.region=", "US");
+        //If mechanism selected to find the provider through
+        //Security.getProvider() then use providerName/ProviderClassName based
+        //on modular/regular provider jar in security configuration file.
+        if (args != null && args.length > 0 && SECURITY_PROP.equals(args[0])) {
+            if (sModuletype == MODULE_TYPE.UNNAMED) {
+                Files.write(SECURE_PROP_EXTN, ("security.provider.10=" + S_IMPL)
+                        .getBytes());
+            } else {
+                Files.write(SECURE_PROP_EXTN, "security.provider.10=TEST"
+                        .getBytes());
+            }
+            VM_ARGS.put("-Djava.security.properties=", SECURE_PROP_EXTN.toFile()
+                    .getCanonicalPath());
+        }
+        return VM_ARGS;
+    }
+
+}
diff --git a/jdk/test/java/security/Provider/TestSecurityProvider.java b/jdk/test/java/security/Provider/TestSecurityProvider.java
new file mode 100644
index 0000000..df6b82b
--- /dev/null
+++ b/jdk/test/java/security/Provider/TestSecurityProvider.java
@@ -0,0 +1,45 @@
+/*
+ * 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 provider;
+
+import java.security.Provider;
+
+/**
+ * Custom Security provider for modular test.
+ */
+public final class TestSecurityProvider extends Provider {
+
+    public TestSecurityProvider() {
+        super("TEST", 1.0d, "Test Security provider");
+        System.out.println(String.format("TEST Security provider loaded"
+                + " successfully : %s", this.toString()));
+    }
+
+    @Override
+    public String toString() {
+        return "TestSecurityProvider [getName()=" + getName()
+                + ", getVersion()=" + getVersion() + ", getInfo()="
+                + getInfo() + ", toString()=" + super.toString() + "]";
+    }
+
+}
diff --git a/jdk/test/java/security/Provider/TestSecurityProviderClient.java b/jdk/test/java/security/Provider/TestSecurityProviderClient.java
new file mode 100644
index 0000000..a4f7b41
--- /dev/null
+++ b/jdk/test/java/security/Provider/TestSecurityProviderClient.java
@@ -0,0 +1,80 @@
+/*
+ * 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 client;
+
+import java.security.Provider;
+import java.security.Security;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+/**
+ * Modular test for client using different mechanism to find the custom security
+ * provider. It uses ServiceLoader and ClassLoader to find the TEST provider
+ * available in classPath/modulePath. It also tries to find, if the provider is
+ * configured through "java.security" file.
+ */
+public class TestSecurityProviderClient {
+
+    private static final String CUSTOM_PROVIDER_NAME = "TEST";
+    private static final String EXCEPTION_MESSAGE
+            = "Unable to find Test Security Provider";
+    private static final String SERVICE_LOADER = "SERVICE_LOADER";
+    private static final String CLASS_LOADER = "CLASS_LOADER";
+
+    public static void main(String[] args) {
+        Provider provider = null;
+        //Try to find the TEST provider loaded by ServiceLoader.
+        if (args != null && args.length > 0
+                && SERVICE_LOADER.equals(args[0])) {
+            System.out.println(
+                    "Using service loader to find Security provider.");
+            ServiceLoader<Provider> services
+                    = ServiceLoader.load(java.security.Provider.class);
+            Iterator<Provider> iterator = services.iterator();
+            while (iterator.hasNext()) {
+                Provider p = iterator.next();
+                if (p.getName().equals(CUSTOM_PROVIDER_NAME)) {
+                    provider = p;
+                    break;
+                }
+            }
+        } else if (args != null && args.length > 0
+                && CLASS_LOADER.equals(args[0])) {
+            System.out.println("Using class loader to find Security provider.");
+            //Find the TEST provider loaded by ClassLoader.
+            provider = new provider.TestSecurityProvider();
+        } else {
+            //Find the TEST provider configured through Security.getProvider().
+            System.out.println("Finding Security provider through"
+                    + " Security.getProvider().");
+            provider = Security.getProvider(CUSTOM_PROVIDER_NAME);
+        }
+
+        if (provider != null) {
+            System.out.format("%nTest Security provider named '%s' loaded "
+                    + "successfully", CUSTOM_PROVIDER_NAME);
+        } else {
+            throw new RuntimeException(EXCEPTION_MESSAGE);
+        }
+    }
+}
diff --git a/jdk/test/java/security/cert/X509Certificate/EmptySubject.java b/jdk/test/java/security/cert/X509Certificate/EmptySubject.java
index 5a15110..6436405 100644
--- a/jdk/test/java/security/cert/X509Certificate/EmptySubject.java
+++ b/jdk/test/java/security/cert/X509Certificate/EmptySubject.java
@@ -33,8 +33,6 @@
 import java.security.cert.*;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.x509.*;
-
 public class EmptySubject {
 
     public static void main(String[] args) throws Exception {
diff --git a/jdk/test/java/security/modules/ModularTest.java b/jdk/test/java/security/modules/ModularTest.java
new file mode 100644
index 0000000..4a1ffbc
--- /dev/null
+++ b/jdk/test/java/security/modules/ModularTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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.io.IOException;
+import java.io.OutputStream;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import java.lang.module.ModuleDescriptor;
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import jdk.internal.module.ModuleInfoWriter;
+import static java.lang.module.ModuleDescriptor.Builder;
+
+/**
+ * Base class need to be extended by modular test for security.
+ */
+public abstract class ModularTest {
+
+    /**
+     * Enum represents all supported module types supported in JDK9. i.e.
+     * EXPLICIT - Modules have module descriptor(module-info.java)
+     * defining the module.
+     * AUTO - Are regular jar files but provided in MODULE_PATH instead
+     * of CLASS_PATH.
+     * UNNAMED - Are regular jar but provided through CLASS_PATH.
+     */
+    public enum MODULE_TYPE {
+
+        EXPLICIT, AUTO, UNNAMED;
+    }
+
+    public static final String SPACE = " ";
+    public static final Path SRC = Paths.get(System.getProperty("test.src"));
+    public static final String DESCRIPTOR = "MetaService";
+    public static final String MODULAR = "Modular";
+    public static final String AUTO = "AutoServiceType";
+    public static final String JAR_EXTN = ".jar";
+
+    /**
+     * Setup test data for the test.
+     */
+    @DataProvider(name = "TestParams")
+    public Object[][] setUpTestData() {
+        return getTestInput();
+    }
+
+    /**
+     * Test method for TestNG.
+     */
+    @Test(dataProvider = "TestParams")
+    public void runTest(MODULE_TYPE cModuleType, MODULE_TYPE sModuletype,
+            boolean addMetaDesc, String failureMsgExpected, String[] args)
+            throws Exception {
+
+        String testName = new StringJoiner("_").add(cModuleType.toString())
+                .add(sModuletype.toString()).add(
+                        (addMetaDesc) ? "DESCRIPTOR" : "NO_DESCRIPTOR")
+                .toString();
+
+        System.out.format("%nStarting Test case: '%s'", testName);
+        Path cJarPath = findJarPath(false, cModuleType, false,
+                (sModuletype == MODULE_TYPE.EXPLICIT));
+        Path sJarPath = findJarPath(true, sModuletype, addMetaDesc, false);
+        System.out.format("%nClient jar path : %s ", cJarPath);
+        System.out.format("%nService jar path : %s ", sJarPath);
+        OutputAnalyzer output = executeTestClient(cModuleType, cJarPath,
+                sModuletype, sJarPath, args);
+
+        if (output.getExitValue() != 0) {
+            if (failureMsgExpected != null
+                    && output.getOutput().contains(failureMsgExpected)) {
+                System.out.println("PASS: Test is expected to fail here.");
+            } else {
+                System.out.format("%nUnexpected failure occured with exit code"
+                        + " '%s'.", output.getExitValue());
+                throw new RuntimeException("Unexpected failure occured.");
+            }
+        }
+    }
+
+    /**
+     * Abstract method need to be implemented by each Test type to provide
+     * test parameters.
+     */
+    public abstract Object[][] getTestInput();
+
+    /**
+     * Execute the test client to access required service.
+     */
+    public abstract OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType,
+            Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath,
+            String... args) throws Exception;
+
+    /**
+     * Find the Jar for service/client based on module type and if service
+     * descriptor required.
+     */
+    public abstract Path findJarPath(boolean service, MODULE_TYPE moduleType,
+            boolean addMetaDesc, boolean dependsOnServiceModule);
+
+    /**
+     * Constructs a Java Command line string based on modular structure followed
+     * by modular client and service.
+     */
+    public String[] getJavaCommand(Path modulePath, String classPath,
+            String clientModuleName, String mainClass,
+            Map<String, String> vmArgs, String... options) throws IOException {
+
+        final StringJoiner command = new StringJoiner(SPACE, SPACE, SPACE);
+        vmArgs.forEach((key, value) -> command.add(key + value));
+        if (modulePath != null) {
+            command.add("-mp").add(modulePath.toFile().getCanonicalPath());
+        }
+        if (classPath != null && classPath.length() > 0) {
+            command.add("-cp").add(classPath);
+        }
+        if (clientModuleName != null && clientModuleName.length() > 0) {
+            command.add("-m").add(clientModuleName + "/" + mainClass);
+        } else {
+            command.add(mainClass);
+        }
+        command.add(Arrays.stream(options).collect(Collectors.joining(SPACE)));
+        return command.toString().trim().split("[\\s]+");
+    }
+
+    /**
+     * Generate ModuleDescriptor object for explicit/auto based client/Service
+     * modules type.
+     */
+    public ModuleDescriptor generateModuleDescriptor(boolean isService,
+            MODULE_TYPE moduleType, String moduleName, String pkg,
+            String serviceInterface, String serviceImpl,
+            String serviceModuleName, List<String> requiredModules,
+            boolean depends) {
+
+        final Builder builder;
+        if (moduleType == MODULE_TYPE.EXPLICIT) {
+            System.out.format(" %nGenerating ModuleDescriptor object");
+            builder = new Builder(moduleName).exports(pkg);
+            if (isService) {
+                builder.provides(serviceInterface, serviceImpl);
+            } else {
+                builder.uses(serviceInterface);
+                if (depends) {
+                    builder.requires(serviceModuleName);
+                }
+            }
+        } else {
+            System.out.format(" %nModuleDescriptor object not required.");
+            return null;
+        }
+        requiredModules.stream().forEach(reqMod -> builder.requires(reqMod));
+        return builder.build();
+    }
+
+    /**
+     * Generates service descriptor inside META-INF folder.
+     */
+    public boolean createMetaInfServiceDescriptor(
+            Path serviceDescriptorFile, String serviceImpl) {
+        boolean created = true;
+        System.out.format("%nCreating META-INF service descriptor for '%s' "
+                + "at path '%s'", serviceImpl, serviceDescriptorFile);
+        try {
+            Path parent = serviceDescriptorFile.getParent();
+            if (parent != null) {
+                Files.createDirectories(parent);
+            }
+            Files.write(serviceDescriptorFile, serviceImpl.getBytes("UTF-8"));
+            System.out.println(
+                    "META-INF service descriptor generated successfully");
+        } catch (IOException e) {
+            e.printStackTrace(System.out);
+            created = false;
+        }
+        return created;
+    }
+
+    /**
+     * Generate modular/regular jar file.
+     */
+    public void generateJar(ModuleDescriptor mDescriptor, Path jar,
+            Path compilePath) throws IOException {
+        System.out.format("%nCreating jar file '%s'", jar);
+        JarUtils.createJarFile(jar, compilePath);
+        if (mDescriptor != null) {
+            Path dir = Files.createTempDirectory("tmp");
+            Path mi = dir.resolve("module-info.class");
+            try (OutputStream out = Files.newOutputStream(mi)) {
+                ModuleInfoWriter.write(mDescriptor, out);
+            }
+            System.out.format("%nAdding 'module-info.class' to jar '%s'", jar);
+            JarUtils.updateJarFile(jar, dir);
+        }
+    }
+
+    /**
+     * Copy pre-generated jar files to the module base path.
+     */
+    public void copyJarsToModuleBase(MODULE_TYPE moduleType, Path jar,
+            Path mBasePath) throws IOException {
+        if (mBasePath != null) {
+            Files.createDirectories(mBasePath);
+        }
+        if (moduleType != MODULE_TYPE.UNNAMED) {
+            Path artifactName = mBasePath.resolve(jar.getFileName());
+            System.out.format("%nCopy jar path: '%s' to module base path: %s",
+                    jar, artifactName);
+            Files.copy(jar, artifactName);
+        }
+    }
+
+    /**
+     * Construct class path string.
+     */
+    public String buildClassPath(MODULE_TYPE cModuleType,
+            Path cJarPath, MODULE_TYPE sModuletype,
+            Path sJarPath) throws IOException {
+        StringJoiner classPath = new StringJoiner(File.pathSeparator);
+        classPath.add((cModuleType == MODULE_TYPE.UNNAMED)
+                ? cJarPath.toFile().getCanonicalPath() : "");
+        classPath.add((sModuletype == MODULE_TYPE.UNNAMED)
+                ? sJarPath.toFile().getCanonicalPath() : "");
+        return classPath.toString();
+    }
+
+    /**
+     * Construct executable module name for java. It is fixed for explicit
+     * module type while it is same as jar file name for automated module type.
+     */
+    public String getModuleName(MODULE_TYPE moduleType,
+            Path jarPath, String mName) {
+        String jarName = jarPath.toFile().getName();
+        return (moduleType == MODULE_TYPE.EXPLICIT) ? mName
+                : ((moduleType == MODULE_TYPE.AUTO) ? jarName.substring(0,
+                                jarName.indexOf(JAR_EXTN)) : "");
+    }
+
+    /**
+     * Delete all the files inside the base module path.
+     */
+    public void cleanModuleBasePath(Path mBasePath) {
+        Arrays.asList(mBasePath.toFile().listFiles()).forEach(f -> {
+            System.out.println("delete: " + f);
+            f.delete();
+        });
+    }
+
+}
diff --git a/jdk/test/java/security/testlibrary/Proc.java b/jdk/test/java/security/testlibrary/Proc.java
index 1ab58bf..6f9fa5d 100644
--- a/jdk/test/java/security/testlibrary/Proc.java
+++ b/jdk/test/java/security/testlibrary/Proc.java
@@ -33,6 +33,7 @@
 import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Base64;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -182,15 +183,21 @@
             cmd.add(new File(new File(System.getProperty("java.home"), "bin"),
                         "java").getPath());
         }
-        cmd.add("-cp");
-        StringBuilder cp = new StringBuilder();
-        for (URL url: ((URLClassLoader)Proc.class.getClassLoader()).getURLs()) {
-            if (cp.length() != 0) {
-                cp.append(File.pathSeparatorChar);
-            }
-            cp.append(url.getFile());
+
+        int n = 0;
+        String addexports;
+        while ((addexports = System.getProperty("jdk.launcher.addexports." + n)) != null) {
+            prop("jdk.launcher.addexports." + n, addexports);
+            n++;
         }
-        cmd.add(cp.toString());
+
+        Collections.addAll(cmd, splitProperty("test.vm.opts"));
+        Collections.addAll(cmd, splitProperty("test.java.opts"));
+
+        cmd.add("-cp");
+        cmd.add(System.getProperty("test.class.path") + File.pathSeparator +
+                System.getProperty("test.src.path"));
+
         for (Entry<String,String> e: prop.entrySet()) {
             cmd.add("-D" + e.getKey() + "=" + e.getValue());
         }
@@ -322,4 +329,12 @@
     public static void d(Throwable e) throws IOException {
         e.printStackTrace();
     }
+
+    private static String[] splitProperty(String prop) {
+        String s = System.getProperty(prop);
+        if (s == null || s.trim().isEmpty()) {
+            return new String[] {};
+        }
+        return s.trim().split("\\s+");
+    }
 }
diff --git a/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh
index bc80b3f..5d722c3 100644
--- a/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh
+++ b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh
@@ -24,20 +24,22 @@
 # @test
 # @bug 8003267
 # @summary Unit test for generic time zone names support
-# @compile -XDignore.symbol.file GenericTimeZoneNamesTest.java
+# @modules java.base/sun.util.locale.provider
+# @compile GenericTimeZoneNamesTest.java
 # @run shell GenericTimeZoneNamesTest.sh
 
 # This test is locale data-dependent and assumes that both JRE and CLDR
 # have the same geneic time zone names in English.
 
+EXTRAOPTS="-XaddExports:java.base/sun.util.locale.provider=ALL-UNNAMED"
 STATUS=0
 echo "Locale providers: default"
-if ! ${TESTJAVA}/bin/java -esa ${TESTVMOPTS} -cp "${TESTCLASSES}" GenericTimeZoneNamesTest en-US; then
+if ! ${TESTJAVA}/bin/java -esa ${TESTVMOPTS} ${EXTRAOPTS} -cp "${TESTCLASSES}" GenericTimeZoneNamesTest en-US; then
     STATUS=1
 fi
 
 echo "Locale providers: CLDR"
-if ! ${TESTJAVA}/bin/java -esa ${TESTVMOPTS} -cp "${TESTCLASSES}" -Djava.locale.providers=CLDR GenericTimeZoneNamesTest en-US; then
+if ! ${TESTJAVA}/bin/java -esa ${TESTVMOPTS} ${EXTRAOPTS} -cp "${TESTCLASSES}" -Djava.locale.providers=CLDR GenericTimeZoneNamesTest en-US; then
    STATUS=1
 fi
 exit ${STATUS}
diff --git a/jdk/test/java/util/Currency/CheckDataVersion.java b/jdk/test/java/util/Currency/CheckDataVersion.java
index 70320cb..204a80a 100644
--- a/jdk/test/java/util/Currency/CheckDataVersion.java
+++ b/jdk/test/java/util/Currency/CheckDataVersion.java
@@ -29,6 +29,7 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.security.*;
+import java.util.Currency;
 
 class CheckDataVersion {
     static final String datafile = "tablea1.txt";
@@ -63,9 +64,9 @@
             AccessController.doPrivileged(new PrivilegedAction<Object>() {
                 public Object run() {
                     try {
+                        InputStream in = Currency.class.getModule().getResourceAsStream("java/util/currency.data");
                         String sep = File.separator;
-                        DataInputStream dis = new DataInputStream(
-                             new BufferedInputStream(getClass().getResourceAsStream("/java/util/currency.data")));
+                        DataInputStream dis = new DataInputStream(in);
                         int magic = dis.readInt();
                         if (magic != 0x43757244) {
                             throw new RuntimeException("The magic number in the JRE's currency data is incorrect.  Expected: 0x43757244, Got: 0x"+magic);
diff --git a/jdk/test/java/util/Currency/CurrencyTest.java b/jdk/test/java/util/Currency/CurrencyTest.java
index fc16459..05d3cbf 100644
--- a/jdk/test/java/util/Currency/CurrencyTest.java
+++ b/jdk/test/java/util/Currency/CurrencyTest.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
@@ -25,6 +25,7 @@
  * @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531
  *    6488442 7036905 8008577 8039317 8074350 8074351
  * @summary Basic tests for Currency class.
+ * @modules jdk.localedata
  */
 
 import java.io.ByteArrayInputStream;
diff --git a/jdk/test/java/util/Formatter/Basic.sh b/jdk/test/java/util/Formatter/Basic.sh
index 25bd5ba..0bf4162 100644
--- a/jdk/test/java/util/Formatter/Basic.sh
+++ b/jdk/test/java/util/Formatter/Basic.sh
@@ -23,7 +23,8 @@
 
 #
 
-${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -cp ${TESTSRC} -d . \
+EXTRAOPTS="-XaddExports:java.base/jdk.internal.math=ALL-UNNAMED"
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -cp ${TESTSRC} -d . \
     ${TESTSRC}/Basic.java
 
 expectPass() {
@@ -39,7 +40,7 @@
   echo "Testing:" ${1}
   TZ="${1}"; export TZ
   echo "  " $TZ
-  ${TESTJAVA}/bin/java ${TESTVMOPTS} Basic
+  ${TESTJAVA}/bin/java ${TESTVMOPTS} ${EXTRAOPTS} Basic
   expectPass $?
 }
 
diff --git a/jdk/test/java/util/Locale/LocaleProviders.sh b/jdk/test/java/util/Locale/LocaleProviders.sh
index 798fce5..f90a66f 100644
--- a/jdk/test/java/util/Locale/LocaleProviders.sh
+++ b/jdk/test/java/util/Locale/LocaleProviders.sh
@@ -26,7 +26,9 @@
 # @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577
 #      8010666 8013086 8013233 8013903 8015960 8028771 8054482 8062006
 # @summary tests for "java.locale.providers" system property
-# @compile -XDignore.symbol.file LocaleProviders.java
+# @modules java.base/sun.util.locale
+#          java.base/sun.util.locale.provider
+# @compile LocaleProviders.java
 # @run shell/timeout=600 LocaleProviders.sh
 
 if [ "${TESTSRC}" = "" ]
@@ -118,18 +120,21 @@
 tznp
 tznp8013086
 EOF
+
+EXTRAOPTS="-XaddExports:java.base/sun.util.locale=ALL-UNNAMED,java.base/sun.util.locale.provider=ALL-UNNAMED"
+
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d ${SPIDIR}${FS}dest \
     ${SPIDIR}${FS}src${FS}tznp.java \
     ${SPIDIR}${FS}src${FS}tznp8013086.java
 ${COMPILEJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS} cvf ${SPIDIR}${FS}tznp.jar -C ${SPIDIR}${FS}dest .
 
 # get the platform default locales
-PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale display`
+PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale display`
 DEFLANG=`echo ${PLATDEF} | sed -e "s/,.*//"`
 DEFCTRY=`echo ${PLATDEF} | sed -e "s/.*,//"`
 echo "DEFLANG=${DEFLANG}"
 echo "DEFCTRY=${DEFCTRY}"
-PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale format`
+PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale format`
 DEFFMTLANG=`echo ${PLATDEF} | sed -e "s/,.*//"`
 DEFFMTCTRY=`echo ${PLATDEF} | sed -e "s/.*,//"`
 echo "DEFFMTLANG=${DEFFMTLANG}"
@@ -137,7 +142,7 @@
 
 runTest()
 {
-    RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES}${PS}${SPICLASSES} -Djava.locale.providers=$PREFLIST LocaleProviders $METHODNAME $PARAM1 $PARAM2 $PARAM3"
+    RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath ${TESTCLASSES}${PS}${SPICLASSES} -Djava.locale.providers=$PREFLIST LocaleProviders $METHODNAME $PARAM1 $PARAM2 $PARAM3"
     echo ${RUNCMD}
     ${RUNCMD}
     result=$?
diff --git a/jdk/test/java/util/PluggableLocale/ExecTest.sh b/jdk/test/java/util/PluggableLocale/ExecTest.sh
index bb89773..190d5ab 100644
--- a/jdk/test/java/util/PluggableLocale/ExecTest.sh
+++ b/jdk/test/java/util/PluggableLocale/ExecTest.sh
@@ -92,10 +92,13 @@
     ;;
 esac
 
+
+EXTRA_OPTS="-XaddExports:java.base/sun.util.locale.provider=ALL-UNNAMED,java.base/sun.util.resources=ALL-UNNAMED"
+
 # compile
 cp ${TESTSRC}${FS}ProviderTest.java .
 cp ${TESTSRC}${FS}$2.java .
-COMPILE="${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+COMPILE="${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRA_OPTS} \
     -XDignore.symbol.file -d . -classpath ${CLASSPATHARG} $2.java"
 echo ${COMPILE}
 ${COMPILE}
@@ -120,7 +123,7 @@
 fi
 
 # run
-RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${SECURITYOPTS} -classpath ${CLASSPATHARG} -Djava.locale.providers=JRE,SPI $2 "
+RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRA_OPTS} ${SECURITYOPTS} -classpath ${CLASSPATHARG} -Djava.locale.providers=JRE,SPI $2 "
 
 echo ${RUNCMD}
 ${RUNCMD}
diff --git a/jdk/test/java/util/PluggableLocale/ProviderTest.java b/jdk/test/java/util/PluggableLocale/ProviderTest.java
index 32b5b63..30cc49f 100644
--- a/jdk/test/java/util/PluggableLocale/ProviderTest.java
+++ b/jdk/test/java/util/PluggableLocale/ProviderTest.java
@@ -26,7 +26,6 @@
 
 import java.text.*;
 import java.util.*;
-import sun.text.resources.*;
 import sun.util.locale.provider.*;
 
 public class ProviderTest {
diff --git a/jdk/test/java/util/ResourceBundle/Bug4168625Test.java b/jdk/test/java/util/ResourceBundle/Bug4168625Test.java
index 09568a2..e6dca78 100644
--- a/jdk/test/java/util/ResourceBundle/Bug4168625Test.java
+++ b/jdk/test/java/util/ResourceBundle/Bug4168625Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -425,26 +425,36 @@
                 throws ClassNotFoundException {
             Class result;
             synchronized (this) {
-                logln(">>"+threadName()+">load "+className);
-                loadedClasses.addElement(className);
+                try {
+                    logln(">>"+threadName()+">load "+className);
+                    loadedClasses.addElement(className);
 
-                result = findLoadedClass(className);
-                if (result == null) {
-                    final byte[] classData = getClassData(className);
-                    if (classData == null) {
-                        //we don't have a local copy of this one
-                        logln("Loading system class: "+className);
-                        result = loadFromSystem(className);
-                    } else {
-                        result = defineClass(classData, 0, classData.length);
-                        if (result == null) {
-                            //there was an error defining the class
+                    result = findLoadedClass(className);
+                    if (result == null) {
+                        final byte[] classData = getClassData(className);
+                        if (classData == null) {
+                            //we don't have a local copy of this one
+                            logln("Loading system class: "+className);
                             result = loadFromSystem(className);
+                        } else {
+                            result = defineClass(classData, 0, classData.length);
+                            if (result == null) {
+                                //there was an error defining the class
+                                result = loadFromSystem(className);
+                            }
+                        }
+                        if ((result != null) && resolveIt) {
+                            resolveClass(result);
                         }
                     }
-                    if ((result != null) && resolveIt) {
-                        resolveClass(result);
+                } catch (ClassNotFoundException e) {
+                    // Ignore loading of Bug4168625ResourceProvider
+                    if (className.equals("Bug4168625ResourceProvider")) {
+                        logln("Ignoring " + className);
+                        loadedClasses.remove(className);
+                        return null;
                     }
+                    throw e;
                 }
             }
             for (int i = classesToWaitFor.length-1; i >= 0; --i) {
diff --git a/jdk/test/java/util/ResourceBundle/Bug6299235Test.java b/jdk/test/java/util/ResourceBundle/Bug6299235Test.java
index 9d44671..ed42ee3 100644
--- a/jdk/test/java/util/ResourceBundle/Bug6299235Test.java
+++ b/jdk/test/java/util/ResourceBundle/Bug6299235Test.java
@@ -20,13 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-/*
- *
- */
-import java.io.File;
+
+import java.awt.Toolkit;
 import java.util.Locale;
-import java.util.ResourceBundle;
-import sun.util.CoreResourceBundleControl;
 
 /*
  * After introducing CoreResourceBundleControl for Awt/Swing resources
@@ -39,24 +35,26 @@
  */
 
 public class Bug6299235Test {
+    static final Locale ru_RU = new Locale("ru", "RU");
 
-    public static void main(String args[]) throws Exception {
-        /* Try to load "sun.awt.resources.awt_ru_RU.properties which
-         * is in awtres.jar.
-         */
-        ResourceBundle russionAwtRes = ResourceBundle.getBundle("sun.awt.resources.awt",
-                                                                new Locale("ru", "RU"),
-                                                                CoreResourceBundleControl.getRBControlInstance());
-
-        /* If this call throws MissingResourceException, the test fails. */
-        if (russionAwtRes != null) {
-            String result = russionAwtRes.getString("foo");
-            if (result.equals("bar")) {
-                System.out.println("Bug6299235Test passed");
-            } else {
-                System.err.println("Bug6299235Test failed");
-                throw new Exception("Resource found, but value of key foo is not correct\n");
+    public static void main(String args[]) {
+        Locale locale = Locale.getDefault();
+        try {
+            Locale.setDefault(ru_RU);
+            // Get the value for the test key "foo"
+            String value = Toolkit.getProperty("foo", "undefined");
+            if (!value.equals("bar")) {
+                throw new RuntimeException("key = foo, value = " + value);
             }
+            // Get the value for a valid key "AWT.enter"
+            value = Toolkit.getProperty("AWT.enter", "DO NOT ENTER");
+            if (value.equals("DO NOT ENTER")) {
+                throw new RuntimeException("AWT.enter undefined.");
+            }
+        } finally {
+            // Restore the default Locale
+            Locale.setDefault(locale);
         }
+        System.out.println("Bug6299235Test passed");
     }
 }
diff --git a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh
index a29c744..35725bc 100644
--- a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh
+++ b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh
@@ -58,11 +58,17 @@
 echo "TESTJAVA=${TESTJAVA}"
 echo "TESTSRC=${TESTSRC}"
 echo "TESTCLASSES=${TESTCLASSES}"
-echo "NEW_EXT_DIR=${NEW_EXT_DIR}"
 
-cd ${TESTSRC}
+PATCHDIR=${TESTCLASSES}/patches
+rm -rf $PATCHDIR
+mkdir -p $PATCHDIR/java.desktop
+
+cd ${PATCHDIR}/java.desktop
+${TESTJAVA}/bin/jar xf ${TESTSRC}/awtres.jar
+
 echo 
-${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}awtres.jar Bug6299235Test
+${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:${PATCHDIR} \
+     -cp ${TESTCLASSES} Bug6299235Test
 
 if [ $? -ne 0 ]
     then
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
new file mode 100644
index 0000000..059e109
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
@@ -0,0 +1,46 @@
+/*
+ * 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 jdk.test.resources.asia;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import jdk.test.resources.MyControl;
+import jdk.test.resources.MyResourcesProvider;
+
+public class MyResourcesAsia extends MyControl implements MyResourcesProvider {
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (isAsiaLocale(locale)) {
+            try {
+                ClassLoader loader = MyResourcesAsia.class.getClassLoader();
+                return newBundle(baseName, locale, "java.properties", loader, false);
+            } catch (IllegalAccessException | InstantiationException | IOException e) {
+                System.out.println(e);
+            }
+        }
+        return null;
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
new file mode 100644
index 0000000..e64ab3d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
new file mode 100644
index 0000000..515e71c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
new file mode 100644
index 0000000..699d706
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/module-info.java
new file mode 100644
index 0000000..0b821d5
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/asiabundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 asiabundles {
+    requires test;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.asia.MyResourcesAsia;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
new file mode 100644
index 0000000..29d3641
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
@@ -0,0 +1,46 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import jdk.test.resources.MyControl;
+import jdk.test.resources.MyResourcesProvider;
+
+public class MyResourcesEU extends MyControl implements MyResourcesProvider {
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (isEULocale(locale)) {
+            try {
+                ClassLoader loader = MyResourcesEU.class.getClassLoader();
+                return newBundle(baseName, locale, "java.class", loader, false);
+            } catch (IllegalAccessException | InstantiationException | IOException e) {
+                System.out.println(e);
+            }
+        }
+        return null;
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_de.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_de.java
new file mode 100644
index 0000000..e57e387
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_de.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
new file mode 100644
index 0000000..4420853
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+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/appbasic/src/eubundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/module-info.java
new file mode 100644
index 0000000..67a55c8
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/eubundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 eubundles {
+    requires test;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.eu.MyResourcesEU;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..6866cf1
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/Main.java
@@ -0,0 +1,53 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                errors++;
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyControl.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyControl.java
new file mode 100644
index 0000000..0cf7f9b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyControl.java
@@ -0,0 +1,59 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.*;
+
+public class MyControl extends ResourceBundle.Control {
+    private static final Set<Locale> euLocales, asiaLocales;
+
+    static {
+        euLocales = new HashSet<>(Arrays.asList(Locale.GERMAN, Locale.FRENCH));
+        asiaLocales = new HashSet<>(Arrays.asList(Locale.JAPANESE, Locale.CHINESE, Locale.TAIWAN));
+    }
+
+    @Override
+    public String toBundleName(String baseName, Locale locale) {
+        String bundleName = baseName;
+        if (euLocales.contains(locale)) {
+            bundleName = addRegion(baseName, "eu");
+        } else if (asiaLocales.contains(locale)) {
+            bundleName = addRegion(baseName, "asia");
+        }
+        return super.toBundleName(bundleName, locale);
+    }
+
+    private String addRegion(String baseName, String region) {
+        int index = baseName.lastIndexOf('.');
+        return baseName.substring(0, index + 1) + region + baseName.substring(index);
+    }
+
+    protected static boolean isEULocale(Locale locale) {
+        return euLocales.contains(locale);
+    }
+
+    protected static boolean isAsiaLocale(Locale locale) {
+        return asiaLocales.contains(locale);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources.java
new file mode 100644
index 0000000..235e80d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProvider.java
new file mode 100644
index 0000000..eacdd25
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.spi.ResourceBundleProvider;
+
+public interface MyResourcesProvider extends ResourceBundleProvider {
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProviderImpl.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProviderImpl.java
new file mode 100644
index 0000000..91dec1f
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResourcesProviderImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class MyResourcesProviderImpl extends MyControl implements MyResourcesProvider {
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (locale.equals(Locale.ENGLISH) || locale.equals(Locale.ROOT)) {
+            try {
+                ClassLoader loader = MyResourcesProviderImpl.class.getClassLoader();
+                return newBundle(baseName, locale, "java.class", loader, false);
+            } catch (IllegalAccessException | InstantiationException | IOException e) {
+            }
+        }
+        return null;
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources_en.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources_en.java
new file mode 100644
index 0000000..65f2a64
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/jdk/test/resources/MyResources_en.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/module-info.java
new file mode 100644
index 0000000..3ca685b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic/src/test/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test {
+    exports jdk.test.resources to eubundles, asiabundles;
+    uses jdk.test.resources.MyResourcesProvider;
+    provides jdk.test.resources.MyResourcesProvider with jdk.test.resources.MyResourcesProviderImpl;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/appbasic2.sh b/jdk/test/java/util/ResourceBundle/modules/appbasic2/appbasic2.sh
new file mode 100644
index 0000000..51c0f4a
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/appbasic2.sh
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8044767
+# @summary Basic test for ResourceBundle with modules; named module "test"
+#          contains resource bundles for root and en, and separate named modules
+#          "eubundles" and "asiabundles" contain other resource bundles.
+
+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"
+
+
+for I in eu asia
+do
+  B=${I}bundles
+  mkdir -p mods/$B
+  CLASSES="`find $TESTSRC/src/$B -name '*.java'`"
+  if [ "x$CLASSES" != x ]; then
+    $JAVAC -g -d mods -modulesourcepath $TESTSRC/src -cp mods/test $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
+done
+
+mkdir -p mods/test
+$JAVAC -g -d mods -modulesourcepath $TESTSRC/src `find $TESTSRC/src/test -name "*.java"`
+
+$JAVA -mp mods -m test/jdk.test.Main de fr ja zh-tw en de
+
+exit $?
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
new file mode 100644
index 0000000..72d1010
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
@@ -0,0 +1,59 @@
+/*
+ * 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 jdk.test.resources.asia;
+
+import java.util.Locale;
+import jdk.test.resources.MyResourcesProvider;
+
+public class MyResourcesAsia extends MyResourcesProvider {
+    public MyResourcesAsia() {
+        super("java.properties");
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        // Convert baseName to its properties resource name for the given locale
+        // e.g., jdk.test.resources.MyResources -> jdk/test/resources/asia/MyResources_zh_TW
+        StringBuilder sb = new StringBuilder();
+        int index = baseName.lastIndexOf('.');
+        sb.append(baseName.substring(0, index))
+            .append(".asia")
+            .append(baseName.substring(index));
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    protected boolean isSupportedInModule(Locale locale) {
+        return locale.equals(Locale.JAPANESE)
+            || locale.equals(Locale.CHINESE) || locale.equals(Locale.TAIWAN);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
new file mode 100644
index 0000000..e64ab3d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
new file mode 100644
index 0000000..515e71c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
new file mode 100644
index 0000000..699d706
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/module-info.java
new file mode 100644
index 0000000..0b821d5
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/asiabundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 asiabundles {
+    requires test;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.asia.MyResourcesAsia;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
new file mode 100644
index 0000000..f95a44f
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
@@ -0,0 +1,46 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.Locale;
+import jdk.test.resources.MyResourcesProvider;
+
+public class MyResourcesEU extends MyResourcesProvider {
+    public MyResourcesEU() {
+        super("java.class");
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        int index = baseName.lastIndexOf('.');
+        String bundleName = baseName.substring(0, index) + ".eu" + baseName.substring(index)
+                                + '_' + locale.getLanguage();
+        return bundleName;
+    }
+
+    @Override
+    protected boolean isSupportedInModule(Locale locale) {
+        return locale.equals(Locale.GERMAN) || locale.equals(Locale.FRENCH);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_de.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_de.java
new file mode 100644
index 0000000..e57e387
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_de.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_fr.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
new file mode 100644
index 0000000..4420853
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+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/appbasic2/src/eubundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/module-info.java
new file mode 100644
index 0000000..67a55c8
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/eubundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 eubundles {
+    requires test;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.eu.MyResourcesEU;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..6866cf1
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/Main.java
@@ -0,0 +1,53 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                errors++;
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources.java
new file mode 100644
index 0000000..235e80d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProvider.java
new file mode 100644
index 0000000..2ff0ceb
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProvider.java
@@ -0,0 +1,45 @@
+/*
+ * 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 jdk.test.resources;
+
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.spi.AbstractResourceBundleProvider;
+
+public abstract class MyResourcesProvider extends AbstractResourceBundleProvider {
+    protected MyResourcesProvider(String... formats) {
+        super(formats);
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (isSupportedInModule(locale)) {
+            return super.getBundle(baseName, locale);
+        }
+        return null;
+    }
+
+    protected abstract boolean isSupportedInModule(Locale locale);
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProviderImpl.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProviderImpl.java
new file mode 100644
index 0000000..ef9c683
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResourcesProviderImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.Locale;
+
+public class MyResourcesProviderImpl extends MyResourcesProvider {
+    public MyResourcesProviderImpl() {
+        super("java.class");
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        return locale.equals(Locale.ROOT) ? baseName : baseName + '_' + locale.getLanguage();
+    }
+
+    @Override
+    protected boolean isSupportedInModule(Locale locale) {
+        return locale.equals(Locale.ENGLISH) || locale.equals(Locale.ROOT);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources_en.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources_en.java
new file mode 100644
index 0000000..65f2a64
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/jdk/test/resources/MyResources_en.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/module-info.java
new file mode 100644
index 0000000..3ca685b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/appbasic2/src/test/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test {
+    exports jdk.test.resources to eubundles, asiabundles;
+    uses jdk.test.resources.MyResourcesProvider;
+    provides jdk.test.resources.MyResourcesProvider with jdk.test.resources.MyResourcesProviderImpl;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/basic.sh b/jdk/test/java/util/ResourceBundle/modules/basic/basic.sh
new file mode 100644
index 0000000..86fd0fd
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/basic.sh
@@ -0,0 +1,89 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8044767 8139067
+# @summary Basic test case for ResourceBundle with modules;
+#          ResourceBundle.getBundle caller is in module named "test",
+#          resource bundles are grouped in main (module "mainbundles"),
+#          EU (module "eubundles"), and Asia (module "asiabundles").
+#          Also adds a jar file containing resource bundles to the class path.
+
+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"
+JAR="$COMPILEJAVA/bin/jar"
+JAVA="$TESTJAVA/bin/java"
+
+rm -rf mods
+
+CP=
+for I in main eu asia
+do
+  B=${I}bundles
+  mkdir -p mods/$B
+  CLASSES="`find $TESTSRC/src/$B -name '*.java'`"
+  if [ "x$CLASSES" != x ]; then
+    $JAVAC -g -d mods -modulesourcepath $TESTSRC/src $CP $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
+  CP="-cp mods/mainbundles"
+done
+
+mkdir -p mods/test
+$JAVAC -g -cp mods/mainbundles -d mods -modulesourcepath $TESTSRC/src \
+    `find $TESTSRC/src/test -name "*.java"`
+
+# Create a jar to be added to the class path. Expected only properties files are
+# picked up from the class path.
+rm -f extra.jar
+mkdir -p classes
+$JAVAC -d classes $TESTSRC/src/extra/jdk/test/resources/eu/*.java
+$JAR -cf extra.jar -C classes jdk/test/resources/eu \
+                   -C $TESTSRC/src/extra jdk/test/resources/asia
+
+STATUS=0
+
+echo "jdk.test.Main should load bundles using ResourceBundleProviders."
+$JAVA -mp mods -m test/jdk.test.Main de fr ja ja-jp zh-tw en de ja-jp || STATUS=1
+
+echo "jdk.test.Main should NOT load bundles from the jar file specified by the class-path."
+$JAVA -cp extra.jar -mp mods -m test/jdk.test.Main es vi && STATUS=1
+
+exit $STATUS
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/MyResources_ja_JP.properties b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/MyResources_ja_JP.properties
new file mode 100644
index 0000000..c4b198e
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/MyResources_ja_JP.properties
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+# This resource bundle is located at jdk/test/resources to demonstrate
+# the unique package requirement is not applicable to .properties bundles.
+
+key=ja-JP: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
new file mode 100644
index 0000000..a62c8be
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResourcesAsia.java
@@ -0,0 +1,38 @@
+/*
+ * 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 jdk.test.resources.asia;
+
+import java.util.Locale;
+import jdk.test.resources.MyResourcesProvider;
+
+/**
+ *
+ */
+public class MyResourcesAsia extends MyResourcesProvider {
+    public MyResourcesAsia() {
+        super("java.properties", "asia",
+              Locale.JAPANESE, Locale.JAPAN, Locale.CHINESE, Locale.TAIWAN,
+              new Locale("vi"));
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
new file mode 100644
index 0000000..e64ab3d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
new file mode 100644
index 0000000..515e71c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
new file mode 100644
index 0000000..699d706
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/module-info.java
new file mode 100644
index 0000000..9c51bcc
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 asiabundles {
+    requires mainbundles;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.asia.MyResourcesAsia;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
new file mode 100644
index 0000000..6895120
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResourcesEU.java
@@ -0,0 +1,37 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.Locale;
+import jdk.test.resources.MyResourcesProvider;
+
+/**
+ *
+ */
+public class MyResourcesEU extends MyResourcesProvider {
+    public MyResourcesEU() {
+        super("java.class", "eu",
+              Locale.GERMAN, Locale.FRENCH, new Locale("es"));
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_de.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_de.java
new file mode 100644
index 0000000..e57e387
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_de.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
new file mode 100644
index 0000000..4420853
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/jdk/test/resources/eu/MyResources_fr.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+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/basic/src/eubundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/module-info.java
new file mode 100644
index 0000000..4a003a5
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/eubundles/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 eubundles {
+    requires mainbundles;
+
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.eu.MyResourcesEU;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/asia/MyResources_vi.properties b/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/asia/MyResources_vi.properties
new file mode 100644
index 0000000..4662419
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/asia/MyResources_vi.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=vi: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/eu/MyResources_es.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/eu/MyResources_es.java
new file mode 100644
index 0000000..764bc49
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/extra/jdk/test/resources/eu/MyResources_es.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.eu;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_es extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "es: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources.java
new file mode 100644
index 0000000..235e80d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesMain.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesMain.java
new file mode 100644
index 0000000..ccb353c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesMain.java
@@ -0,0 +1,32 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.Locale;
+
+public class MyResourcesMain extends MyResourcesProvider {
+    public MyResourcesMain() {
+        super("java.class", "", Locale.ROOT, Locale.ENGLISH);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesProvider.java
new file mode 100644
index 0000000..c9ebc4b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesProvider.java
@@ -0,0 +1,82 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import java.util.Set;
+import java.util.spi.AbstractResourceBundleProvider;
+
+
+public class MyResourcesProvider extends AbstractResourceBundleProvider {
+    private final String region;
+    private final Set<Locale> supportedLocales;
+    private final List<String> formats;
+
+    protected MyResourcesProvider() {
+        region = "";
+        supportedLocales = null;
+        formats = Collections.emptyList();
+    }
+
+    protected MyResourcesProvider(String format, String region, Locale... locales) {
+        super(format);
+        this.region = region;
+        this.supportedLocales = new HashSet<>(Arrays.asList(locales));
+        this.formats = Collections.singletonList(format);
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        if (isSupportedInModule(locale)) {
+           return super.getBundle(baseName, locale);
+        }
+        return null;
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        // The resource bundle for Locale.JAPAN is loccated at jdk.test.resources
+        // in module "asiabundles".
+        String name = locale.equals(Locale.JAPAN) ? baseName : addRegion(baseName);
+        return Control.getControl(Control.FORMAT_DEFAULT).toBundleName(name, locale);
+    }
+
+    private String addRegion(String baseName) {
+        if (region.isEmpty()) {
+            return baseName;
+        }
+        int index = baseName.lastIndexOf('.');
+        return baseName.substring(0, index + 1) + region + baseName.substring(index);
+    }
+
+    protected boolean isSupportedInModule(Locale locale) {
+        return supportedLocales.contains(locale);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources_en.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources_en.java
new file mode 100644
index 0000000..65f2a64
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResources_en.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/module-info.java
new file mode 100644
index 0000000..64769af
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 mainbundles {
+    exports jdk.test.resources to test, eubundles, asiabundles;
+    provides jdk.test.resources.MyResourcesProvider
+        with jdk.test.resources.MyResourcesMain;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..65388e7
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/test/jdk/test/Main.java
@@ -0,0 +1,51 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Locale;
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                errors++;
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/basic/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/basic/src/test/module-info.java
new file mode 100644
index 0000000..2d9e6e2
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/test/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 test {
+    requires mainbundles;
+    uses jdk.test.resources.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh b/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh
new file mode 100644
index 0000000..e87e05c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8044767 8139067
+# @summary Test case for having resource bundles in a local named module
+#          with no ResourceBundleProviders.
+
+
+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"
+JAR="$COMPILEJAVA/bin/jar"
+JAVA="$TESTJAVA/bin/java"
+
+rm -rf mods
+mkdir -p mods/test
+
+#
+# Copy .properties files
+#
+PROPS="`(cd $TESTSRC/src; find . -name '*.properties')`"
+if [ "x$PROPS" != x ]; then
+    for P in $PROPS
+    do
+      D=`dirname $P`
+      mkdir -p mods/$D
+      cp $TESTSRC/src/$P mods/$D/
+    done
+fi
+
+$JAVAC -g -d mods -modulesourcepath $TESTSRC/src \
+       -cp mods/bundles `find $TESTSRC/src/test -name "*.java"`
+
+# Create a jar to be added to the class path. Expected properties files are
+# picked up from the class path.
+rm -f extra.jar
+mkdir -p classes
+$JAR -cf extra.jar -C $TESTSRC/src/extra jdk/test/resources
+
+STATUS=0
+
+echo 'jdk.test.Main should load bundles local to named module "test".'
+$JAVA -mp 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 -mp mods -m test/jdk.test.Main vi && STATUS=1
+
+exit $STATUS
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/extra/jdk/test/resources/MyResources_vi.properties b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/extra/jdk/test/resources/MyResources_vi.properties
new file mode 100644
index 0000000..4662419
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/extra/jdk/test/resources/MyResources_vi.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=vi: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..65a70cb
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/Main.java
@@ -0,0 +1,67 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import java.util.MissingResourceException;
+
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                System.out.println("ERROR: " + value + " expected: " + tag);
+                errors++;
+            }
+        }
+
+        // Make sure ResourceBundle.getBundle throws an UnsupportedOperationException with
+        // a ResourceBundle.Control.
+        try {
+            ResourceBundle rb;
+            rb = ResourceBundle.getBundle("jdk.test.resources.MyResources",
+                                          Locale.ENGLISH,
+                                          Control.getControl(Control.FORMAT_DEFAULT));
+            System.out.println("ERROR: no UnsupportedOperationException thrown with a ResourceBundle.Control");
+            errors++;
+        } catch (UnsupportedOperationException e) {
+            // OK
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources.java
new file mode 100644
index 0000000..235e80d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_de.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_de.java
new file mode 100644
index 0000000..93bd11e
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_de.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_en.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_en.java
new file mode 100644
index 0000000..65f2a64
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_en.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_fr.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_fr.java
new file mode 100644
index 0000000..5d85154
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_fr.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+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/modlocal/src/test/jdk/test/resources/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_ja.properties
new file mode 100644
index 0000000..e64ab3d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh.properties
new file mode 100644
index 0000000..515e71c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh_TW.properties
new file mode 100644
index 0000000..699d706
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/jdk/test/resources/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/module-info.java
new file mode 100644
index 0000000..6d6b0a1
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/src/test/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 test {
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java b/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java
new file mode 100644
index 0000000..68eb09e
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/TestPermission.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+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 jdk.compiler
+ * @build TestPermission CompilerUtils jdk.testlibrary.*
+ * @run testng TestPermission
+ * @summary Driver for testing ResourceBundle::getBundle(String, Module)
+ */
+
+public class TestPermission {
+
+    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");
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("test", "m1");
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+    }
+
+    /**
+     * Run the modular test
+     */
+    @Test
+    public void runTest() throws Exception {
+        int exitValue = executeTestJava("-mp", MODS_DIR.toString(),
+                                        "-m", "test/jdk.test.Main")
+                            .outputTo(System.out)
+                            .errorTo(System.out)
+                            .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/m1/module-info.java b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/module-info.java
new file mode 100644
index 0000000..44b2d01
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    exports p1;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/Bundle.java b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/Bundle.java
new file mode 100644
index 0000000..ea71d8c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/Bundle.java
@@ -0,0 +1,32 @@
+/*
+ * 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 p1;
+
+import java.util.ResourceBundle;
+
+public class Bundle {
+    public static ResourceBundle getBundle(String basename) {
+        return ResourceBundle.getBundle(basename);
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/resources/MyResources.java
new file mode 100644
index 0000000..6766c77
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/m1/p1/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 p1.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "msg", "m1" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..512ee4a
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/Main.java
@@ -0,0 +1,63 @@
+/*
+ * 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 jdk.test;
+
+import p1.Bundle;
+import java.lang.reflect.Module;
+import java.util.ResourceBundle;
+
+public class Main {
+    private static final String TEST_RESOURCE_BUNDLE_NAME
+            = "jdk.test.resources.TestResources";
+    private static final String M1_RESOURCE_BUNDLE_NAME
+            = "p1.resources.MyResources";
+
+    public static void main(String[] args) {
+        // local resource
+        ResourceBundle.getBundle(TEST_RESOURCE_BUNDLE_NAME, Main.class.getModule());
+
+        // resource in another module
+        Module m1 = p1.Bundle.class.getModule();
+        ResourceBundle rb1 = Bundle.getBundle(M1_RESOURCE_BUNDLE_NAME);
+        ResourceBundle rb2 = ResourceBundle.getBundle(M1_RESOURCE_BUNDLE_NAME, m1);
+        if (rb1 != rb2) {
+            throw new RuntimeException("unexpected resource bundle");
+        }
+
+        System.setSecurityManager(new SecurityManager());
+
+        // no permission needed for local resource
+        ResourceBundle.getBundle(TEST_RESOURCE_BUNDLE_NAME, Main.class.getModule());
+
+        // resource bundle through m1's exported API
+        Bundle.getBundle(M1_RESOURCE_BUNDLE_NAME);
+
+        try {
+            // fail to get resource bundle in another module
+            ResourceBundle.getBundle(M1_RESOURCE_BUNDLE_NAME, m1);
+            throw new RuntimeException("should deny access");
+        } catch (SecurityException e) {}
+    }
+
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/resources/TestResources.java b/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/resources/TestResources.java
new file mode 100644
index 0000000..a32e349
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/test/jdk/test/resources/TestResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class TestResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "msg", "test" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/security/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/security/src/test/module-info.java
new file mode 100644
index 0000000..fec5381
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/security/src/test/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module test {
+    requires m1;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/simple.sh b/jdk/test/java/util/ResourceBundle/modules/simple/simple.sh
new file mode 100644
index 0000000..9975d1c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/simple.sh
@@ -0,0 +1,70 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8044767
+# @summary Simple test case for ResourceBundle with named modules;
+#          ResourceBundle.getBundle caller is in named module "test" and
+#          all resource bundles are in single named module "bundles" with
+#          service providers.
+
+
+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 -modulesourcepath $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
+
+$JAVAC -g -d mods -modulesourcepath $TESTSRC/src \
+       -cp mods/bundles `find $TESTSRC/src/test -name "*.java"`
+
+$JAVA -mp mods -m test/jdk.test.Main de fr ja zh-tw en de
+
+exit $?
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources.java
new file mode 100644
index 0000000..235e80d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResourcesProvider.java
new file mode 100644
index 0000000..29fc236
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResourcesProvider.java
@@ -0,0 +1,48 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.Locale;
+import java.util.spi.AbstractResourceBundleProvider;
+
+public class MyResourcesProvider extends AbstractResourceBundleProvider {
+    public MyResourcesProvider() {
+        super("java.class", "java.properties");
+        System.err.println("MyResourcesProvider called " + this);
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        StringBuilder sb = new StringBuilder(baseName);
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_de.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_de.java
new file mode 100644
index 0000000..93bd11e
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_de.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_en.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_en.java
new file mode 100644
index 0000000..65f2a64
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_en.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_fr.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_fr.java
new file mode 100644
index 0000000..5d85154
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_fr.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources;
+
+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/simple/src/bundles/jdk/test/resources/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_ja.properties
new file mode 100644
index 0000000..e64ab3d
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh.properties
new file mode 100644
index 0000000..515e71c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh_TW.properties
new file mode 100644
index 0000000..699d706
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/jdk/test/resources/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/module-info.java
new file mode 100644
index 0000000..7725c44
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/bundles/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 bundles {
+    exports jdk.test.resources to test;
+    provides jdk.test.resources.MyResourcesProvider with jdk.test.resources.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..d93cb62
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/test/jdk/test/Main.java
@@ -0,0 +1,51 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Locale;
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                System.out.println("ERROR: " + value + " expected: " + tag);
+                errors++;
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/simple/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/simple/src/test/module-info.java
new file mode 100644
index 0000000..c5ac262
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/simple/src/test/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test {
+    requires bundles;
+
+    uses jdk.test.resources.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithNoModuleArg.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithNoModuleArg.java
new file mode 100644
index 0000000..5e100ab
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithNoModuleArg.java
@@ -0,0 +1,71 @@
+/*
+ * 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 jdk.embargo;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class TestWithNoModuleArg {
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Usage: java ... basename should-be-loaded-flag");
+            System.out.println("  ex. java ... jdk.test.resources.classes.MyResources false");
+            return;
+        }
+
+        String basename = args[0];
+        boolean shouldBeLoaded = "true".equals(args[1]);
+
+        int errors = 0;
+        try {
+            // Set the default Locale to Locale.ROOT to avoid any confusions related to fallback
+            Locale.setDefault(Locale.ROOT);
+            ResourceBundle rb = ResourceBundle.getBundle(basename);
+            if (shouldBeLoaded) {
+                System.out.println("Passed: got resource bundle:");
+            } else {
+                System.out.println("Failed: no MissingResourceException thrown");
+                errors++;
+            }
+            System.out.println("            bundle = " + rb);
+        } catch (MissingResourceException e) {
+            if (!shouldBeLoaded) {
+                System.out.println("Passed: got expected " + e);
+            } else {
+                System.out.println("Failed: got unexpected " + e);
+                errors++;
+            }
+            System.out.println("            cause = " + e.getCause());
+        } catch (Throwable t) {
+            System.out.println("Failed: unexpected throwable: " + t);
+            errors++;
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithUnnamedModuleArg.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithUnnamedModuleArg.java
new file mode 100644
index 0000000..8f2ca8e
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/jdk/embargo/TestWithUnnamedModuleArg.java
@@ -0,0 +1,78 @@
+/*
+ * 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 jdk.embargo;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class TestWithUnnamedModuleArg {
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Usage: java ... basename should-be-loaded-flag");
+            System.out.println("  ex. java ... jdk.test.resources.classes.MyResources false");
+            return;
+        }
+
+        String basename = args[0];
+        boolean shouldBeLoaded = "true".equals(args[1]);
+
+        int errors = 0;
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        try {
+            // Set the default Locale to Locale.ROOT to avoid any confusions related to fallback
+            Locale.setDefault(Locale.ROOT);
+            ResourceBundle rb = ResourceBundle.getBundle(basename,
+                                                         cl.getUnnamedModule());
+            if (shouldBeLoaded) {
+                System.out.println("Passed: got resource bundle:");
+            } else {
+                System.out.println("Failed: no MissingResourceException thrown");
+                errors++;
+            }
+            System.out.println("        bundle = " + rb);
+        } catch (MissingResourceException e) {
+            if (!shouldBeLoaded) {
+                System.out.println("Passed: got expected " + e);
+            } else {
+                System.out.println("Failed: got unexpected " + e);
+                errors++;
+            }
+            System.out.println("        cause = " + e.getCause());
+        } catch (Throwable t) {
+            System.out.println("Failed: unexpected throwable: " + t);
+            errors++;
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/module-info.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/module-info.java
new file mode 100644
index 0000000..3455a3b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/embargo/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 embargo {
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResources.java
new file mode 100644
index 0000000..8de8bea
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.exported.classes;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResourcesProvider.java
new file mode 100644
index 0000000..86d9daf
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/classes/MyResourcesProvider.java
@@ -0,0 +1,48 @@
+/*
+ * 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 jdk.test.resources.exported.classes;
+
+import java.util.Locale;
+import java.util.spi.AbstractResourceBundleProvider;
+
+public class MyResourcesProvider extends AbstractResourceBundleProvider {
+    public MyResourcesProvider() {
+        super("java.class", "java.properties");
+        System.err.println("MyResourcesProvider called " + this);
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        StringBuilder sb = new StringBuilder(baseName);
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/props/MyResources.properties b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/props/MyResources.properties
new file mode 100644
index 0000000..a988528
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/jdk/test/resources/exported/props/MyResources.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=root: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/module-info.java
new file mode 100644
index 0000000..a110e88
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/exported.named.bundles/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module exported.named.bundles {
+    // unqualified exports to verify that resource bundles are not picked
+    // up by other named modules
+    exports jdk.test.resources.exported.classes;
+    provides jdk.test.resources.exported.classes.MyResourcesProvider
+        with jdk.test.resources.exported.classes.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResources.java
new file mode 100644
index 0000000..08cc009
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.test.resources.classes;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResourcesProvider.java
new file mode 100644
index 0000000..70c391c
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/classes/MyResourcesProvider.java
@@ -0,0 +1,60 @@
+/*
+ * 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 jdk.test.resources.classes;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.spi.AbstractResourceBundleProvider;
+
+public class MyResourcesProvider extends AbstractResourceBundleProvider {
+    public MyResourcesProvider() {
+        super("java.class");
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        StringBuilder sb = new StringBuilder(baseName);
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        ResourceBundle rb = super.getBundle(baseName, locale);
+        String tag = locale.toLanguageTag();
+        if (tag.equals("und")) {
+            tag = "ROOT"; // to a human friendly name
+        }
+        System.out.printf("    MyResourcesProvider.getBundle(%s, %s)%n         -> %s%n",
+                          baseName, tag, rb);
+        return rb;
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResources.properties b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResources.properties
new file mode 100644
index 0000000..a988528
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResources.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=root: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResourcesProvider.java
new file mode 100644
index 0000000..73b92fb
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/jdk/test/resources/props/MyResourcesProvider.java
@@ -0,0 +1,60 @@
+/*
+ * 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 jdk.test.resources.props;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.spi.AbstractResourceBundleProvider;
+
+public class MyResourcesProvider extends AbstractResourceBundleProvider {
+    public MyResourcesProvider() {
+        super("java.properties");
+    }
+
+    @Override
+    protected String toBundleName(String baseName, Locale locale) {
+        StringBuilder sb = new StringBuilder(baseName);
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        ResourceBundle rb = super.getBundle(baseName, locale);
+        String tag = locale.toLanguageTag();
+        if (tag.equals("und")) {
+            tag = "ROOT"; // to a human friendly name
+        }
+        System.out.printf("    MyResourcesProvider.getBundle(%s, %s)%n         -> %s%n",
+                          baseName, tag, rb);
+        return rb;
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/module-info.java
new file mode 100644
index 0000000..a9fd37f
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/named.bundles/module-info.java
@@ -0,0 +1,31 @@
+/*
+ * 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 named.bundles {
+    exports jdk.test.resources.classes to test; // exports only to test
+    exports jdk.test.resources.props to test;   // exports only to test
+    provides jdk.test.resources.classes.MyResourcesProvider
+        with jdk.test.resources.classes.MyResourcesProvider;
+    provides jdk.test.resources.props.MyResourcesProvider
+        with jdk.test.resources.props.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/classes/MyResources.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/classes/MyResources.java
new file mode 100644
index 0000000..0c8c3f7
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/classes/MyResources.java
@@ -0,0 +1,35 @@
+/*
+ * 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 jdk.pkg.resources.classes;
+
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/props/MyResources.properties b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/props/MyResources.properties
new file mode 100644
index 0000000..a988528
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/resources/props/MyResources.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=root: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/test/Main.java
new file mode 100644
index 0000000..54ac2e7
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/pkg/jdk/pkg/test/Main.java
@@ -0,0 +1,78 @@
+/*
+ * 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 jdk.pkg.test;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Usage: java ... basename should-be-loaded-flag");
+            System.out.println("  ex. java ... jdk.test.resources.classes.MyResources false");
+            return;
+        }
+
+        String basename = args[0];
+        boolean shouldBeLoaded = "true".equals(args[1]);
+
+        int errors = 0;
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        try {
+            // Use the default Locale to avoid confusion related to fallback
+            Locale.setDefault(Locale.ENGLISH);
+            ResourceBundle rb = ResourceBundle.getBundle(basename,
+                                                         cl.getUnnamedModule());
+            if (shouldBeLoaded) {
+                System.out.println("Passed: got resource bundle:");
+            } else {
+                System.out.println("Failed: no MissingResourceException thrown");
+                errors++;
+            }
+            System.out.println("            bundle = " + rb);
+        } catch (MissingResourceException e) {
+            if (!shouldBeLoaded) {
+                System.out.println("Passed: got expected " + e);
+            } else {
+                System.out.println("Failed: got unexpected " + e);
+                errors++;
+            }
+            System.out.println("            cause = " + e.getCause());
+        } catch (Throwable t) {
+            System.out.println("Failed: unexpected throwable: " + t);
+            errors++;
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithNoModuleArg.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithNoModuleArg.java
new file mode 100644
index 0000000..19de28a
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithNoModuleArg.java
@@ -0,0 +1,71 @@
+/*
+ * 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 jdk.test;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class TestWithNoModuleArg {
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Usage: java ... basename should-be-loaded-flag");
+            System.out.println("  ex. java ... jdk.test.resources.classes.MyResources false");
+            return;
+        }
+
+        String basename = args[0];
+        boolean shouldBeLoaded = "true".equals(args[1]);
+
+        int errors = 0;
+        try {
+            // Set the default Locale to Locale.ROOT to avoid any confusions related to fallback
+            Locale.setDefault(Locale.ROOT);
+            ResourceBundle rb = ResourceBundle.getBundle(basename);
+            if (shouldBeLoaded) {
+                System.out.println("Passed: got resource bundle:");
+            } else {
+                System.out.println("Failed: no MissingResourceException thrown");
+                errors++;
+            }
+            System.out.println("            bundle = " + rb);
+        } catch (MissingResourceException e) {
+            if (!shouldBeLoaded) {
+                System.out.println("Passed: got expected " + e);
+            } else {
+                System.out.println("Failed: got unexpected " + e);
+                errors++;
+            }
+            System.out.println("            cause = " + e.getCause());
+        } catch (Throwable t) {
+            System.out.println("Failed: unexpected throwable: " + t);
+            errors++;
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithUnnamedModuleArg.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithUnnamedModuleArg.java
new file mode 100644
index 0000000..d36b53f
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/jdk/test/TestWithUnnamedModuleArg.java
@@ -0,0 +1,78 @@
+/*
+ * 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 jdk.test;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class TestWithUnnamedModuleArg {
+    public static void main(String[] args) throws Exception {
+        if (args.length != 2) {
+            System.out.println("Usage: java ... basename should-be-loaded-flag");
+            System.out.println("  ex. java ... jdk.test.resources.classes.MyResources false");
+            return;
+        }
+
+        String basename = args[0];
+        boolean shouldBeLoaded = "true".equals(args[1]);
+
+        int errors = 0;
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null) {
+            cl = ClassLoader.getSystemClassLoader();
+        }
+
+        try {
+            // Set the default Locale to Locale.ROOT to avoid any confusions related to fallback
+            Locale.setDefault(Locale.ROOT);
+            ResourceBundle rb = ResourceBundle.getBundle(basename,
+                                                         cl.getUnnamedModule());
+            if (shouldBeLoaded) {
+                System.out.println("Passed: got resource bundle:");
+            } else {
+                System.out.println("Failed: no MissingResourceException thrown");
+                errors++;
+            }
+            System.out.println("            bundle = " + rb);
+        } catch (MissingResourceException e) {
+            if (!shouldBeLoaded) {
+                System.out.println("Passed: got expected " + e);
+            } else {
+                System.out.println("Failed: got unexpected " + e);
+                errors++;
+            }
+            System.out.println("            cause = " + e.getCause());
+        } catch (Throwable t) {
+            System.out.println("Failed: unexpected throwable: " + t);
+            errors++;
+        }
+
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/module-info.java
new file mode 100644
index 0000000..00954c8
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/src/test/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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 test {
+    // jdk.test.resources.classes.MyResourcesProvider is in named.bundles.
+    requires named.bundles;
+    uses jdk.test.resources.classes.MyResourcesProvider;
+    uses jdk.test.resources.props.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh b/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh
new file mode 100644
index 0000000..02ca3c4
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh
@@ -0,0 +1,233 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8137317 8139238
+# @summary Visibility tests for ResourceBundle.getBundle with and without
+# an unnamed module argument.
+
+
+set -e
+STATUS=0
+
+runJava()
+{
+    echo "Executing java $@"
+    $JAVA $@ || STATUS=1
+    echo
+}
+
+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 classes
+
+MODS=`cd $TESTSRC/src; find . -name module-info.java -exec dirname {} \; | sed 's:\./::'`
+
+for M in $MODS
+do
+    mkdir -p mods/$M
+    CLASSES="`find $TESTSRC/src/$M -name '*.java'`"
+    if [ "x$CLASSES" != x ]; then
+        $JAVAC -g -d mods -modulesourcepath $TESTSRC/src $CLASSES
+    fi
+    PROPS="`(cd $TESTSRC/src/$M; find . -name '*.properties')`"
+    if [ "x$PROPS" != x ]; then
+        for P in $PROPS
+        do
+            D=`dirname $P`
+            mkdir -p mods/$M/$D
+            cp $TESTSRC/src/$M/$P mods/$M/$D/
+        done
+    fi
+done
+
+# Package jdk.test is in named module "test".
+# Package jdk.embargo is in named module "embargo".
+
+# jdk.{test,embargo}.TestWithUnnamedModuleArg call:
+#     ResourceBundle.getBundle(basename, classloader.getUnnamedModule())
+#     where classloader is the TCCL or system class loader.
+# jdk.{test,embargo}.TestWithNoModuleArg call:
+#     ResourceBundle.getBundle(basename)
+
+# jdk.test.resources[.exported].classes.* are class-based resource bundles.
+# jdk.test.resources[.exported].props.* are properties file-based resource bundles.
+
+# Packages jdk.test.resources.{classes,props} in named module "named.bundles"
+# are exported only to named module "test".
+# Packages jdk.test.resources.exported.{classes,props} in named module
+# "exported.named.bundle" are exported to unnamed modules.
+
+########################################
+# Test cases with jdk.test.resources.* #
+########################################
+
+# Tests using jdk.test.TestWithNoModuleArg and jdk.embargo.TestWithNoModuleArg
+# neither of which specifies an unnamed module with ResourceBundle.getBundle().
+
+# jdk.test.resources.{classes,props}.* are available only to named module "test"
+# by ResourceBundleProvider.
+runJava -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.classes.MyResources true
+runJava -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.props.MyResources true
+runJava -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.classes.MyResources false
+runJava -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.props.MyResources false
+
+# Add mods/named.bundles to the class path.
+runJava -cp mods/named.bundles -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.classes.MyResources true
+runJava -cp mods/named.bundles -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.props.MyResources true
+runJava -cp mods/named.bundles -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.classes.MyResources false
+runJava -cp mods/named.bundles -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.props.MyResources false
+
+# Tests using jdk.test.TestWithUnnamedModuleArg and jdk.embargo.TestWithUnnamedModuleArg
+# both of which specify an unnamed module with ResourceBundle.getBundle.
+
+# jdk.test.resources.classes is exported to named module "test".
+# IllegalAccessException is thrown in ResourceBundle.Control.newBundle().
+runJava -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+    jdk.test.resources.classes.MyResources false
+
+# jdk.test.resources.props is exported to named module "test".
+# loader.getResource() doesn't find jdk.test.resources.props.MyResources.
+runJava -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+    jdk.test.resources.props.MyResources false
+
+# IllegalAccessException is thrown in ResourceBundle.Control.newBundle().
+runJava -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+    jdk.test.resources.classes.MyResources false
+# jdk.test.resources.props is exported to named module "test".
+# loader.getResource() doesn't find jdk.test.resources.props.MyResources.
+runJava -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+    jdk.test.resources.props.MyResources false
+
+# Add mods/named.bundles to the class path
+
+# IllegalAccessException is thrown in ResourceBundle.Control.newBundle().
+runJava -cp mods/named.bundles -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.classes.MyResources false
+# loader.getResource() finds jdk.test.resources.exported.props.MyResources.
+runJava -cp mods/named.bundles -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.props.MyResources true
+
+# jdk.test.resources.exported.classes.MyResources is treated
+# as if the class is in an unnamed module.
+runJava -cp mods/named.bundles -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.classes.MyResources true
+# loader.getResource() finds jdk.test.resources.exported.props.MyResources.
+runJava -cp mods/named.bundles -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.props.MyResources true
+
+#################################################
+# Test cases with jdk.test.resources.exported.* #
+#################################################
+# Tests using jdk.test.TestWithNoModuleArg and jdk.embargo.TestWithNoModuleArg
+# neither of which specifies an unnamed module with ResourceBundle.getBundle.
+
+# None of jdk.test.resources.exported.** is available to the named modules.
+runJava -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.exported.classes.MyResources false
+runJava -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.exported.props.MyResources false
+runJava -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.exported.classes.MyResources false
+runJava -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.exported.props.MyResources false
+
+# Add mods/exported.named.bundles to the class path.
+runJava -cp mods/exported.named.bundles -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.exported.classes.MyResources false
+runJava -cp mods/exported.named.bundles -mp mods -m test/jdk.test.TestWithNoModuleArg \
+    jdk.test.resources.exported.props.MyResources false
+runJava -cp mods/exported.named.bundles -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.exported.classes.MyResources false
+runJava -cp mods/exported.named.bundles -mp mods -m embargo/jdk.embargo.TestWithNoModuleArg \
+    jdk.test.resources.exported.props.MyResources false
+
+# Tests using jdk.test.TestWithUnnamedModuleArg and jdk.embargo.TestWithUnnamedModuleArg
+# which specify an unnamed module with ResourceBundle.getBundle.
+
+# loader.loadClass() doesn't find jdk.test.resources.exported.classes.MyResources
+# and throws a ClassNotFoundException.
+runJava -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.classes.MyResources false
+# The properties files in jdk.test.resources.exported.props are not found with loader.getResource().
+runJava -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.props.MyResources false
+
+
+# loader.loadClass() doesn't find jdk.test.resources.exported.classes.MyResources
+# and throws a ClassNotFoundException.
+runJava -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.classes.MyResources false
+# The properties files in jdk.test.resources.exported.props are not found
+# with loader.getResource().
+runJava -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.props.MyResources false
+
+# Add mods/exported.named.bundles to the class path.
+
+# jdk.test.resources.exported.classes.MyResources.getModule().isNamed() returns false.
+runJava -cp mods/exported.named.bundles -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.classes.MyResources true
+# loader.getResource() finds jdk.test.resources.exported.props.MyResources.
+runJava -cp mods/exported.named.bundles -mp mods -m test/jdk.test.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.props.MyResources true
+
+# jdk.test.resources.exported.classes.MyResources.getModule().isNamed() returns false.
+runJava -cp mods/exported.named.bundles -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.classes.MyResources true
+# loader.getResource() finds jdk.test.resources.exported.props.MyResources.
+runJava -cp mods/exported.named.bundles -mp mods -m embargo/jdk.embargo.TestWithUnnamedModuleArg \
+        jdk.test.resources.exported.props.MyResources true
+
+#######################################
+# Test cases with jdk.pkg.resources.* #
+#######################################
+# Prepare resource bundles in an unnamed module
+PKG=$TESTSRC/src/pkg
+mkdir -p classes/jdk/pkg/resources/props
+$JAVAC -g -d classes $PKG/jdk/pkg/test/Main.java $PKG/jdk/pkg/resources/classes/MyResources.java
+cp $PKG/jdk/pkg/resources/props/MyResources.properties classes/jdk/pkg/resources/props
+
+# jdk.pkg.resources.* are in an unnamed module.
+# jdk.pkg.test.Main calls ResourceBundle.getBundle with an unnamed module.
+runJava -cp classes jdk.pkg.test.Main jdk.pkg.resources.classes.MyResources true
+runJava -cp classes jdk.pkg.test.Main jdk.pkg.resources.props.MyResources true
+
+exit $STATUS
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources.xml
new file mode 100644
index 0000000..dc4be6b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle</comment>
+    <entry key="key">root: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResourcesProvider.java b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResourcesProvider.java
new file mode 100644
index 0000000..ca4cec5
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResourcesProvider.java
@@ -0,0 +1,81 @@
+/*
+ * 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 jdk.test.resources;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.spi.ResourceBundleProvider;
+
+public class MyResourcesProvider implements ResourceBundleProvider {
+    @Override
+    public ResourceBundle getBundle(String baseName, Locale locale) {
+        String xmlName = toXMLName(baseName, locale);
+        try (InputStream is = this.getClass().getModule().getResourceAsStream(xmlName)) {
+            return new XMLResourceBundle(new BufferedInputStream(is));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String toXMLName(String baseName, Locale locale) {
+        StringBuilder sb = new StringBuilder(baseName.replace('.', '/'));
+        String lang = locale.getLanguage();
+        if (!lang.isEmpty()) {
+            sb.append('_').append(lang);
+            String country = locale.getCountry();
+            if (!country.isEmpty()) {
+                sb.append('_').append(country);
+            }
+        }
+        return sb.append(".xml").toString();
+    }
+
+    private static class XMLResourceBundle extends ResourceBundle {
+        private Properties props;
+
+        XMLResourceBundle(InputStream stream) throws IOException {
+            props = new Properties();
+            props.loadFromXML(stream);
+        }
+
+        @Override
+        protected Object handleGetObject(String key) {
+            if (key == null) {
+                throw new NullPointerException();
+            }
+            return props.get(key);
+        }
+
+        @Override
+        public Enumeration<String> getKeys() {
+            // Not implemented
+            return null;
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_de.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_de.xml
new file mode 100644
index 0000000..cfaa5dd
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_de.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle</comment>
+    <entry key="key">de: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_en.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_en.xml
new file mode 100644
index 0000000..0213a21
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_en.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle</comment>
+    <entry key="key">en: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_fr.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_fr.xml
new file mode 100644
index 0000000..d6b57ef
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_fr.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle</comment>
+    <entry key="key">fr: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_ja.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_ja.xml
new file mode 100644
index 0000000..6d82961
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_ja.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle in named modules.</comment>
+    <entry key="key">ja: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh.xml
new file mode 100644
index 0000000..df1a2b7
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle in named modules.</comment>
+    <entry key="key">zh: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh_TW.xml b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh_TW.xml
new file mode 100644
index 0000000..5ce424a
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/jdk/test/resources/MyResources_zh_TW.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+    <comment>Test data for ResourceBundle in named modules.</comment>
+    <entry key="key">zh-TW: message</entry>
+</properties>
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/module-info.java b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/module-info.java
new file mode 100644
index 0000000..7725c44
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/bundles/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 bundles {
+    exports jdk.test.resources to test;
+    provides jdk.test.resources.MyResourcesProvider with jdk.test.resources.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/jdk/test/Main.java b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..d93cb62
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/jdk/test/Main.java
@@ -0,0 +1,51 @@
+/*
+ * 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 jdk.test;
+
+import java.util.Locale;
+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("locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                System.out.println("ERROR: " + value + " expected: " + tag);
+                errors++;
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/module-info.java b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/module-info.java
new file mode 100644
index 0000000..c5ac262
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/src/test/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test {
+    requires bundles;
+
+    uses jdk.test.resources.MyResourcesProvider;
+}
diff --git a/jdk/test/java/util/ResourceBundle/modules/xmlformat/xmlformat.sh b/jdk/test/java/util/ResourceBundle/modules/xmlformat/xmlformat.sh
new file mode 100644
index 0000000..8495232
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/xmlformat/xmlformat.sh
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @summary Simple test case for ResourceBundle with modules;
+#          ResourceBundle.getBundle caller is in module named "test" and
+#          all resource bundles are in single module named "bundles".
+
+
+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 -modulesourcepath $TESTSRC/src $CLASSES
+fi
+PROPS="`(cd $TESTSRC/src/$B; find . -name '*.xml')`"
+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
+
+$JAVAC -g -d mods -modulesourcepath $TESTSRC/src \
+       -cp mods/bundles `find $TESTSRC/src/test -name "*.java"`
+
+$JAVA -mp mods -m test/jdk.test.Main de fr ja zh-tw en de
+
+exit $?
diff --git a/jdk/test/java/util/Scanner/ScannerStreamTest.java b/jdk/test/java/util/Scanner/ScannerStreamTest.java
index 0f555c5..98d28a7 100644
--- a/jdk/test/java/util/Scanner/ScannerStreamTest.java
+++ b/jdk/test/java/util/Scanner/ScannerStreamTest.java
@@ -46,8 +46,8 @@
  * @test
  * @bug 8072722
  * @summary Tests of stream support in java.util.Scanner
- * @library ../stream/bootlib/java.base
- * @build java.util.stream.OpTestCase
+ * @library ../stream/bootlib
+ * @build java.base/java.util.stream.OpTestCase
  * @run testng/othervm ScannerStreamTest
  */
 
diff --git a/jdk/test/java/util/ServiceLoader/TwoIterators.java b/jdk/test/java/util/ServiceLoader/TwoIterators.java
new file mode 100644
index 0000000..ddb9cc0
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/TwoIterators.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Test ServiceLoader with two iterators, interleaving their use
+ *   to test that they don't interfere with each other
+ * @run testng TwoIterators
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class TwoIterators {
+
+    // service type
+    public static interface S { }
+
+    // service provider implementations
+    public static class S1 implements S { }
+    public static class S2 implements S { }
+
+    private ClassLoader testClassLoader;
+
+    // creates the services configuration file and sets the ClassLoader
+    @BeforeClass
+    void setup() throws Exception {
+        String classes = System.getProperty("test.classes");
+        Path dir = Paths.get(classes, "META-INF", "services");
+        Files.createDirectories(dir);
+        Path config = dir.resolve(S.class.getName());
+        Files.write(config, Arrays.asList(S1.class.getName(), S2.class.getName()));
+
+        this.testClassLoader = TwoIterators.class.getClassLoader();
+    }
+
+    @Test
+    public void testSequentialUse1() {
+        ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+        Iterator<S> iterator1 = sl.iterator();
+        iterator1.next();
+        iterator1.next();
+        assertFalse(iterator1.hasNext());
+
+        Iterator<S> iterator2 = sl.iterator();
+        iterator2.next();
+        iterator2.next();
+        assertFalse(iterator2.hasNext());
+    }
+
+    @Test
+    public void testSequentialUse2() {
+        ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+        Iterator<S> iterator1 = sl.iterator();
+        Iterator<S> iterator2 = sl.iterator();
+
+        iterator1.next();
+        iterator1.next();
+        assertFalse(iterator1.hasNext());
+
+        iterator2.next();
+        iterator2.next();
+        assertFalse(iterator2.hasNext());
+    }
+
+    @Test
+    public void testInterleaved1() {
+        ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+        Iterator<S> iterator1 = sl.iterator();
+        Iterator<S> iterator2 = sl.iterator();
+
+        iterator1.next();
+        iterator2.next();
+        iterator1.next();
+        iterator2.next();
+        assertFalse(iterator1.hasNext());
+        assertFalse(iterator2.hasNext());
+    }
+
+    @Test
+    public void testInterleaved2() {
+        ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+        Iterator<S> iterator1 = sl.iterator();
+        iterator1.next();
+
+        Iterator<S> iterator2 = sl.iterator();
+
+        assertTrue(iterator1.hasNext());
+        assertTrue(iterator2.hasNext());
+
+        iterator1.next();
+        iterator2.next();
+        iterator2.next();
+
+        assertFalse(iterator1.hasNext());
+        assertFalse(iterator2.hasNext());
+    }
+
+    @Test
+    public void testInterleaved3() {
+        ServiceLoader<S> sl = ServiceLoader.load(S.class, testClassLoader);
+
+        Iterator<S> iterator1 = sl.iterator();
+        iterator1.next();
+
+        Iterator<S> iterator2 = sl.iterator();
+
+        assertTrue(iterator2.hasNext());
+        assertTrue(iterator1.hasNext());
+
+        iterator2.next();
+        iterator2.next();
+        iterator1.next();
+
+        assertFalse(iterator1.hasNext());
+        assertFalse(iterator2.hasNext());
+    }
+}
+
diff --git a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java b/jdk/test/java/util/ServiceLoader/modules/BasicTest.java
new file mode 100644
index 0000000..3b64a1d
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/BasicTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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 BasicTest
+ * @summary Basic test of ServiceLoader with modules
+ */
+
+public class BasicTest {
+
+    @Test
+    public void testEmptyLayer() {
+        ServiceLoader<Provider> sl
+            = ServiceLoader.load(Layer.empty(), Provider.class);
+        assertFalse(sl.iterator().hasNext());
+    }
+
+    @Test
+    public void testBootLayer() {
+        ServiceLoader<Provider> sl
+            = ServiceLoader.load(Layer.boot(), Provider.class);
+        boolean found = false;
+        for (Provider provider : sl) {
+            if (provider.getName().equals("SunJCE"))
+                found = true;
+        }
+        assertTrue(found);
+    }
+
+    @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
new file mode 100644
index 0000000..abb90c0
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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 -modulepath.
+     *
+     * BananaScriptEngine should be found.
+     */
+    public void runWithModulePath() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-m", "test/test.Main",
+                              "BananaScriptEngine")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Run test with -modulepath and -classpath.
+     *
+     * Both BananaScriptEngine and PearScriptEngine should be found
+     */
+    public void runWithModulePathAndClassPath() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-cp", CLASSES_DIR.toString(),
+                              "-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.empty(), 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/jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java b/jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java
new file mode 100644
index 0000000..d599d44
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * 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 bananascript {
+    requires java.scripting;
+
+    provides javax.script.ScriptEngineFactory
+      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/src/bananascript/org/banana/BananaScript.java
new file mode 100644
index 0000000..ddaf1e1
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScript.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+package org.banana;
+
+import java.io.Reader;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class BananaScript implements ScriptEngine {
+
+    @Override
+    public Object eval(String script, ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script, Bindings n) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , Bindings n) {
+        throw new RuntimeException();
+    }
+    @Override
+    public void put(String key, Object value) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object get(String key) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings getBindings(int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setBindings(Bindings bindings, int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings createBindings() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptContext getContext() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setContext(ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngineFactory getFactory() {
+        throw new RuntimeException();
+    }
+}
+
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java
new file mode 100644
index 0000000..443415c
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.banana;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class BananaScriptEngineFactory implements ScriptEngineFactory {
+
+    @Override
+    public String getEngineName() {
+        return "BananaScriptEngine";
+    }
+
+    @Override
+    public String getEngineVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public List<String> getExtensions() {
+        return Arrays.asList("banana");
+    }
+
+    @Override
+    public List<String> getMimeTypes() {
+        return Arrays.asList("application/x-bananascript");
+    }
+
+    @Override
+    public List<String> getNames() {
+        return Arrays.asList("BananaScript");
+    }
+
+    @Override
+    public String getLanguageName() {
+        return "BananaScript";
+    }
+
+    @Override
+    public String getLanguageVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public Object getParameter(String key) {
+        return null;
+    }
+
+    @Override
+    public String getMethodCallSyntax(String obj, String m, String... args) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getOutputStatement(String toDisplay) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getProgram(String... statements) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngine getScriptEngine() {
+        return new BananaScript();
+    }
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/META-INF/services/javax.script.ScriptEngineFactory b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..c0d757e
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.pear.PearScriptEngineFactory
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScript.java b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScript.java
new file mode 100644
index 0000000..b8400c0
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScript.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package org.pear;
+
+import java.io.Reader;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class PearScript implements ScriptEngine {
+
+    @Override
+    public Object eval(String script, ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script, Bindings n) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , Bindings n) {
+        throw new RuntimeException();
+    }
+    @Override
+    public void put(String key, Object value) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object get(String key) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings getBindings(int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setBindings(Bindings bindings, int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings createBindings() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptContext getContext() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setContext(ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngineFactory getFactory() {
+        throw new RuntimeException();
+    }
+}
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
new file mode 100644
index 0000000..c00c4b1
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.pear;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class PearScriptEngineFactory implements ScriptEngineFactory {
+
+    @Override
+    public String getEngineName() {
+        return "PearScriptEngine";
+    }
+
+    @Override
+    public String getEngineVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public List<String> getExtensions() {
+        return Arrays.asList("pear");
+    }
+
+    @Override
+    public List<String> getMimeTypes() {
+        return Arrays.asList("application/x-pearscript");
+    }
+
+    @Override
+    public List<String> getNames() {
+        return Arrays.asList("PearScript");
+    }
+
+    @Override
+    public String getLanguageName() {
+        return "PearScript";
+    }
+
+    @Override
+    public String getLanguageVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public Object getParameter(String key) {
+        return null;
+    }
+
+    @Override
+    public String getMethodCallSyntax(String obj, String m, String... args) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getOutputStatement(String toDisplay) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getProgram(String... statements) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngine getScriptEngine() {
+        return new PearScript();
+    }
+}
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
new file mode 100644
index 0000000..a43887c
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/test/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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
new file mode 100644
index 0000000..a03d8eb
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/src/test/test/Main.java
@@ -0,0 +1,44 @@
+/*
+ * 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/logging/LocalizedLevelName.java b/jdk/test/java/util/logging/LocalizedLevelName.java
index cdb425a..561e2d1 100644
--- a/jdk/test/java/util/logging/LocalizedLevelName.java
+++ b/jdk/test/java/util/logging/LocalizedLevelName.java
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import java.lang.reflect.Module;
 import java.util.*;
 import java.util.logging.*;
 
@@ -97,7 +98,10 @@
 
     private static final String RBNAME = "sun.util.logging.resources.logging";
     private static String getLocalizedMessage(Locale locale, String key) {
-        ResourceBundle rb = ResourceBundle.getBundle(RBNAME, locale);
+        // this test verifies if the logging.properties in the java.logging module
+        // is localized.
+        Module module = java.util.logging.Level.class.getModule();
+        ResourceBundle rb = ResourceBundle.getBundle(RBNAME, locale, module);
         return rb.getString(key);
     }
 }
diff --git a/jdk/test/java/util/logging/modules/GetResourceBundleTest.java b/jdk/test/java/util/logging/modules/GetResourceBundleTest.java
new file mode 100644
index 0000000..c049613
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/GetResourceBundleTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static jdk.testlibrary.ProcessTools.*;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8129126 8136802 8137316 8137317 8136804 8139350
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build GetResourceBundleTest CompilerUtils jdk.testlibrary.ProcessTools
+ * @run testng GetResourceBundleTest
+ * @summary Tests Logger.getLogger + logger.getResourceBundle in an named/unnamed module,
+ *          resources are in named and unnamed modules respectively.
+ *          Positive tests to ensure that a Logger can retrieve ResourceBundle in its current module.
+ *          Negative tests to ensure that a Logger cannot retrieve ResourceBundle in another module.
+ *          This test also verifies 8136802 8137316 8137317 8136804 8139350.
+ */
+
+public class GetResourceBundleTest {
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path MOD_SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MOD_DEST_DIR = Paths.get("mods");
+    private static final Path PKG_SRC_DIR = Paths.get(TEST_SRC, "pkgs");
+    private static final Path PKG_DEST_DIR = Paths.get("pkgs");
+
+    private static final String[] modules = new String[] {"m1", "m2"};
+
+    /**
+     * Compiles all modules used by the test, copy resource files.
+     */
+    @BeforeClass
+    public void setup() throws Exception {
+        // compile all modules
+        for (String mn : modules) {
+            Path msrc = MOD_SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MOD_DEST_DIR,
+                    "-modulesourcepath", MOD_SRC_DIR.toString()));
+        }
+        assertTrue(CompilerUtils.compile(PKG_SRC_DIR, PKG_DEST_DIR,
+                "-modulepath", MOD_DEST_DIR.toString(), "-addmods", String.join(",", modules)));
+
+        // copy resource files
+        String[] files = { "m1/p1/resource/p.properties", "m2/p2/resource/p.properties" };
+        for(String f : files) {
+            Files.copy(MOD_SRC_DIR.resolve(f), MOD_DEST_DIR.resolve(f), REPLACE_EXISTING);
+        }
+        String p3 = "p3/resource/p.properties";
+        Files.copy(PKG_SRC_DIR.resolve(p3), PKG_DEST_DIR.resolve(p3), REPLACE_EXISTING);
+    }
+
+    @Test
+    public void runWithoutSecurityManager() throws Exception {
+        int exitValue = executeTestJava(
+                "-cp", PKG_DEST_DIR.toString(),
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "p3.test.ResourceBundleTest")
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+    }
+
+    @Test
+    public void runWithSecurityManager() throws Exception {
+        int exitValue = executeTestJava(
+                "-Djava.security.manager",
+                "-cp", PKG_DEST_DIR.toString(),
+                "-mp", MOD_DEST_DIR.toString(),
+                "-addmods", String.join(",", modules),
+                "p3.test.ResourceBundleTest")
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+    }
+}
diff --git a/jdk/test/java/util/logging/modules/pkgs/p3/resource/ClassResource.java b/jdk/test/java/util/logging/modules/pkgs/p3/resource/ClassResource.java
new file mode 100644
index 0000000..2cdb727
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/pkgs/p3/resource/ClassResource.java
@@ -0,0 +1,35 @@
+/*
+ * 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.resource;
+
+import java.util.ListResourceBundle;
+
+public class ClassResource extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+                { "OkKey", "OK" },
+                { "CancelKey", "Cancel" }, };
+    }
+}
diff --git a/jdk/test/java/util/logging/modules/pkgs/p3/resource/p.properties b/jdk/test/java/util/logging/modules/pkgs/p3/resource/p.properties
new file mode 100644
index 0000000..f1861bc
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/pkgs/p3/resource/p.properties
@@ -0,0 +1 @@
+OkKey=OK
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
new file mode 100644
index 0000000..2989a78
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/pkgs/p3/test/ResourceBundleTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.test;
+
+import java.lang.reflect.Module;
+import java.util.logging.Logger;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import p2.test.ModuleLoggerAccess;
+
+/*
+ * Test Logger.getLogger + logger.getResourceBundle in unnamed/named module,
+ * resources are in named and unnamed modules respectively.
+ */
+public class ResourceBundleTest {
+    private static final String RESOURCE_KEY = "OkKey";
+    private static final String RESOURCE_VALUE = "OK";
+
+    private static final String HELP_MSG =
+            "Test that a class in a %s module %s obtain a logger " +
+            "which uses a resource bundle %s bundled in " +
+            "%s module. ( The package in which the resource is " +
+            "contained is not exported by the module )";
+    private static final String NAMED_POSITIVE_CLASSBUNDLE_MSG =
+            String.format(HELP_MSG, "named", "can", "class", "the same");
+    private static final String UNNAMED_POSITIVE_CLASSBUNDLE_MSG =
+            String.format(HELP_MSG, "unnamed", "can", "class", "the same");
+    private static final String NAMED_POSITIVE_PROPERTYBUNDLE_MSG =
+            String.format(HELP_MSG, "named", "can", "property", "the same");
+    private static final String UNNAMED_POSITIVE_PROPERTYBUNDLE_MSG =
+            String.format(HELP_MSG, "unnamed", "can", "property", "the same");
+    private static final String NAMED_NEGATIVE_CLASSBUNDLE_MSG =
+            String.format(HELP_MSG, "named", "cannot", "class", "another");
+    private static final String UNNAMED_NEGATIVE_CLASSBUNDLE_MSG =
+            String.format(HELP_MSG, "unnamed", "cannot", "class", "another");
+    private static final String NAMED_NEGATIVE_PROPERTYBUNDLE_MSG =
+            String.format(HELP_MSG, "named", "cannot", "property", "another");
+    private static final String UNNAMED_NEGATIVE_PROPERTYBUNDLE_MSG =
+            String.format(HELP_MSG, "unnamed", "cannot", "property", "another");
+
+    public static void main(String[] args) {
+        verifySetup();
+        testLoggerRBs();
+        failToLoadRBs();
+    }
+
+    static void verifySetup() {
+        Module m = ResourceBundleTest.class.getModule();
+        System.out.println("Module Name for ResourceBundleTest : " + m.getName());
+        assertTrue(!m.isNamed());
+        m = ModuleLoggerAccess.class.getModule();
+        System.out.println("Module Name for ModuleLoggerAccess : " + m.getName());
+        assertTrue(m.isNamed());
+    }
+
+    /*
+     * Positive tests :
+     *  Should be able to access class/property resource bundle in current module,
+     *  no matter named or unnamed module.
+     */
+    static void testLoggerRBs() {
+        testLoggerClassRBs();
+        testLoggerPropertyRBs();
+    }
+
+    static void testLoggerClassRBs() {
+        testLoggerResoureBundle(
+                Logger.getLogger("mylogger.a", "p3.resource.ClassResource"),
+                p3.resource.ClassResource.class,
+                UNNAMED_POSITIVE_CLASSBUNDLE_MSG);
+        testLoggerResoureBundle(
+                ModuleLoggerAccess.getLogger("mylogger.b", "p2.resource.ClassResource"),
+                ModuleLoggerAccess.getResourceClass(),
+                NAMED_POSITIVE_CLASSBUNDLE_MSG);
+    }
+
+    static void testLoggerPropertyRBs() {
+        testLoggerResoureBundle(
+                Logger.getLogger("mylogger.c", "p3.resource.p"),
+                PropertyResourceBundle.class,
+                UNNAMED_POSITIVE_PROPERTYBUNDLE_MSG);
+        testLoggerResoureBundle(
+                ModuleLoggerAccess.getLogger("mylogger.d", "p2.resource.p"),
+                PropertyResourceBundle.class,
+                NAMED_POSITIVE_PROPERTYBUNDLE_MSG);
+    }
+
+    static void testLoggerResoureBundle(Logger logger, Class<?> rbType, String helpMsg) {
+        System.out.println(helpMsg);
+        ResourceBundle rb = logger.getResourceBundle();
+        assertTrue(rbType.isInstance(rb));
+        assertTrue(RESOURCE_VALUE.equals(rb.getString(RESOURCE_KEY)));
+    }
+
+    /*
+     * Negative tests :
+     *  MissingResourceException should be thrown when access class/property resource bundle
+     *  from another module, no matter named or unnamed module.
+     */
+    static void failToLoadRBs() {
+        failToLoadClassRBs();
+        failToLoadPropertyRBs();
+    }
+
+    static void failToLoadClassRBs() {
+        // in an unnamed module, try to create a logger with
+        // class resource bundle in named module m1 or m2.
+        failToLoadResourceBundle("mylogger.e", "p1.resource.ClassResource",
+                false, UNNAMED_NEGATIVE_CLASSBUNDLE_MSG);
+        failToLoadResourceBundle("mylogger.f", "p2.resource.ClassResource",
+                false, UNNAMED_NEGATIVE_CLASSBUNDLE_MSG);
+        // in named module m2, try to create a logger with
+        // 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() {
+        // in an unnamed module, try to create a logger with
+        // property resource bundle in named module m1 or m2.
+        failToLoadResourceBundle("mylogger.i", "p1.resource.p",
+                false, UNNAMED_NEGATIVE_PROPERTYBUNDLE_MSG);
+        failToLoadResourceBundle("mylogger.j", "p2.resource.p",
+                false, UNNAMED_NEGATIVE_PROPERTYBUNDLE_MSG);
+        // in named module m2, try to create a logger with
+        // 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,
+            boolean getLoggerInNamedModule, String helpMsg) {
+        String msg = String.format(
+                "Logger : %s. Expected exception is not thrown for ResourceBundle : %s.",
+                loggerName, rbName);
+        System.out.println(helpMsg);
+        try {
+            if(getLoggerInNamedModule) {
+                ModuleLoggerAccess.getLogger(loggerName, rbName);
+            } else {
+                Logger.getLogger(loggerName, rbName);
+            }
+            throw new RuntimeException(msg);
+        } catch (MissingResourceException expected) {
+            System.out.println("Get expected exception : " + expected);
+            return;
+        }
+    }
+
+    public static void assertTrue(boolean b) {
+        if (!b) {
+            throw new RuntimeException("Expect true, get false!");
+        }
+    }
+}
diff --git a/jdk/test/java/util/logging/modules/src/m1/module-info.java b/jdk/test/java/util/logging/modules/src/m1/module-info.java
new file mode 100644
index 0000000..a6e576f
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    requires java.logging;
+}
diff --git a/jdk/test/java/util/logging/modules/src/m1/p1/resource/ClassResource.java b/jdk/test/java/util/logging/modules/src/m1/p1/resource/ClassResource.java
new file mode 100644
index 0000000..227ff3d
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m1/p1/resource/ClassResource.java
@@ -0,0 +1,35 @@
+/*
+ * 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 p1.resource;
+
+import java.util.ListResourceBundle;
+
+public class ClassResource extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+                { "OkKey", "OK" },
+                { "CancelKey", "Cancel" }, };
+    }
+}
diff --git a/jdk/test/java/util/logging/modules/src/m1/p1/resource/p.properties b/jdk/test/java/util/logging/modules/src/m1/p1/resource/p.properties
new file mode 100644
index 0000000..f1861bc
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m1/p1/resource/p.properties
@@ -0,0 +1 @@
+OkKey=OK
diff --git a/jdk/test/java/util/logging/modules/src/m2/module-info.java b/jdk/test/java/util/logging/modules/src/m2/module-info.java
new file mode 100644
index 0000000..a2f3c66
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m2/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    requires m1;
+    requires java.logging;
+    exports p2.test;
+}
diff --git a/jdk/test/java/util/logging/modules/src/m2/p2/resource/ClassResource.java b/jdk/test/java/util/logging/modules/src/m2/p2/resource/ClassResource.java
new file mode 100644
index 0000000..09bd516
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m2/p2/resource/ClassResource.java
@@ -0,0 +1,34 @@
+/*
+ * 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 p2.resource;
+
+import java.util.ListResourceBundle;
+
+public class ClassResource extends ListResourceBundle {
+    protected Object[][] getContents() {
+        return new Object[][] {
+                { "OkKey", "OK" },
+                { "CancelKey", "Cancel" }, };
+    }
+}
diff --git a/jdk/test/java/util/logging/modules/src/m2/p2/resource/p.properties b/jdk/test/java/util/logging/modules/src/m2/p2/resource/p.properties
new file mode 100644
index 0000000..f1861bc
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m2/p2/resource/p.properties
@@ -0,0 +1 @@
+OkKey=OK
diff --git a/jdk/test/java/util/logging/modules/src/m2/p2/test/ModuleLoggerAccess.java b/jdk/test/java/util/logging/modules/src/m2/p2/test/ModuleLoggerAccess.java
new file mode 100644
index 0000000..4d322e0
--- /dev/null
+++ b/jdk/test/java/util/logging/modules/src/m2/p2/test/ModuleLoggerAccess.java
@@ -0,0 +1,41 @@
+/*
+ * 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 p2.test;
+
+import java.util.logging.Logger;
+
+/*
+ * Logger in this named module m2 loading a resource bundle
+ * in m2, m1 or unnamed module.
+ */
+public class ModuleLoggerAccess {
+
+    public static Logger getLogger(String loggerName, String rbName) {
+        return Logger.getLogger(loggerName, rbName);
+    }
+
+    public static Class<?> getResourceClass() {
+        return p2.resource.ClassResource.class;
+    }
+}
diff --git a/jdk/test/java/util/regex/PatternStreamTest.java b/jdk/test/java/util/regex/PatternStreamTest.java
index 1ac3bfd..1f02e41 100644
--- a/jdk/test/java/util/regex/PatternStreamTest.java
+++ b/jdk/test/java/util/regex/PatternStreamTest.java
@@ -25,8 +25,8 @@
  * @test
  * @bug 8016846 8024341 8071479 8145006
  * @summary Unit tests stream and lambda-based methods on Pattern and Matcher
- * @library ../stream/bootlib/java.base
- * @build java.util.stream.OpTestCase
+ * @library ../stream/bootlib
+ * @build java.base/java.util.stream.OpTestCase
  * @run testng/othervm PatternStreamTest
  */
 
diff --git a/jdk/test/java/util/stream/bootlib/TEST.properties b/jdk/test/java/util/stream/bootlib/TEST.properties
deleted file mode 100644
index 317080b..0000000
--- a/jdk/test/java/util/stream/bootlib/TEST.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file identifies root(s) of the test-ng hierarchy.
-
-bootclasspath.dirs = java.base
diff --git a/jdk/test/java/util/stream/boottest/TEST.properties b/jdk/test/java/util/stream/boottest/TEST.properties
index 980a89f..3c930e3 100644
--- a/jdk/test/java/util/stream/boottest/TEST.properties
+++ b/jdk/test/java/util/stream/boottest/TEST.properties
@@ -1,5 +1,4 @@
 # This file identifies root(s) of the test-ng hierarchy.
 
-TestNG.dirs = java.base
-bootclasspath.dirs = java.base
-lib.dirs = /java/util/stream/bootlib/java.base
+TestNG.dirs = .
+lib.dirs = /java/util/stream/bootlib
diff --git a/jdk/test/java/util/stream/test/TEST.properties b/jdk/test/java/util/stream/test/TEST.properties
index 706ed7c..4128f6a 100644
--- a/jdk/test/java/util/stream/test/TEST.properties
+++ b/jdk/test/java/util/stream/test/TEST.properties
@@ -2,7 +2,7 @@
 
 TestNG.dirs = .
 
-lib.dirs = /java/util/stream/bootlib/java.base
+lib.dirs = /java/util/stream/bootlib
 
 # Tests that must run in othervm mode
 othervm.dirs= /java/util/stream
diff --git a/jdk/test/javax/crypto/NullCipher/TestWithoutInit.java b/jdk/test/javax/crypto/NullCipher/TestWithoutInit.java
index 6039d09..a3fbf77 100644
--- a/jdk/test/javax/crypto/NullCipher/TestWithoutInit.java
+++ b/jdk/test/javax/crypto/NullCipher/TestWithoutInit.java
@@ -34,7 +34,6 @@
 
 import javax.crypto.*;
 import javax.crypto.spec.*;
-import com.sun.crypto.provider.*;
 
 public class TestWithoutInit {
 
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh b/jdk/test/javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh
new file mode 100644
index 0000000..196189a
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 8081729
+# @summary Test external plugin as classpath jar and as a modular jar.
+#          Test both cases with and without a security manager.
+
+set -e
+
+exception=0
+
+if [ -z "$TESTJAVA" ]; then
+  if [ $# -lt 1 ]; then  echo "No Java path specified. Exiting."; fi
+  if [ $# -lt 1 ]; then exit 1; fi
+  TESTJAVA="$1"; shift
+  COMPILEJAVA="${TESTJAVA}"
+  TESTSRC="`pwd`"
+  TESTCLASSES="`pwd`"
+fi
+
+JAVAC="$COMPILEJAVA/bin/javac"
+JAR="$COMPILEJAVA/bin/jar"
+JAVA="$TESTJAVA/bin/java ${TESTVMOPTS}"
+
+TESTDIR="$TESTCLASSES/classes"
+PLUGINDIR="$TESTCLASSES/classes"
+mkdir -p $TESTDIR
+$JAVAC -d $TESTDIR `find $TESTSRC/src/simptest -name "*.java"`
+
+# compile the plugin java sources and services file into a temp location.
+
+mkdir -p $TESTCLASSES/tmpdir/simp
+cp -r $TESTSRC/src/simp/META-INF $TESTCLASSES/tmpdir
+$JAVAC -d $TESTCLASSES/tmpdir `find $TESTSRC/src/simp -name "*.java"`
+
+# create modular jar file (inc. module-info.java) from the class files.
+mkdir -p $PLUGINDIR
+$JAR cf $PLUGINDIR/simp.jar -C $TESTCLASSES/tmpdir META-INF/services \
+    -C $TESTCLASSES/tmpdir module-info.class -C $TESTCLASSES/tmpdir simp
+
+OS=`uname -s`
+case "$OS" in
+  Windows_* | CYGWIN* )
+CPSEP=";"
+  ;;
+  * )
+CPSEP=":"
+  ;;
+esac
+
+# expect to find SimpReader via jar on classpath.
+# Will be treated as a regular jar.
+echo "Test classpath jar .. "
+$JAVA  -cp ${TESTDIR}${CPSEP}${PLUGINDIR}/simp.jar simptest.TestSIMPPlugin
+if [ $? -ne 0 ]; then
+    exception=1
+      echo "Classpath test failed: exception thrown!"
+fi
+echo "Test classpath jar with security manager .."
+$JAVA -Djava.security.manager -cp .${CPSEP}${TESTDIR}${CPSEP}${PLUGINDIR}/simp.jar simptest.TestSIMPPlugin
+if [ $? -ne 0 ]; then
+    exception=1
+    echo "Classpath + SecurityManager test failed: exception thrown!"
+fi
+
+# expect to find SimpReader on module path
+echo "Test modular jar .. "
+$JAVA -mp $PLUGINDIR -cp $TESTDIR simptest.TestSIMPPlugin
+
+if [ $? -ne 0 ]; then
+    exception=1
+    echo "modular jar test failed: exception thrown!"
+fi
+
+echo "Test modular jar with security manager .."
+$JAVA -Djava.security.manager -mp $PLUGINDIR -cp $TESTDIR simptest.TestSIMPPlugin
+if [ $? -ne 0 ]; then
+    exception=1
+    echo "modular jar with security manager test failed: exception thrown!"
+fi
+
+if [ $exception -ne 0 ]; then
+    echo "TEST FAILED"
+    exit 1
+fi
+exit 0
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/META-INF/services/javax.imageio.spi.ImageReaderSpi b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/META-INF/services/javax.imageio.spi.ImageReaderSpi
new file mode 100644
index 0000000..c0a0b0f
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/META-INF/services/javax.imageio.spi.ImageReaderSpi
@@ -0,0 +1 @@
+simp.SIMPImageReaderSpi
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReader.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReader.java
new file mode 100644
index 0000000..8118272
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReader.java
@@ -0,0 +1,145 @@
+/**
+ * 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 simp;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import javax.imageio.IIOException;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+  * A simple image format which has no compression and is a
+  * header with bytes 'SIMP', two signed bytes for width and height,
+  * and then unpadded 3 byte per pixel data representing RGB assumed
+  * to be in sRGB. The signed byte implies a maximum size of 127x127 pixels.
+  * Trailing data is ignored but there must be at least
+  * 3*width*height bytes of data following the simple 6 byte header.
+  */
+public class SIMPImageReader extends ImageReader {
+
+    private ImageInputStream stream = null;
+    private byte width = -1, height = -1;
+    SIMPMetadata metadata = null;
+    byte[] imageData = null;
+
+    public SIMPImageReader(ImageReaderSpi originatingProvider) {
+       super(originatingProvider);
+    }
+
+    public void setInput(Object input,
+                         boolean seekForwardOnly,
+                         boolean ignoreMetadata) {
+        super.setInput(input, seekForwardOnly, ignoreMetadata);
+        stream = (ImageInputStream) input;
+    }
+
+    private void checkState(int imageIndex) throws IOException {
+        if (stream == null) {
+            throw new IllegalStateException("input not set.");
+        }
+        if (imageIndex != 0) {
+            throw new IndexOutOfBoundsException("index != 0");
+        }
+        if (width==-1) {
+            byte[] sig = new byte[4];
+            stream.reset();
+            stream.read(sig);
+            boolean ok = sig[0]=='S' && sig[1]=='I' &&
+                         sig[2]=='M' && sig[3]=='P';
+            if (!ok) {
+                throw new IIOException("Not a SIMP image");
+            }
+            width = stream.readByte();
+            height = stream.readByte();
+        }
+        if (width <= 0 || height <= 0) {
+            throw new IOException("bad image size");
+        }
+        metadata = new SIMPMetadata(width, height);
+    }
+
+    public int getWidth(int imageIndex) throws IOException {
+        checkState(imageIndex);
+        return width;
+    }
+
+    public int getHeight(int imageIndex) throws IOException {
+        checkState(imageIndex);
+        return height;
+    }
+
+     public int getNumImages(boolean allowSearch) throws IOException {
+        checkState(0);
+        return 1;
+    }
+
+     public IIOMetadata getStreamMetadata() throws IOException {
+        return null;
+     }
+
+     public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
+        checkState(imageIndex);
+        return metadata;
+    }
+
+    public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
+        throws IOException {
+
+        checkState(imageIndex);
+        BufferedImage bi =
+            new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+        ArrayList<ImageTypeSpecifier> list = new ArrayList<>(1);
+        list.add(new ImageTypeSpecifier(bi));
+        return list.iterator();
+    }
+
+    public BufferedImage read(int imageIndex, ImageReadParam param)
+                            throws IOException {
+        checkState(imageIndex);
+        int len = 3*width*height;
+        byte[] imageData = new byte[len];
+        // The following is not efficient and is skipping all the
+        // progress updates, and ignoring the ImageReadParam, which
+        // it should not, but it is all we need for this test.
+        stream.readFully(imageData, 0, len);
+        BufferedImage bi =
+            new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        int off = 0;
+        for (int h=0;h<height;h++) {
+            int rgb = imageData[off]++ << 16 |
+                      imageData[off++] <<  8 | imageData[off++];
+            for (int w=0;w<width;w++) {
+                bi.setRGB(w, h, rgb);
+            }
+        }
+        return bi;
+    }
+}
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReaderSpi.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReaderSpi.java
new file mode 100644
index 0000000..b4523f6
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPImageReaderSpi.java
@@ -0,0 +1,86 @@
+/**
+ * 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 simp;
+
+import java.io.IOException;
+import java.util.Locale;
+import javax.imageio.IIOException;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+public class SIMPImageReaderSpi extends ImageReaderSpi {
+
+    private static final String[] FORMATNAMES = {"simp, SIMP"};
+    private static final String[] SUFFIXES = {"simp"};
+    private static final String[] MIMETYPES = {"image/simp"};
+
+    public SIMPImageReaderSpi() {
+        super("J Duke",                   // vendor
+              "1.0",                      // version
+               FORMATNAMES,               // format names
+               SUFFIXES,                  // file suffixes
+               MIMETYPES,                 // mimetypes
+               "simp.SIMPImageReader",    // reader class name
+               new Class<?>[] { ImageInputStream.class }, // input types
+               null,              // writer class names. TBD.
+               true,              // supports native metadata,
+               null,              // [no] native stream metadata format
+               null,              // [no] native stream metadata class
+               null,              // [no] native extra stream metadata format
+               null,              // [no] native extra stream metadata class
+               true,              // supports standard metadata,
+               "simp_metadata_1.0",       // metadata format name,
+               "simp.SIMPMetadataFormat", // metadata format class name
+               null,              // [no] extra image metadata format
+               null               // [no] extra image metadata format class
+         );
+         System.out.println("INIT SIMPImageReaderSpi");
+    }
+
+    public String getDescription(Locale locale) {
+        return "SIMPle Image Format Reader";
+    }
+
+    public boolean canDecodeInput(Object source) throws IOException {
+        if (!(source instanceof ImageInputStream)) {
+            return false;
+        }
+        ImageInputStream stream = (ImageInputStream)source;
+
+        stream.mark();
+        try {
+             byte[] sig = new byte[4];
+             stream.read(sig);
+             return sig[0]=='S' && sig[1]=='I' && sig[2]=='M' && sig[3]=='P';
+        } finally {
+            stream.reset();
+        }
+    }
+
+    public ImageReader createReaderInstance(Object extension)
+        throws IIOException {
+        return new SIMPImageReader(this);
+    }
+}
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadata.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadata.java
new file mode 100644
index 0000000..a69f944
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadata.java
@@ -0,0 +1,94 @@
+/**
+ * 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 simp;
+
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import org.w3c.dom.Node;
+
+public class SIMPMetadata extends IIOMetadata {
+
+   static final String nativeMetadataFormatName = "simp_metadata_1.0";
+
+   private int width, height;
+
+   public SIMPMetadata() {
+       super(true,
+             nativeMetadataFormatName, "simp.SIMPMetadataFormat", null, null);
+   }
+
+   public SIMPMetadata(int width, int height) {
+       this();
+       this.width = width;
+       this.height = height;
+   }
+
+   public boolean isReadOnly() {
+        return true;
+   }
+
+   public void setFromTree(String formatName, Node root) {
+    }
+
+    public void mergeTree(String formatName, Node root) {
+        throw new IllegalStateException("read only metadata");
+    }
+
+    public void reset() {
+        throw new IllegalStateException("read only metadata");
+    }
+
+    private IIOMetadataNode addChildNode(IIOMetadataNode root,
+                                         String name,
+                                         Object object) {
+        IIOMetadataNode child = new IIOMetadataNode(name);
+        if (object != null) {
+            child.setUserObject(object);
+            child.setNodeValue(object.toString());
+        }
+        root.appendChild(child);
+        return child;
+    }
+
+    private Node getNativeTree() {
+        IIOMetadataNode root =
+            new IIOMetadataNode(nativeMetadataFormatName);
+        addChildNode(root, "width", width);
+        addChildNode(root, "weight", height);
+        return root;
+    }
+
+    public Node getAsTree(String formatName) {
+        if (formatName.equals(nativeMetadataFormatName)) {
+            return getNativeTree();
+        } else if (formatName.equals
+                   (IIOMetadataFormatImpl.standardMetadataFormatName)) {
+            return getStandardTree();
+        } else {
+            throw new IllegalArgumentException("unsupported format");
+        }
+    }
+}
+
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadataFormat.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadataFormat.java
new file mode 100644
index 0000000..56e7e8b
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/SIMPMetadataFormat.java
@@ -0,0 +1,62 @@
+/**
+ * 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 simp;
+
+import java.util.Arrays;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadataFormat;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+
+public class SIMPMetadataFormat extends IIOMetadataFormatImpl {
+
+    private static IIOMetadataFormat instance = null;
+
+    public static synchronized IIOMetadataFormat getInstance() {
+        if (instance == null) {
+            instance = new SIMPMetadataFormat();
+        }
+        return instance;
+    }
+
+    public boolean canNodeAppear(String elementName,
+                                 ImageTypeSpecifier imageType) {
+        return true;
+    }
+
+    private SIMPMetadataFormat() {
+        super(SIMPMetadata.nativeMetadataFormatName,
+              CHILD_POLICY_SOME);
+
+        addElement("ImageDescriptor",
+                   SIMPMetadata.nativeMetadataFormatName,
+                   CHILD_POLICY_EMPTY);
+
+        addAttribute("ImageDescriptor", "width",
+                     DATATYPE_INTEGER, true, null,
+                     "1", "127", true, true);
+        addAttribute("ImageDescriptor", "height",
+                     DATATYPE_INTEGER, true, null,
+                     "1", "127", true, true);
+    }
+}
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/module-info.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/module-info.java
new file mode 100644
index 0000000..aac3c89
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simp/module-info.java
@@ -0,0 +1,28 @@
+/**
+ * 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 simp {
+    requires java.desktop;
+    exports simp to java.desktop;
+    provides javax.imageio.spi.ImageReaderSpi with simp.SIMPImageReaderSpi;
+}
diff --git a/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simptest/TestSIMPPlugin.java b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simptest/TestSIMPPlugin.java
new file mode 100644
index 0000000..a572bbb
--- /dev/null
+++ b/jdk/test/javax/imageio/plugins/external_plugin_tests/src/simptest/TestSIMPPlugin.java
@@ -0,0 +1,73 @@
+/**
+ * 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 simptest;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormat;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+
+public class TestSIMPPlugin {
+
+    static byte[] simpData = { (byte)'S', (byte)'I', (byte)'M', (byte)'P',
+                               1, 1, 0, 0, 0};
+
+    public static void main(String args[]) throws Exception {
+        Iterator<ImageReader> readers = ImageIO.getImageReadersBySuffix("simp");
+        ImageReader simpReader = null;
+        if (readers.hasNext()) {
+            simpReader = readers.next();
+            System.out.println("reader="+simpReader);
+        }
+        if (simpReader == null) {
+            throw new RuntimeException("Reader not found.");
+        }
+
+        ImageReaderSpi spi = simpReader.getOriginatingProvider();
+        IIOMetadataFormat spiFmt =
+            spi.getImageMetadataFormat("simp_metadata_1.0");
+        System.out.println("fmt from SPI=" + spiFmt);
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(simpData);
+        ImageInputStream iis = new MemoryCacheImageInputStream(bais);
+        simpReader.setInput(iis);
+        BufferedImage bi = simpReader.read(0);
+        System.out.println(bi);
+        IIOMetadata metadata = simpReader.getImageMetadata(0);
+        System.out.println("Image metadata="+metadata);
+        IIOMetadataFormat format =
+            metadata.getMetadataFormat("simp_metadata_1.0");
+        System.out.println("Image metadata format="+format);
+        if (format == null) {
+            throw new RuntimeException("MetadataFormat not found.");
+        }
+    }
+}
diff --git a/jdk/test/javax/imageio/stream/StreamCloserLeak/run_test.sh b/jdk/test/javax/imageio/stream/StreamCloserLeak/run_test.sh
index f725cd7..071550e 100644
--- a/jdk/test/javax/imageio/stream/StreamCloserLeak/run_test.sh
+++ b/jdk/test/javax/imageio/stream/StreamCloserLeak/run_test.sh
@@ -198,15 +198,15 @@
     fail "Unable to create temp directory."
 fi
 
-# Verify that all classoladers are destroyed
-${TESTJAVA}/bin/java ${TESTVMOPTS} -cp Test.jar test.Main
+# Verify that all classloaders are destroyed
+${TESTJAVA}/bin/java -XaddExports:java.desktop/sun.awt=ALL-UNNAMED ${TESTVMOPTS} -cp Test.jar test.Main
 if [ $? -ne 0 ] ; then
     fail "Test FAILED: some classloaders weren't destroyed."
 fi
 
 
 # Verify that ImageIO shutdown hook works correcly
-${TESTJAVA}/bin/java ${TESTVMOPTS} \
+${TESTJAVA}/bin/java -XaddExports:java.desktop/sun.awt=ALL-UNNAMED ${TESTVMOPTS} \
     -cp Test.jar -DforgetSomeStreams=true test.Main
 if [ $? -ne 0 ] ; then
     fail "Test FAILED: some classloaders weren't destroyed of shutdown hook failed."
diff --git a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java
index efcef23..0e375ae 100644
--- a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java
+++ b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java
@@ -37,8 +37,13 @@
 import java.lang.management.*;
 import java.lang.reflect.*;
 import java.net.*;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.*;
-import java.util.jar.*;
+import java.util.stream.Collectors;
 import javax.management.*;
 import javax.management.relation.*;
 import javax.management.remote.*;
@@ -83,9 +88,13 @@
         System.out.println("Checking platform MBeans...");
         checkPlatformMBeans();
 
-        URL codeBase = ClassLoader.getSystemResource("javax/management/MBeanServer.class");
-        if (codeBase == null) {
-            throw new Exception("Could not determine codeBase for " + MBeanServer.class);
+        URL codeBase;
+        String home = System.getProperty("java.home");
+        Path classFile = Paths.get(home, "modules", "java.management");
+        if (Files.isDirectory(classFile)) {
+            codeBase = classFile.toUri().toURL();
+        } else {
+            codeBase = URI.create("jrt:/java.management").toURL();
         }
 
         System.out.println();
@@ -214,14 +223,13 @@
         System.out.println();
     }
 
-    private static String[] findStandardMBeans(URL codeBase)
-            throws Exception {
+    private static String[] findStandardMBeans(URL codeBase) throws Exception {
         Set<String> names;
-        if (codeBase.getProtocol().equalsIgnoreCase("file")
-            && codeBase.toString().endsWith("/"))
+        if (codeBase.getProtocol().equalsIgnoreCase("jrt")) {
+            names = findStandardMBeansFromRuntime();
+        } else {
             names = findStandardMBeansFromDir(codeBase);
-        else
-            names = findStandardMBeansFromJar(codeBase);
+        }
 
         Set<String> standardMBeanNames = new TreeSet<String>();
         for (String name : names) {
@@ -234,21 +242,17 @@
         return standardMBeanNames.toArray(new String[0]);
     }
 
-    private static Set<String> findStandardMBeansFromJar(URL codeBase)
-            throws Exception {
-        InputStream is = codeBase.openStream();
-        JarInputStream jis = new JarInputStream(is);
-        Set<String> names = new TreeSet<String>();
-        JarEntry entry;
-        while ((entry = jis.getNextJarEntry()) != null) {
-            String name = entry.getName();
-            if (!name.endsWith(".class"))
-                continue;
-            name = name.substring(0, name.length() - 6);
-            name = name.replace('/', '.');
-            names.add(name);
-        }
-        return names;
+    private static Set<String> findStandardMBeansFromRuntime() throws Exception {
+        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        Path modules = fs.getPath("/modules");
+        return Files.walk(modules)
+                .filter(path -> path.toString().endsWith(".class"))
+                .map(path -> path.subpath(2, path.getNameCount()))
+                .map(Path::toString)
+                .map(s -> s.substring(0, s.length() - 6))  // drop .class
+                .filter(s -> !s.equals("module-info"))
+                .map(s -> s.replace('/', '.'))
+                .collect(Collectors.toSet());
     }
 
     private static Set<String> findStandardMBeansFromDir(URL codeBase)
diff --git a/jdk/test/javax/naming/module/basic.sh b/jdk/test/javax/naming/module/basic.sh
new file mode 100644
index 0000000..b48fefb
--- /dev/null
+++ b/jdk/test/javax/naming/module/basic.sh
@@ -0,0 +1,104 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @summary Test of JNDI factories using classes exported by third-party modules.
+
+# Demonstrates Java object storage/retrieval, LDAP control and URL context
+# usage using an LDAP directory. The objects and their associated object
+# factories, state factories, control factories and URL context factories
+# are exported from third-party modules.
+#
+# Seven types of object are used:
+#   - an AWT object (Serializable) from the 'java.desktop' JDK module
+#   - a Person object (DirContext) from the 'person' third-party module
+#   - a Fruit object (Referenceable) from the 'fruit' third-party module
+#   - an RMI object (Remote) from the 'hello' third-party module
+#   - an LDAP request control (Control) from the 'foo' third-party module
+#   - an LDAP response control (Control) from the 'authz' third-party module
+#   - an ldapv4 URL (DirContext) from the 'ldapv4' third-party 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"
+
+echo "\nPreparing the 'person' module..."
+mkdir -p mods/person
+$JAVAC -d mods/person `find $TESTSRC/src/person -name "*.java"`
+
+echo "\nPreparing the 'fruit' module..."
+mkdir -p mods/fruit
+$JAVAC -d mods/fruit `find $TESTSRC/src/fruit -name "*.java"`
+
+echo "\nPreparing the 'hello' module..."
+mkdir -p mods/hello
+$JAVAC -d mods/hello `find $TESTSRC/src/hello -name "*.java"`
+
+echo "\nPreparing the 'foo' module..."
+mkdir -p mods/foo
+$JAVAC -d mods/foo `find $TESTSRC/src/foo -name "*.java"`
+
+echo "\nPreparing the 'authz' module..."
+mkdir -p mods/authz
+$JAVAC -d mods/authz `find $TESTSRC/src/authz -name "*.java"`
+
+echo "\nPreparing the 'ldapv4' module..."
+mkdir -p mods/ldapv4
+$JAVAC -d mods/ldapv4 `find $TESTSRC/src/ldapv4 -name "*.java"`
+
+echo "\nPreparing the 'test' module..."
+mkdir -p mods/test
+$JAVAC -d mods -modulesourcepath $TESTSRC/src `find $TESTSRC/src/test -name "*.java"`
+
+
+echo "\nRunning with the 'java.desktop' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.StoreObject ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'person' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.StorePerson ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'fruit' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.StoreFruit ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'hello' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.StoreRemote ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'foo' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.ConnectWithFoo ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'authz' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.ConnectWithAuthzId ldap://localhost/dc=ie,dc=oracle,dc=com
+
+echo "\nRunning with the 'ldapv4' module..."
+$JAVA -Dtest.src=${TESTSRC} -mp mods -m test/test.ReadByUrl ldap://localhost/dc=ie,dc=oracle,dc=com
+
diff --git a/jdk/test/javax/naming/module/src/authz/module-info.java b/jdk/test/javax/naming/module/src/authz/module-info.java
new file mode 100644
index 0000000..982c5a9
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/authz/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 authz {
+    requires java.naming;
+    exports org.example.authz;
+}
+
diff --git a/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdRequestControl.java b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdRequestControl.java
new file mode 100644
index 0000000..cd0c518
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdRequestControl.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/**
+ * This class implements the LDAPv3 Authorization Identity request control
+ * as defined in
+ * <a href="http://tools.ietf.org/html/rfc3829">RFC 3829</a>.
+ */
+
+package org.example.authz;
+
+import javax.naming.ldap.*;
+
+public class AuthzIdRequestControl extends BasicControl {
+
+    public static final String OID = "2.16.840.1.113730.3.4.16";
+
+    public AuthzIdRequestControl() {
+        super(OID, true, null);
+    }
+
+    public AuthzIdRequestControl(boolean criticality) {
+        super(OID, criticality, null);
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControl.java b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControl.java
new file mode 100644
index 0000000..f38f916d
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * This class implements the LDAPv3 Authorization Identity response control
+ * as defined in
+ * <a href="http://tools.ietf.org/html/rfc3829">RFC 3829</a>.
+ */
+
+package org.example.authz;
+
+import java.io.*;
+import javax.naming.ldap.*;
+
+public class AuthzIdResponseControl extends BasicControl {
+
+    public static final String OID = "2.16.840.1.113730.3.4.15";
+
+    private String identity = null;
+
+    public AuthzIdResponseControl(String id, boolean criticality, byte[] value)
+        throws IOException {
+
+        super(id, criticality, value);
+
+        // decode value
+        if (value != null && value.length > 0) {
+            identity = new String(value, "UTF8");
+        }
+    }
+
+    public String getIdentity() {
+        return identity;
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControlFactory.java b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControlFactory.java
new file mode 100644
index 0000000..865355a
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/authz/org/example/authz/AuthzIdResponseControlFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * This class constructs LDAPv3 Authorization Identity response controls.
+ */
+
+package org.example.authz;
+
+import java.io.*;
+import javax.naming.*;
+import javax.naming.ldap.*;
+
+public class AuthzIdResponseControlFactory extends ControlFactory {
+
+    public AuthzIdResponseControlFactory() {
+    }
+
+    public Control getControlInstance(Control control) throws NamingException {
+        String id = control.getID();
+
+        try {
+            if (id.equals(AuthzIdResponseControl.OID)) {
+                return new AuthzIdResponseControl(id, control.isCritical(),
+                    control.getEncodedValue());
+            }
+        } catch (IOException e) {
+            NamingException ne = new NamingException();
+            ne.setRootCause(e);
+            throw ne;
+        }
+
+        return null;
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/foo/module-info.java b/jdk/test/javax/naming/module/src/foo/module-info.java
new file mode 100644
index 0000000..c83ae51
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/foo/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 foo {
+    requires java.naming;
+    exports org.example.foo;
+}
+
diff --git a/jdk/test/javax/naming/module/src/foo/org/example/foo/FooControl.java b/jdk/test/javax/naming/module/src/foo/org/example/foo/FooControl.java
new file mode 100644
index 0000000..ca59b7c
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/foo/org/example/foo/FooControl.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a dummy LDAP control.
+ */
+
+package org.example.foo;
+
+import javax.naming.ldap.*;
+
+public class FooControl extends BasicControl {
+
+    public FooControl() {
+        super("1.2.3.4.5.6.7.8.9", true, null);
+    }
+
+    public FooControl(boolean criticality) {
+        super("1.2.3.4.5.6.7.8.9", criticality, null);
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/fruit/module-info.java b/jdk/test/javax/naming/module/src/fruit/module-info.java
new file mode 100644
index 0000000..27af751
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/fruit/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 fruit {
+    requires java.naming;
+    exports org.example.fruit;
+}
+
diff --git a/jdk/test/javax/naming/module/src/fruit/org/example/fruit/Fruit.java b/jdk/test/javax/naming/module/src/fruit/org/example/fruit/Fruit.java
new file mode 100644
index 0000000..2e443d9
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/fruit/org/example/fruit/Fruit.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.example.fruit;
+
+import javax.naming.*;
+
+/**
+  * This class is used by the StoreFruit test.
+  * It is a referenceable class that can be stored by service
+  * providers like the LDAP and file system providers.
+  */
+public class Fruit implements Referenceable {
+    static String location = null;
+    String fruit;
+
+    public Fruit(String f) {
+        fruit = f;
+    }
+
+    public Reference getReference() throws NamingException {
+        return new Reference(
+            Fruit.class.getName(),
+            new StringRefAddr("fruit", fruit),
+            FruitFactory.class.getName(),
+            location);          // factory location
+    }
+
+    public String toString() {
+        return fruit;
+    }
+
+    public static void setLocation(String loc) {
+        location = loc;
+System.out.println("setting location to : " + location);
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/fruit/org/example/fruit/FruitFactory.java b/jdk/test/javax/naming/module/src/fruit/org/example/fruit/FruitFactory.java
new file mode 100644
index 0000000..aa81b1e
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/fruit/org/example/fruit/FruitFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.example.fruit;
+
+import java.util.Hashtable;
+import javax.naming.*;
+import javax.naming.spi.ObjectFactory;
+
+/**
+ * This is an object factory that when given a reference for a Fruit
+ * object, will create an instance of the corresponding Fruit.
+ */
+public class FruitFactory implements ObjectFactory {
+    public FruitFactory() {
+    }
+
+    public Object getObjectInstance(Object obj, Name name, Context ctx,
+        Hashtable env) throws Exception {
+        if (obj instanceof Reference) {
+            Reference ref = (Reference)obj;
+            if (ref.getClassName().equals(Fruit.class.getName())) {
+                RefAddr addr = ref.get("fruit");
+                if (addr != null) {
+                    return new Fruit((String)addr.getContent());
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/hello/module-info.java b/jdk/test/javax/naming/module/src/hello/module-info.java
new file mode 100644
index 0000000..a26ea5a
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/hello/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 hello {
+    requires java.rmi;
+    exports org.example.hello;
+}
+
diff --git a/jdk/test/javax/naming/module/src/hello/org/example/hello/Hello.java b/jdk/test/javax/naming/module/src/hello/org/example/hello/Hello.java
new file mode 100644
index 0000000..c357d64
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/hello/org/example/hello/Hello.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.example.hello;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+  * This interface is used by the StoreRemote test.
+  * It is a Remote interface. See HelloImpl.java for an implementation.
+  */
+
+public interface Hello extends Remote {
+    public String sayHello() throws RemoteException;
+}
diff --git a/jdk/test/javax/naming/module/src/hello/org/example/hello/HelloImpl.java b/jdk/test/javax/naming/module/src/hello/org/example/hello/HelloImpl.java
new file mode 100644
index 0000000..9130794
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/hello/org/example/hello/HelloImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.example.hello;
+
+import java.rmi.*;
+import java.rmi.server.UnicastRemoteObject;
+
+/**
+  * This class is used by the StoreRemote test.
+  * It is an implementation of the Hello interface.
+  */
+
+public class HelloImpl extends UnicastRemoteObject implements Hello {
+    public HelloImpl() throws RemoteException {
+    }
+
+    public String sayHello() throws RemoteException {
+        return ("Hello, the time is " + new java.util.Date());
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/ldapv4/module-info.java b/jdk/test/javax/naming/module/src/ldapv4/module-info.java
new file mode 100644
index 0000000..65cf6a2
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/ldapv4/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 ldapv4 {
+    requires java.naming;
+    exports org.example.ldapv4;
+}
+
diff --git a/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContext.java b/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContext.java
new file mode 100644
index 0000000..b6e5b71
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContext.java
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a dummy URL context for 'ldapv4://'.
+ */
+
+package org.example.ldapv4;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.spi.*;
+
+public class ldapv4URLContext implements DirContext {
+
+    private DirContext ctx;
+
+    public ldapv4URLContext(Hashtable env) throws NamingException {
+        ctx = new InitialDirContext(env);
+    }
+
+    public Object lookup(String name) throws NamingException {
+        try {
+            return ctx.lookup("");
+        } catch (Exception e) {
+            NamingException ne = new NamingException();
+            ne.setRootCause(e);
+            throw ne;
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public Object lookup(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void bind(String name, Object obj) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void bind(Name name, Object obj) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rebind(String name, Object obj) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rebind(Name name, Object obj) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void unbind(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void unbind(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rename(String oldName, String newName) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rename(Name name, Name newName) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<NameClassPair> list(String name)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<NameClassPair> list(Name name)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<Binding> listBindings(String name)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<Binding> listBindings(Name name)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void destroySubcontext(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void destroySubcontext(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Context createSubcontext(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Context createSubcontext(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Object lookupLink(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Object lookupLink(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NameParser getNameParser(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NameParser getNameParser(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public String composeName(String name, String prefix)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Name composeName(Name name, Name prefix) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public String getNameInNamespace() throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Object removeFromEnvironment(String propName)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Object addToEnvironment(String propName, Object propVal)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Hashtable getEnvironment() throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void close() throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Attributes getAttributes(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Attributes getAttributes(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Attributes getAttributes(Name name, String[] attrIds)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public Attributes getAttributes(String name, String[] attrIds)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void modifyAttributes(Name name, int mod_op, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void modifyAttributes(String name, int mod_op, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void modifyAttributes(Name name, ModificationItem[] mods)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void modifyAttributes(String name, ModificationItem[] mods)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void bind(Name name, Object obj, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void bind(String name, Object obj, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rebind(Name name, Object obj, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public void rebind(String name, Object obj, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext createSubcontext(Name name, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext createSubcontext(String name, Attributes attrs)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext getSchema(Name name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext getSchema(String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext getSchemaClassDefinition(Name name)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public DirContext getSchemaClassDefinition(String name)
+            throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(Name name,
+               Attributes matchingAttributes,
+               String[] attributesToReturn)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(String name,
+               Attributes matchingAttributes,
+               String[] attributesToReturn)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(Name name, Attributes matchingAttributes)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(String name, Attributes matchingAttributes)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(Name name,
+               String filter,
+               SearchControls cons)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(String name,
+               String filter,
+               SearchControls cons)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(Name name,
+               String filterExpr,
+               Object[] filterArgs,
+               SearchControls cons)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    public NamingEnumeration<SearchResult>
+        search(String name,
+               String filterExpr,
+               Object[] filterArgs,
+               SearchControls cons)
+        throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContextFactory.java b/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContextFactory.java
new file mode 100644
index 0000000..e731b77
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/ldapv4/org/example/ldapv4/ldapv4URLContextFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+/**
+ * This is a dumy URL context factory for 'ldapv4://'.
+ */
+
+package org.example.ldapv4;
+
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.spi.*;
+
+public class ldapv4URLContextFactory implements ObjectFactory {
+
+    public ldapv4URLContextFactory() {
+    }
+
+    public Object getObjectInstance(Object urlInfo, Name name, Context nameCtx,
+            Hashtable<?,?> env) throws Exception {
+
+        Hashtable<String,String> env2 = new Hashtable<>();
+        env2.put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+        String ldapUrl = (String)env.get(Context.PROVIDER_URL);
+        env2.put(Context.PROVIDER_URL, ldapUrl.replaceFirst("ldapv4", "ldap"));
+        //env2.put("com.sun.jndi.ldap.trace.ber", System.out);
+        return new ldapv4URLContext(env2);
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/person/module-info.java b/jdk/test/javax/naming/module/src/person/module-info.java
new file mode 100644
index 0000000..f7881b1
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/person/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 person {
+    requires java.naming;
+    exports org.example.person;
+}
+
diff --git a/jdk/test/javax/naming/module/src/person/org/example/person/Person.java b/jdk/test/javax/naming/module/src/person/org/example/person/Person.java
new file mode 100644
index 0000000..1d2427c
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/person/org/example/person/Person.java
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+/**
+ * This class has DirContext attributes and is used by the StorePerson test.
+ * Implementation of the inetOrgPerson LDAP object class as defined in
+ * <a href="http://www.ietf.org/internet-drafts/draft-smith-ldap-inetorgperson-03.txt">draft-smith-ldap-inetorgperson-03.txt</a>.
+ */
+
+package org.example.person;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+
+public class Person {
+
+    private BasicAttributes attrs;
+
+    public Person(String commonName, String surname) {
+
+        attrs = new BasicAttributes(true);
+        Attribute objectClass = new BasicAttribute("objectClass");
+        objectClass.add("top");
+        objectClass.add("person");
+        objectClass.add("inetOrgPerson");
+
+        attrs.put(objectClass);
+        attrs.put(new BasicAttribute("cn", commonName));
+        attrs.put(new BasicAttribute("sn", surname));
+    }
+
+    public Attributes getAttributes() {
+        return attrs;
+    }
+
+    public void setAudio(byte[] value) {
+        attrs.put(new BasicAttribute("audio", value));
+    }
+
+    public void setBusinessCategory(String value) {
+        attrs.put(new BasicAttribute("businessCategory", value));
+    }
+
+    public void setCarLicense(String value) {
+        attrs.put(new BasicAttribute("carLicense", value));
+    }
+
+    public void setDepartmentNumber(String value) {
+        attrs.put(new BasicAttribute("departmentNumber", value));
+    }
+
+    public void setDisplayName(String value) {
+        attrs.put(new BasicAttribute("displayName", value));
+    }
+
+    public void setEmployeeNumber(String value) {
+        attrs.put(new BasicAttribute("employeeNumber", value));
+    }
+
+    public void setEmployeeType(String value) {
+        attrs.put(new BasicAttribute("employeeType", value));
+    }
+
+    public void setGivenName(String value) {
+        attrs.put(new BasicAttribute("givenName", value));
+    }
+
+    public void setHomePhoneNumber(String value) {
+        attrs.put(new BasicAttribute("homePhone", value));
+    }
+
+    public void setHomePostalAddress(String value) {
+        attrs.put(new BasicAttribute("homePostalAddress", value));
+    }
+
+    public void setInitials(String value) {
+        attrs.put(new BasicAttribute("initials", value));
+    }
+
+    public void setJPEGPhoto(String value) {
+        attrs.put(new BasicAttribute("jpegPhoto", value));
+    }
+
+    public void setMailAddress(String value) {
+        attrs.put(new BasicAttribute("mail", value));
+    }
+
+    public void setManagerName(String value) {
+        attrs.put(new BasicAttribute("manager", value));
+    }
+
+    public void setMobileNumber(String value) {
+        attrs.put(new BasicAttribute("mobile", value));
+    }
+
+    public void setOrganizationName(String value) {
+        attrs.put(new BasicAttribute("o", value));
+    }
+
+    public void setPagerNumber(String value) {
+        attrs.put(new BasicAttribute("pager", value));
+    }
+
+    public void setPhoto(String value) {
+        attrs.put(new BasicAttribute("photo", value));
+    }
+
+    public void setRoomNumber(String value) {
+        attrs.put(new BasicAttribute("roomNumber", value));
+    }
+
+    public void setSecretaryName(String value) {
+        attrs.put(new BasicAttribute("secretary", value));
+    }
+
+    public void setUserID(String value) {
+        attrs.put(new BasicAttribute("uid", value));
+    }
+
+    public void setUserCertificate(String value) {
+        attrs.put(new BasicAttribute("userCertificate", value));
+    }
+
+    public void setX500UniqueID(String value) {
+        attrs.put(new BasicAttribute("x500UniqueIdentifier", value));
+    }
+
+    public void setPreferredLanguage(String value) {
+        attrs.put(new BasicAttribute("preferredLanguage", value));
+    }
+
+    public void setUserSMIMECertificate(String value) {
+        attrs.put(new BasicAttribute("userSMIMECertificate", value));
+    }
+
+    public void setUserPKCS12(String value) {
+        attrs.put(new BasicAttribute("userPKCS12", value));
+    }
+
+    /* ----- Attributes inherited from the Person LDAP object class ----- */
+
+    public void setDescription(String value) {
+        attrs.put(new BasicAttribute("description", value));
+    }
+
+    public void setDestinationIndicator(String value) {
+        attrs.put(new BasicAttribute("destinationIndicator", value));
+    }
+
+    public void setFaxNumber(String value) {
+        attrs.put(new BasicAttribute("facsimileTelephoneNumber", value));
+    }
+
+    public void setISDNNumber(String value) {
+        attrs.put(new BasicAttribute("internationalISDNNumber", value));
+    }
+
+    public void setLocalityName(String value) {
+        attrs.put(new BasicAttribute("localityName", value));
+    }
+
+    public void setOrganizationalUnitName(String value) {
+        attrs.put(new BasicAttribute("ou", value));
+    }
+
+    public void setPhysicalDeliveryOfficeName(String value) {
+        attrs.put(new BasicAttribute("physicalDeliveryOfficeName", value));
+    }
+
+    public void setPostalAddress(String value) {
+        attrs.put(new BasicAttribute("postalAddress", value));
+    }
+
+    public void setPostalCode(String value) {
+        attrs.put(new BasicAttribute("postalCode", value));
+    }
+
+    public void setPostOfficeBox(String value) {
+        attrs.put(new BasicAttribute("postOfficeBox", value));
+    }
+
+    public void setPreferredDeliveryMethod(String value) {
+        attrs.put(new BasicAttribute("preferredDeliveryMethod", value));
+    }
+
+    public void setRegisteredAddress(String value) {
+        attrs.put(new BasicAttribute("registeredAddress", value));
+    }
+
+    public void setSeeAlso(String value) {
+        attrs.put(new BasicAttribute("seeAlso", value));
+    }
+
+    public void setStateOrProvinceName(String value) {
+        attrs.put(new BasicAttribute("st", value));
+    }
+
+    public void setStreetAddress(String value) {
+        attrs.put(new BasicAttribute("street", value));
+    }
+
+    public void setTelephoneNumber(String value) {
+        attrs.put(new BasicAttribute("telephoneNumber", value));
+    }
+
+    public void setTeletexTerminalID(String value) {
+        attrs.put(new BasicAttribute("teletexTerminalIdentifier", value));
+    }
+
+    public void setTelexNumber(String value) {
+        attrs.put(new BasicAttribute("telexNumber", value));
+    }
+
+    public void setTitle(String value) {
+        attrs.put(new BasicAttribute("title", value));
+    }
+
+    public void setUserPassword(String value) {
+        attrs.put(new BasicAttribute("userPassword", value));
+    }
+
+    public void setX121Address(String value) {
+        attrs.put(new BasicAttribute("x121Address", value));
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/person/org/example/person/PersonFactory.java b/jdk/test/javax/naming/module/src/person/org/example/person/PersonFactory.java
new file mode 100644
index 0000000..5b1cf07
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/person/org/example/person/PersonFactory.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/*
+ * State factory and object factory for the Person class.
+ */
+
+package org.example.person;
+
+import java.util.Hashtable;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.spi.*;
+
+public class PersonFactory implements DirStateFactory, DirObjectFactory {
+
+    public PersonFactory() {
+    }
+
+    @Override
+    public Object getStateToBind(Object obj, Name name,
+        Context nameCtx, Hashtable environment) throws NamingException {
+
+        return null;
+    }
+
+    @Override
+    public DirStateFactory.Result getStateToBind(Object obj, Name name,
+        Context nameCtx, Hashtable environment, Attributes inAttrs)
+            throws NamingException {
+
+        if (obj instanceof Person) {
+            return new DirStateFactory.Result(null,
+                                              personToAttributes((Person)obj));
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public Object getObjectInstance(Object obj, Name name, Context ctx,
+        Hashtable environment) throws Exception {
+
+        return null;
+    }
+
+    @Override
+    public Object getObjectInstance(Object obj, Name name, Context ctx,
+        Hashtable environment, Attributes attributes) throws Exception {
+
+        if (obj instanceof DirContext) {
+            ((DirContext)obj).close(); // cleanup
+            return attributesToPerson(attributes);
+
+        } else {
+            return null;
+        }
+    }
+
+    private Attributes personToAttributes(Person person) {
+
+        // TBD: build attrs using methods in Person class instead of calling ...
+
+        return person.getAttributes();
+    }
+
+    private Person attributesToPerson(Attributes attrset)
+        throws NamingException {
+
+        Attributes attrs = (Attributes)attrset;
+        Person person = new Person((String)attrs.get("cn").get(),
+                                   (String)attrs.get("sn").get());
+
+        person.setMailAddress((String)attrs.get("mail").get());
+
+        // TBD: extract any other attributes
+
+        return person;
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/module-info.java b/jdk/test/javax/naming/module/src/test/module-info.java
new file mode 100644
index 0000000..c541a6a
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/module-info.java
@@ -0,0 +1,36 @@
+/*
+ * 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 test {
+    requires java.naming;
+    requires java.desktop;
+    requires java.xml.bind; // for javax.xml.bind.DatatypeConverter
+    requires java.rmi; // for java.rmi.server.UnicastRemoteObject
+    requires person;
+    requires fruit;
+    requires hello;
+    requires foo;
+    requires authz;
+    requires ldapv4;
+}
+
diff --git a/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.java b/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.java
new file mode 100644
index 0000000..27e8e49
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate JNDI using an LDAP request/response control.
+ * The Authorization Identity controls and their associated control factory
+ * is supplied by a third-party module.
+ */
+
+package test;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+import org.example.authz.AuthzIdRequestControl;
+import org.example.authz.AuthzIdResponseControl;
+
+public class ConnectWithAuthzId {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") +
+        "/src/test/test/ConnectWithAuthzId.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   ConnectWithAuthzId <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java ConnectWithAuthzId ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the ConnectWithAuthzId.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Connect to the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        env.put(Context.SECURITY_AUTHENTICATION, "simple");
+        env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=ie,dc=oracle,dc=com");
+        env.put(Context.SECURITY_CREDENTIALS, "changeit");
+        env.put(LdapContext.CONTROL_FACTORIES,
+            "org.example.authz.AuthzIdResponseControlFactory");
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        System.out.println("ConnectWithAuthzId: connecting to " + ldapUri);
+        LdapContext ctx = null;
+        Control[] connectionControls = { new AuthzIdRequestControl(false) };
+
+        try {
+            ctx = new InitialLdapContext(env, connectionControls);
+            System.out.println("ConnectWithAuthzId: connected");
+            // Retrieve the response controls
+            Control[] responseControls = ctx.getResponseControls();
+            if (responseControls != null) {
+                for (Control responseControl : responseControls) {
+                    System.out.println("ConnectWithAuthzId: received response" +
+                        " control: " + responseControl.getID());
+                    if (responseControl instanceof AuthzIdResponseControl) {
+                        AuthzIdResponseControl authzId =
+                            (AuthzIdResponseControl)responseControl;
+                        System.out.println("ConnectWithAuthzId: identity is  " +
+                            authzId.getIdentity());
+                    }
+                }
+            }
+        } catch (NamingException e) {
+            System.err.println("ConnectWithAuthzId: error connecting " + e);
+        } finally {
+            if (ctx != null) {
+                ctx.close();
+            }
+        }
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.ldap b/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.ldap
new file mode 100644
index 0000000..5e98ad6
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ConnectWithAuthzId.ldap
@@ -0,0 +1,96 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for ConnectWithAuthzId.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the ConnectWithAuthzId application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#       (Some manual BER encoding was needed to simulate the response control.)
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   81: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5   46:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10   31:     OCTET STRING 'cn=admin,dc=ie,dc=oracle,dc=com'
+#  43    8:     [0] 'changeit'
+#         :     }
+#  53   28:   [0] {
+#  55   26:     SEQUENCE {
+#  57   24:       OCTET STRING '2.16.840.1.113730.3.4.16'
+#         :       }
+#         :     }
+#         :   }
+0000: 30 51 02 01 01 60 2E 02   01 03 04 1F 63 6E 3D 61  0Q...`......cn=a
+0010: 64 6D 69 6E 2C 64 63 3D   69 65 2C 64 63 3D 6F 72  dmin,dc=ie,dc=or
+0020: 61 63 6C 65 2C 64 63 3D   63 6F 6D 80 08 63 68 61  acle,dc=com..cha
+0030: 6E 67 65 69 74 A0 1C 30   1A 04 18 32 2E 31 36 2E  ngeit..0...2.16.
+0040: 38 34 30 2E 31 2E 31 31   33 37 33 30 2E 33 2E 34  840.1.113730.3.4
+0050: 2E 31 36                                           .16
+
+# LDAP BindResponse:
+#
+#   0   51: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#  14   37:   [0] {
+#  16   35:     SEQUENCE {
+#  18   24:       OCTET STRING '2.16.840.1.113730.3.4.15'
+#  44    7:       OCTET STRING 'u:admin'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 33 02 01 01 61 07 0A   01 00 04 00 04 00 A0 25  0....a..........
+0010: 30 23 04 18 32 2E 31 36   2E 38 34 30 2E 31 2E 31  0...2.16.840.1.1
+0020: 31 33 37 33 30 2E 33 2E   34 2E 31 35 04 07 75 3A  13730.3.4.15..u:
+0030: 61 64 6D 69 6E                                     admin
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 02 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
diff --git a/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.java b/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.java
new file mode 100644
index 0000000..c14e4f4
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate JNDI using an LDAP connection control supplied by a third-party
+ * module.
+ */
+
+package test;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+import org.example.foo.FooControl;
+
+public class ConnectWithFoo {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/ConnectWithFoo.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   ConnectWithFoo <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java ConnectWithFoo ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the ConnectWithFoo.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Connect to the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        System.out.println("ConnectWithFoo: connecting to " + ldapUri);
+        LdapContext ctx = null;
+        Control[] connectionControls = { new FooControl(false) };
+
+        try {
+            ctx = new InitialLdapContext(env, connectionControls);
+            System.out.println("ConnectWithFoo: connected");
+        } catch (NamingException e) {
+            System.err.println("ConnectWithFoo: error connecting " + e);
+        } finally {
+            if (ctx != null) {
+                ctx.close();
+            }
+        }
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.ldap b/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.ldap
new file mode 100644
index 0000000..c73020b
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ConnectWithFoo.ldap
@@ -0,0 +1,84 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for ConnectWithFoo.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the ConnectWithFoo application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   35: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10    0:     OCTET STRING
+#  12    0:     [0]
+#         :     }
+#  14   21:   [0] {
+#  16   19:     SEQUENCE {
+#  18   17:       OCTET STRING '1.2.3.4.5.6.7.8.9'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 23 02 01 01 60 07 02   01 03 04 00 80 00 A0 15  0#...`..........
+0010: 30 13 04 11 31 2E 32 2E   33 2E 34 2E 35 2E 36 2E  0...1.2.3.4.5.6.
+0020: 37 2E 38 2E 39                                     7.8.9
+
+# LDAP BindResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 02 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
diff --git a/jdk/test/javax/naming/module/src/test/test/LDAPServer.java b/jdk/test/javax/naming/module/src/test/test/LDAPServer.java
new file mode 100644
index 0000000..01a31f0
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/LDAPServer.java
@@ -0,0 +1,250 @@
+/*
+ * 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 test;
+
+import java.io.*;
+import java.nio.file.*;
+import java.math.BigInteger;
+import java.net.*;
+import java.util.*;
+import java.util.regex.*;
+import javax.xml.bind.DatatypeConverter;
+
+/*
+ * A dummy LDAP server.
+ *
+ * Loads a sequence of LDAP messages from a capture file into its cache.
+ * It listens for LDAP requests, finds a match in its cache and sends the
+ * corresponding LDAP responses.
+ *
+ * The capture file contains an LDAP protocol exchange in the hexadecimal
+ * dump format emitted by sun.misc.HexDumpEncoder:
+ *
+ * xxxx: 00 11 22 33 44 55 66 77   88 99 aa bb cc dd ee ff  ................
+ *
+ * Typically, LDAP protocol exchange is generated by running the LDAP client
+ * application program against a real LDAP server and setting the JNDI/LDAP
+ * environment property: com.sun.jndi.ldap.trace.ber to activate LDAP message
+ * tracing.
+ */
+public class LDAPServer {
+
+    /*
+     * A cache of LDAP requests and responses.
+     * Messages with the same ID are stored in a list.
+     * The first element in the list is the LDAP request,
+     * the remaining elements are the LDAP responses.
+     */
+    private final Map<Integer,List<byte[]>> cache = new HashMap<>();
+
+    public LDAPServer(ServerSocket serverSocket, String filename)
+        throws Exception {
+
+        System.out.println("LDAPServer: Loading LDAP cache from: " + filename);
+        loadCaptureFile(filename);
+
+        System.out.println("LDAPServer: listening on port " +
+            serverSocket.getLocalPort());
+
+        try (Socket clientSocket = serverSocket.accept();
+            OutputStream out = clientSocket.getOutputStream();
+            InputStream in = clientSocket.getInputStream();) {
+
+            byte[] inBuffer = new byte[8192];
+            int count;
+
+            while ((count = in.read(inBuffer)) > 0) {
+                byte[] request = Arrays.copyOf(inBuffer, count);
+                int[] ids = getIDs(request);
+                int messageID = ids[0];
+                String operation = getOperation(ids[1]);
+                System.out.println("\nLDAPServer: received LDAP " + operation +
+                    "  [message ID " + messageID + "]");
+
+                List<byte[]> encodings = cache.get(messageID);
+                if (encodings == null ||
+                    (!Arrays.equals(request, encodings.get(0)))) {
+                    throw new Exception(
+                        "LDAPServer: ERROR: received an LDAP " + operation +
+                        " (ID=" + messageID + ") not present in cache");
+                }
+
+                for (int i = 1; i < encodings.size(); i++) {
+                    // skip the request (at index 0)
+                    byte[] response = encodings.get(i);
+                    out.write(response, 0, response.length);
+                    ids = getIDs(response);
+                    System.out.println("\nLDAPServer: Sent LDAP " +
+                        getOperation(ids[1]) + "  [message ID " + ids[0] + "]");
+                }
+            }
+        } catch (IOException e) {
+            System.out.println("LDAPServer: ERROR: " + e);
+            throw e;
+        }
+
+        System.out.println("\n[LDAP server exited normally]");
+    }
+
+    /*
+     * Load a capture file containing an LDAP protocol exchange in the
+     * hexadecimal dump format emitted by sun.misc.HexDumpEncoder:
+     *
+     * xxxx: 00 11 22 33 44 55 66 77   88 99 aa bb cc dd ee ff  ................
+     */
+    private void loadCaptureFile(String filename) throws IOException {
+        StringBuilder hexString = new StringBuilder();
+        String pattern = "(....): (..) (..) (..) (..) (..) (..) (..) (..)   (..) (..) (..) (..) (..) (..) (..) (..).*";
+
+        try (Scanner fileScanner =  new Scanner(Paths.get(filename))) {
+            while (fileScanner.hasNextLine()){
+
+                try (Scanner lineScanner =
+                    new Scanner(fileScanner.nextLine())) {
+                    if (lineScanner.findInLine(pattern) == null) {
+                        continue;
+                    }
+                    MatchResult result = lineScanner.match();
+                    for (int i = 1; i <= result.groupCount(); i++) {
+                        String digits = result.group(i);
+                        if (digits.length() == 4) {
+                            if (digits.equals("0000")) { // start-of-message
+                                if (hexString.length() > 0) {
+                                    addToCache(hexString.toString());
+                                    hexString = new StringBuilder();
+                                }
+                            }
+                            continue;
+                        } else if (digits.equals("  ")) { // short message
+                            continue;
+                        }
+                        hexString.append(digits);
+                    }
+                }
+            }
+        }
+        addToCache(hexString.toString());
+    }
+
+    /*
+     * Add an LDAP encoding to the cache (by messageID key).
+     */
+    private void addToCache(String hexString) throws IOException {
+        byte[] encoding = DatatypeConverter.parseHexBinary(hexString);
+        int[] ids = getIDs(encoding);
+        int messageID = ids[0];
+        List<byte[]> encodings = cache.get(messageID);
+        if (encodings == null) {
+            encodings = new ArrayList<>();
+        }
+        System.out.println("    adding LDAP " + getOperation(ids[1]) +
+            " with message ID " + messageID + " to the cache");
+        encodings.add(encoding);
+        cache.put(messageID, encodings);
+    }
+
+    /*
+     * Extracts the message ID and operation ID from an LDAP protocol encoding
+     * and returns them in a 2-element array of integers.
+     */
+    private static int[] getIDs(byte[] encoding) throws IOException {
+        if (encoding[0] != 0x30) {
+            throw new IOException("Error: bad LDAP encoding in capture file: " +
+                "expected ASN.1 SEQUENCE tag (0x30), encountered " +
+                encoding[0]);
+        }
+
+        int index = 2;
+        if ((encoding[1] & 0x80) == 0x80) {
+            index += (encoding[1] & 0x0F);
+        }
+
+        if (encoding[index] != 0x02) {
+            throw new IOException("Error: bad LDAP encoding in capture file: " +
+                "expected ASN.1 INTEGER tag (0x02), encountered " +
+                encoding[index]);
+        }
+        int length = encoding[index + 1];
+        index += 2;
+        int messageID =
+            new BigInteger(1,
+                Arrays.copyOfRange(encoding, index, index + length)).intValue();
+        index += length;
+        int operationID = encoding[index];
+
+        return new int[]{messageID, operationID};
+    }
+
+    /*
+     * Maps an LDAP operation ID to a string description
+     */
+    private static String getOperation(int operationID) {
+        switch (operationID) {
+        case 0x60:
+            return "BindRequest";       // [APPLICATION 0]
+        case 0x61:
+            return "BindResponse";      // [APPLICATION 1]
+        case 0x42:
+            return "UnbindRequest";     // [APPLICATION 2]
+        case 0x63:
+            return "SearchRequest";     // [APPLICATION 3]
+        case 0x64:
+            return "SearchResultEntry"; // [APPLICATION 4]
+        case 0x65:
+            return "SearchResultDone";  // [APPLICATION 5]
+        case 0x66:
+            return "ModifyRequest";     // [APPLICATION 6]
+        case 0x67:
+            return "ModifyResponse";    // [APPLICATION 7]
+        case 0x68:
+            return "AddRequest";        // [APPLICATION 8]
+        case 0x69:
+            return "AddResponse";       // [APPLICATION 9]
+        case 0x4A:
+            return "DeleteRequest";     // [APPLICATION 10]
+        case 0x6B:
+            return "DeleteResponse";    // [APPLICATION 11]
+        case 0x6C:
+            return "ModifyDNRequest";   // [APPLICATION 12]
+        case 0x6D:
+            return "ModifyDNResponse";  // [APPLICATION 13]
+        case 0x6E:
+            return "CompareRequest";    // [APPLICATION 14]
+        case 0x6F:
+            return "CompareResponse";   // [APPLICATION 15]
+        case 0x50:
+            return "AbandonRequest";    // [APPLICATION 16]
+        case 0x73:
+            return "SearchResultReference";  // [APPLICATION 19]
+        case 0x77:
+            return "ExtendedRequest";   // [APPLICATION 23]
+        case 0x78:
+            return "ExtendedResponse";  // [APPLICATION 24]
+        case 0x79:
+            return "IntermediateResponse";  // [APPLICATION 25]
+        default:
+            return "Unknown";
+        }
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/ReadByUrl.java b/jdk/test/javax/naming/module/src/test/test/ReadByUrl.java
new file mode 100644
index 0000000..4b68da4
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ReadByUrl.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate JNDI using the 'ldapv4' URL scheme supplied by a third-party
+ * module.
+ */
+
+package test;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+public class ReadByUrl {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/ReadByUrl.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   ReadByUrl <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java ReadByUrl ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the ReadByUrl.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Connect to the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI("ldapv4", null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        // URL context factory location for 'ldapv4://'
+        env.put(Context.URL_PKG_PREFIXES, "org.example");
+
+        System.out.println("ReadByUrl: connecting to " + ldapUri);
+        DirContext ctx = null;
+
+        try {
+            ctx = new InitialDirContext(env);
+            System.out.println("ReadByUrl: connected");
+            DirContext entry = (DirContext) ctx.lookup(ldapUri.toString());
+            entry.close();
+        } catch (NamingException e) {
+            System.err.println("ReadByUrl: error connecting " + e);
+        } finally {
+            if (ctx != null) {
+                ctx.close();
+            }
+        }
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/ReadByUrl.ldap b/jdk/test/javax/naming/module/src/test/test/ReadByUrl.ldap
new file mode 100644
index 0000000..ec9f090
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/ReadByUrl.ldap
@@ -0,0 +1,158 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for ReadByUrl.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the ReadByUrl application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10    0:     OCTET STRING
+#  12    0:     [0]
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 60 07 02   01 03 04 00 80 00        0....`........
+
+# LDAP BindResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP SearchRequest:
+#
+#   0   88: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5   54:   [APPLICATION 3] {
+#   7   22:     OCTET STRING 'dc=ie,dc=oracle,dc=com'
+#  31    1:     ENUMERATED 0
+#  34    1:     ENUMERATED 3
+#  37    1:     INTEGER 0
+#  40    1:     INTEGER 0
+#  43    1:     BOOLEAN FALSE
+#  46   11:     [7] 'objectClass'
+#  59    0:     SEQUENCE {}
+#         :     }
+#  61   27:   [0] {
+#  63   25:     SEQUENCE {
+#  65   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+0000: 30 58 02 01 02 63 36 04   16 64 63 3D 69 65 2C 64  0X...c6..dc=ie,d
+0010: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 0A  c=oracle,dc=com.
+0020: 01 00 0A 01 03 02 01 00   02 01 00 01 01 00 87 0B  ................
+0030: 6F 62 6A 65 63 74 43 6C   61 73 73 30 00 A0 1B 30  objectClass0...0
+0040: 19 04 17 32 2E 31 36 2E   38 34 30 2E 31 2E 31 31  ...2.16.840.1.11
+0050: 33 37 33 30 2E 33 2E 34   2E 32                    3730.3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0  111: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5  106:   [APPLICATION 4] {
+#   7   22:     OCTET STRING 'dc=ie,dc=oracle,dc=com'
+#  31   80:     SEQUENCE {
+#  33   44:       SEQUENCE {
+#  35   11:         OCTET STRING 'objectClass'
+#  48   29:         SET {
+#  50    3:           OCTET STRING 'top'
+#  55    8:           OCTET STRING 'dcObject'
+#  65   12:           OCTET STRING 'organization'
+#         :           }
+#         :         }
+#  79   20:       SEQUENCE {
+#  81    1:         OCTET STRING 6F
+#  84   15:         SET {
+#  86   13:           OCTET STRING 'ie.oracle.com'
+#         :           }
+#         :         }
+# 101   10:       SEQUENCE {
+# 103    2:         OCTET STRING 64 63
+# 107    4:         SET {
+# 109    2:           OCTET STRING 69 65
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 6F 02 01 02 64 6A 04   16 64 63 3D 69 65 2C 64  0o...dj..dc=ie,d
+0010: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0020: 50 30 2C 04 0B 6F 62 6A   65 63 74 43 6C 61 73 73  P0,..objectClass
+0030: 31 1D 04 03 74 6F 70 04   08 64 63 4F 62 6A 65 63  1...top..dcObjec
+0040: 74 04 0C 6F 72 67 61 6E   69 7A 61 74 69 6F 6E 30  t..organization0
+0050: 14 04 01 6F 31 0F 04 0D   69 65 2E 6F 72 61 63 6C  ...o1...ie.oracl
+0060: 65 2E 63 6F 6D 30 0A 04   02 64 63 31 04 04 02 69  e.com0...dc1...i
+0070: 65                                                 e
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 02 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 3
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 03 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
+
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreFruit.java b/jdk/test/javax/naming/module/src/test/test/StoreFruit.java
new file mode 100644
index 0000000..278102c
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreFruit.java
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate Java object storage and retrieval using an LDAP directory.
+ * The Fruit object and its associated object factory is supplied by a
+ * third-party module. The Fruit object implements javax.naming.Referenceable.
+ */
+
+package test;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+import org.example.fruit.Fruit;
+
+public class StoreFruit {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/StoreFruit.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   StoreFruit <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java StoreFruit ldap://oasis/o=airius.com");
+    return;
+        }
+
+        /*
+         * Launch the LDAP server with the StoreFruit.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Store fruit objects in the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+    "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        System.out.println("StoreFruit: connecting to " + ldapUri);
+        DirContext ctx = new InitialDirContext(env);
+        Fruit fruit = null;
+        String dn = "cn=myfruit";
+        String dn2 = "cn=myapple";
+
+        try {
+            fruit = new Fruit("orange");
+            ctx.bind(dn, fruit);
+            System.out.println("StoreFruit: created entry '" + dn + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StoreFruit: entry '" + dn +
+                "' already exists");
+            cleanup(ctx, (String)null);
+            return;
+        }
+
+        try {
+            ctx.bind(dn2, new Fruit("apple"));
+            System.out.println("StoreFruit: created entry '" + dn2 + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StoreFruit: entry '" + dn2 +
+                "' already exists");
+            cleanup(ctx, dn);
+            return;
+        }
+
+        /*
+         * Retrieve fruit objects from the LDAP directory
+         */
+
+        try {
+            Fruit fruit2 = (Fruit) ctx.lookup(dn);
+            System.out.println("StoreFruit: retrieved object: " + fruit2);
+        } catch (NamingException e) {
+            System.err.println("StoreFruit: error retrieving entry '" +
+                dn + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        try {
+            Fruit fruit3 = (Fruit) ctx.lookup(dn2);
+            System.out.println("StoreFruit: retrieved object: " + fruit3);
+        } catch (NamingException e) {
+            System.err.println("StoreFruit: error retrieving entry '" +
+                dn2 + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        cleanup(ctx, dn, dn2);
+    }
+
+    /*
+     * Remove objects from the LDAP directory
+     */
+    private static void cleanup(DirContext ctx, String... dns)
+        throws NamingException {
+
+        for (String dn : dns) {
+            try {
+                ctx.destroySubcontext(dn);
+                System.out.println("StoreFruit: removed entry '" + dn + "'");
+            } catch (NamingException e) {
+                System.err.println("StoreFruit: error removing entry '" + dn +
+                    "' " + e);
+            }
+        }
+        ctx.close();
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreFruit.ldap b/jdk/test/javax/naming/module/src/test/test/StoreFruit.ldap
new file mode 100644
index 0000000..4ab6306
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreFruit.ldap
@@ -0,0 +1,512 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for StoreFruit.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the StoreFruit application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10    0:     OCTET STRING
+#  12    0:     [0]
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 60 07 02   01 03 04 00 80 00        0....`........
+
+# LDAP BindResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP AddRequest:
+#
+#   0  297: SEQUENCE {
+#   4    1:   INTEGER 2
+#   7  261:   [APPLICATION 8] {
+#  11   33:     OCTET STRING 'cn=myfruit,dc=ie,dc=oracle,dc=com'
+#  46  223:     SEQUENCE {
+#  49   68:       SEQUENCE {
+#  51   11:         OCTET STRING 'objectClass'
+#  64   53:         SET {
+#  66    3:           OCTET STRING 'top'
+#  71   13:           OCTET STRING 'javaContainer'
+#  86   10:           OCTET STRING 'javaObject'
+#  98   19:           OCTET STRING 'javaNamingReference'
+#         :           }
+#         :         }
+# 119   41:       SEQUENCE {
+# 121   20:         OCTET STRING 'javaReferenceAddress'
+# 143   17:         SET {
+# 145   15:           OCTET STRING '#0#fruit#orange'
+#         :           }
+#         :         }
+# 162   47:       SEQUENCE {
+# 164   11:         OCTET STRING 'javaFactory'
+# 177   32:         SET {
+# 179   30:           OCTET STRING 'org.example.fruit.FruitFactory'
+#         :           }
+#         :         }
+# 211   42:       SEQUENCE {
+# 213   13:         OCTET STRING 'javaClassName'
+# 228   25:         SET {
+# 230   23:           OCTET STRING 'org.example.fruit.Fruit'
+#         :           }
+#         :         }
+# 255   15:       SEQUENCE {
+# 257    2:         OCTET STRING 63 6E
+# 261    9:         SET {
+# 263    7:           OCTET STRING 'myfruit'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+# 272   27:   [0] {
+# 274   25:     SEQUENCE {
+# 276   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 01 29 02 01 02 68   82 01 05 04 21 63 6E 3D  0..)...h....!cn=
+0010: 6D 79 66 72 75 69 74 2C   64 63 3D 69 65 2C 64 63  myfruit,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 81  =oracle,dc=com0.
+0030: DF 30 44 04 0B 6F 62 6A   65 63 74 43 6C 61 73 73  .0D..objectClass
+0040: 31 35 04 03 74 6F 70 04   0D 6A 61 76 61 43 6F 6E  15..top..javaCon
+0050: 74 61 69 6E 65 72 04 0A   6A 61 76 61 4F 62 6A 65  tainer..javaObje
+0060: 63 74 04 13 6A 61 76 61   4E 61 6D 69 6E 67 52 65  ct..javaNamingRe
+0070: 66 65 72 65 6E 63 65 30   29 04 14 6A 61 76 61 52  ference0)..javaR
+0080: 65 66 65 72 65 6E 63 65   41 64 64 72 65 73 73 31  eferenceAddress1
+0090: 11 04 0F 23 30 23 66 72   75 69 74 23 6F 72 61 6E  ...#0#fruit#oran
+00A0: 67 65 30 2F 04 0B 6A 61   76 61 46 61 63 74 6F 72  ge0/..javaFactor
+00B0: 79 31 20 04 1E 6F 72 67   2E 65 78 61 6D 70 6C 65  y1 ..org.example
+00C0: 2E 66 72 75 69 74 2E 46   72 75 69 74 46 61 63 74  .fruit.FruitFact
+00D0: 6F 72 79 30 2A 04 0D 6A   61 76 61 43 6C 61 73 73  ory0*..javaClass
+00E0: 4E 61 6D 65 31 19 04 17   6F 72 67 2E 65 78 61 6D  Name1...org.exam
+00F0: 70 6C 65 2E 66 72 75 69   74 2E 46 72 75 69 74 30  ple.fruit.Fruit0
+0100: 0F 04 02 63 6E 31 09 04   07 6D 79 66 72 75 69 74  ...cn1...myfruit
+0110: A0 1B 30 19 04 17 32 2E   31 36 2E 38 34 30 2E 31  ..0...2.16.840.1
+0120: 2E 31 31 33 37 33 30 2E   33 2E 34 2E 32           .113730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    7:   [APPLICATION 9] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 02 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP AddRequest:
+#
+#   0  296: SEQUENCE {
+#   4    1:   INTEGER 3
+#   7  260:   [APPLICATION 8] {
+#  11   33:     OCTET STRING 'cn=myapple,dc=ie,dc=oracle,dc=com'
+#  46  222:     SEQUENCE {
+#  49   68:       SEQUENCE {
+#  51   11:         OCTET STRING 'objectClass'
+#  64   53:         SET {
+#  66    3:           OCTET STRING 'top'
+#  71   13:           OCTET STRING 'javaContainer'
+#  86   10:           OCTET STRING 'javaObject'
+#  98   19:           OCTET STRING 'javaNamingReference'
+#         :           }
+#         :         }
+# 119   40:       SEQUENCE {
+# 121   20:         OCTET STRING 'javaReferenceAddress'
+# 143   16:         SET {
+# 145   14:           OCTET STRING '#0#fruit#apple'
+#         :           }
+#         :         }
+# 161   47:       SEQUENCE {
+# 163   11:         OCTET STRING 'javaFactory'
+# 176   32:         SET {
+# 178   30:           OCTET STRING 'org.example.fruit.FruitFactory'
+#         :           }
+#         :         }
+# 210   42:       SEQUENCE {
+# 212   13:         OCTET STRING 'javaClassName'
+# 227   25:         SET {
+# 229   23:           OCTET STRING 'org.example.fruit.Fruit'
+#         :           }
+#         :         }
+# 254   15:       SEQUENCE {
+# 256    2:         OCTET STRING 63 6E
+# 260    9:         SET {
+# 262    7:           OCTET STRING 'myapple'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+# 271   27:   [0] {
+# 273   25:     SEQUENCE {
+# 275   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 01 28 02 01 03 68   82 01 04 04 21 63 6E 3D  0..(...h....!cn=
+0010: 6D 79 61 70 70 6C 65 2C   64 63 3D 69 65 2C 64 63  myapple,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 81  =oracle,dc=com0.
+0030: DE 30 44 04 0B 6F 62 6A   65 63 74 43 6C 61 73 73  .0D..objectClass
+0040: 31 35 04 03 74 6F 70 04   0D 6A 61 76 61 43 6F 6E  15..top..javaCon
+0050: 74 61 69 6E 65 72 04 0A   6A 61 76 61 4F 62 6A 65  tainer..javaObje
+0060: 63 74 04 13 6A 61 76 61   4E 61 6D 69 6E 67 52 65  ct..javaNamingRe
+0070: 66 65 72 65 6E 63 65 30   28 04 14 6A 61 76 61 52  ference0(..javaR
+0080: 65 66 65 72 65 6E 63 65   41 64 64 72 65 73 73 31  eferenceAddress1
+0090: 10 04 0E 23 30 23 66 72   75 69 74 23 61 70 70 6C  ...#0#fruit#appl
+00A0: 65 30 2F 04 0B 6A 61 76   61 46 61 63 74 6F 72 79  e0/..javaFactory
+00B0: 31 20 04 1E 6F 72 67 2E   65 78 61 6D 70 6C 65 2E  1 ..org.example.
+00C0: 66 72 75 69 74 2E 46 72   75 69 74 46 61 63 74 6F  fruit.FruitFacto
+00D0: 72 79 30 2A 04 0D 6A 61   76 61 43 6C 61 73 73 4E  ry0*..javaClassN
+00E0: 61 6D 65 31 19 04 17 6F   72 67 2E 65 78 61 6D 70  ame1...org.examp
+00F0: 6C 65 2E 66 72 75 69 74   2E 46 72 75 69 74 30 0F  le.fruit.Fruit0.
+0100: 04 02 63 6E 31 09 04 07   6D 79 61 70 70 6C 65 A0  ..cn1...myapple.
+0110: 1B 30 19 04 17 32 2E 31   36 2E 38 34 30 2E 31 2E  .0...2.16.840.1.
+0120: 31 31 33 37 33 30 2E 33   2E 34 2E 32              113730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 3
+#   5    7:   [APPLICATION 9] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 03 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP SearchRequest:
+#
+#   0   99: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5   65:   [APPLICATION 3] {
+#   7   33:     OCTET STRING 'cn=myfruit,dc=ie,dc=oracle,dc=com'
+#  42    1:     ENUMERATED 0
+#  45    1:     ENUMERATED 3
+#  48    1:     INTEGER 0
+#  51    1:     INTEGER 0
+#  54    1:     BOOLEAN FALSE
+#  57   11:     [7] 'objectClass'
+#  70    0:     SEQUENCE {}
+#         :     }
+#  72   27:   [0] {
+#  74   25:     SEQUENCE {
+#  76   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 63 02 01 04 63 41 04   21 63 6E 3D 6D 79 66 72  0c...cA.!cn=myfr
+0010: 75 69 74 2C 64 63 3D 69   65 2C 64 63 3D 6F 72 61  uit,dc=ie,dc=ora
+0020: 63 6C 65 2C 64 63 3D 63   6F 6D 0A 01 00 0A 01 03  cle,dc=com......
+0030: 02 01 00 02 01 00 01 01   00 87 0B 6F 62 6A 65 63  ...........objec
+0040: 74 43 6C 61 73 73 30 00   A0 1B 30 19 04 17 32 2E  tClass0...0...2.
+0050: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0060: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0  268: SEQUENCE {
+#   4    1:   INTEGER 4
+#   7  261:   [APPLICATION 4] {
+#  11   33:     OCTET STRING 'cn=myfruit,dc=ie,dc=oracle,dc=com'
+#  46  223:     SEQUENCE {
+#  49   68:       SEQUENCE {
+#  51   11:         OCTET STRING 'objectClass'
+#  64   53:         SET {
+#  66    3:           OCTET STRING 'top'
+#  71   13:           OCTET STRING 'javaContainer'
+#  86   10:           OCTET STRING 'javaObject'
+#  98   19:           OCTET STRING 'javaNamingReference'
+#         :           }
+#         :         }
+# 119   41:       SEQUENCE {
+# 121   20:         OCTET STRING 'javaReferenceAddress'
+# 143   17:         SET {
+# 145   15:           OCTET STRING '#0#fruit#orange'
+#         :           }
+#         :         }
+# 162   47:       SEQUENCE {
+# 164   11:         OCTET STRING 'javaFactory'
+# 177   32:         SET {
+# 179   30:           OCTET STRING 'org.example.fruit.FruitFactory'
+#         :           }
+#         :         }
+# 211   42:       SEQUENCE {
+# 213   13:         OCTET STRING 'javaClassName'
+# 228   25:         SET {
+# 230   23:           OCTET STRING 'org.example.fruit.Fruit'
+#         :           }
+#         :         }
+# 255   15:       SEQUENCE {
+# 257    2:         OCTET STRING 63 6E
+# 261    9:         SET {
+# 263    7:           OCTET STRING 'myfruit'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 01 0C 02 01 04 64   82 01 05 04 21 63 6E 3D  0......d....!cn=
+0010: 6D 79 66 72 75 69 74 2C   64 63 3D 69 65 2C 64 63  myfruit,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 81  =oracle,dc=com0.
+0030: DF 30 44 04 0B 6F 62 6A   65 63 74 43 6C 61 73 73  .0D..objectClass
+0040: 31 35 04 03 74 6F 70 04   0D 6A 61 76 61 43 6F 6E  15..top..javaCon
+0050: 74 61 69 6E 65 72 04 0A   6A 61 76 61 4F 62 6A 65  tainer..javaObje
+0060: 63 74 04 13 6A 61 76 61   4E 61 6D 69 6E 67 52 65  ct..javaNamingRe
+0070: 66 65 72 65 6E 63 65 30   29 04 14 6A 61 76 61 52  ference0)..javaR
+0080: 65 66 65 72 65 6E 63 65   41 64 64 72 65 73 73 31  eferenceAddress1
+0090: 11 04 0F 23 30 23 66 72   75 69 74 23 6F 72 61 6E  ...#0#fruit#oran
+00A0: 67 65 30 2F 04 0B 6A 61   76 61 46 61 63 74 6F 72  ge0/..javaFactor
+00B0: 79 31 20 04 1E 6F 72 67   2E 65 78 61 6D 70 6C 65  y1 ..org.example
+00C0: 2E 66 72 75 69 74 2E 46   72 75 69 74 46 61 63 74  .fruit.FruitFact
+00D0: 6F 72 79 30 2A 04 0D 6A   61 76 61 43 6C 61 73 73  ory0*..javaClass
+00E0: 4E 61 6D 65 31 19 04 17   6F 72 67 2E 65 78 61 6D  Name1...org.exam
+00F0: 70 6C 65 2E 66 72 75 69   74 2E 46 72 75 69 74 30  ple.fruit.Fruit0
+0100: 0F 04 02 63 6E 31 09 04   07 6D 79 66 72 75 69 74  ...cn1...myfruit
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 04 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP SearchRequest:
+#
+#   0   99: SEQUENCE {
+#   2    1:   INTEGER 5
+#   5   65:   [APPLICATION 3] {
+#   7   33:     OCTET STRING 'cn=myapple,dc=ie,dc=oracle,dc=com'
+#  42    1:     ENUMERATED 0
+#  45    1:     ENUMERATED 3
+#  48    1:     INTEGER 0
+#  51    1:     INTEGER 0
+#  54    1:     BOOLEAN FALSE
+#  57   11:     [7] 'objectClass'
+#  70    0:     SEQUENCE {}
+#         :     }
+#  72   27:   [0] {
+#  74   25:     SEQUENCE {
+#  76   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 63 02 01 05 63 41 04   21 63 6E 3D 6D 79 61 70  0c...cA.!cn=myap
+0010: 70 6C 65 2C 64 63 3D 69   65 2C 64 63 3D 6F 72 61  ple,dc=ie,dc=ora
+0020: 63 6C 65 2C 64 63 3D 63   6F 6D 0A 01 00 0A 01 03  cle,dc=com......
+0030: 02 01 00 02 01 00 01 01   00 87 0B 6F 62 6A 65 63  ...........objec
+0040: 74 43 6C 61 73 73 30 00   A0 1B 30 19 04 17 32 2E  tClass0...0...2.
+0050: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0060: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0  267: SEQUENCE {
+#   4    1:   INTEGER 5
+#   7  260:   [APPLICATION 4] {
+#  11   33:     OCTET STRING 'cn=myapple,dc=ie,dc=oracle,dc=com'
+#  46  222:     SEQUENCE {
+#  49   68:       SEQUENCE {
+#  51   11:         OCTET STRING 'objectClass'
+#  64   53:         SET {
+#  66    3:           OCTET STRING 'top'
+#  71   13:           OCTET STRING 'javaContainer'
+#  86   10:           OCTET STRING 'javaObject'
+#  98   19:           OCTET STRING 'javaNamingReference'
+#         :           }
+#         :         }
+# 119   40:       SEQUENCE {
+# 121   20:         OCTET STRING 'javaReferenceAddress'
+# 143   16:         SET {
+# 145   14:           OCTET STRING '#0#fruit#apple'
+#         :           }
+#         :         }
+# 161   47:       SEQUENCE {
+# 163   11:         OCTET STRING 'javaFactory'
+# 176   32:         SET {
+# 178   30:           OCTET STRING 'org.example.fruit.FruitFactory'
+#         :           }
+#         :         }
+# 210   42:       SEQUENCE {
+# 212   13:         OCTET STRING 'javaClassName'
+# 227   25:         SET {
+# 229   23:           OCTET STRING 'org.example.fruit.Fruit'
+#         :           }
+#         :         }
+# 254   15:       SEQUENCE {
+# 256    2:         OCTET STRING 63 6E
+# 260    9:         SET {
+# 262    7:           OCTET STRING 'myapple'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 01 0B 02 01 05 64   82 01 04 04 21 63 6E 3D  0......d....!cn=
+0010: 6D 79 61 70 70 6C 65 2C   64 63 3D 69 65 2C 64 63  myapple,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 81  =oracle,dc=com0.
+0030: DE 30 44 04 0B 6F 62 6A   65 63 74 43 6C 61 73 73  .0D..objectClass
+0040: 31 35 04 03 74 6F 70 04   0D 6A 61 76 61 43 6F 6E  15..top..javaCon
+0050: 74 61 69 6E 65 72 04 0A   6A 61 76 61 4F 62 6A 65  tainer..javaObje
+0060: 63 74 04 13 6A 61 76 61   4E 61 6D 69 6E 67 52 65  ct..javaNamingRe
+0070: 66 65 72 65 6E 63 65 30   28 04 14 6A 61 76 61 52  ference0(..javaR
+0080: 65 66 65 72 65 6E 63 65   41 64 64 72 65 73 73 31  eferenceAddress1
+0090: 10 04 0E 23 30 23 66 72   75 69 74 23 61 70 70 6C  ...#0#fruit#appl
+00A0: 65 30 2F 04 0B 6A 61 76   61 46 61 63 74 6F 72 79  e0/..javaFactory
+00B0: 31 20 04 1E 6F 72 67 2E   65 78 61 6D 70 6C 65 2E  1 ..org.example.
+00C0: 66 72 75 69 74 2E 46 72   75 69 74 46 61 63 74 6F  fruit.FruitFacto
+00D0: 72 79 30 2A 04 0D 6A 61   76 61 43 6C 61 73 73 4E  ry0*..javaClassN
+00E0: 61 6D 65 31 19 04 17 6F   72 67 2E 65 78 61 6D 70  ame1...org.examp
+00F0: 6C 65 2E 66 72 75 69 74   2E 46 72 75 69 74 30 0F  le.fruit.Fruit0.
+0100: 04 02 63 6E 31 09 04 07   6D 79 61 70 70 6C 65     ..cn1...myapple
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 5
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 05 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP DeleteRequest:
+#
+#   0   67: SEQUENCE {
+#   2    1:   INTEGER 6
+#   5   33:   [APPLICATION 10] 'cn=myfruit,dc=ie,dc=oracle,dc=com'
+#  40   27:   [0] {
+#  42   25:     SEQUENCE {
+#  44   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 43 02 01 06 4A 21 63   6E 3D 6D 79 66 72 75 69  0C...J!cn=myfrui
+0010: 74 2C 64 63 3D 69 65 2C   64 63 3D 6F 72 61 63 6C  t,dc=ie,dc=oracl
+0020: 65 2C 64 63 3D 63 6F 6D   A0 1B 30 19 04 17 32 2E  e,dc=com..0...2.
+0030: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0040: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 6
+#   5    7:   [APPLICATION 11] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 06 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP DeleteRequest:
+#
+#   0   67: SEQUENCE {
+#   2    1:   INTEGER 7
+#   5   33:   [APPLICATION 10] 'cn=myapple,dc=ie,dc=oracle,dc=com'
+#  40   27:   [0] {
+#  42   25:     SEQUENCE {
+#  44   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 43 02 01 07 4A 21 63   6E 3D 6D 79 61 70 70 6C  0C...J!cn=myappl
+0010: 65 2C 64 63 3D 69 65 2C   64 63 3D 6F 72 61 63 6C  e,dc=ie,dc=oracl
+0020: 65 2C 64 63 3D 63 6F 6D   A0 1B 30 19 04 17 32 2E  e,dc=com..0...2.
+0030: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0040: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 7
+#   5    7:   [APPLICATION 11] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 07 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 8
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 08 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
+
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreObject.java b/jdk/test/javax/naming/module/src/test/test/StoreObject.java
new file mode 100644
index 0000000..2834321
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreObject.java
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate Java object storage and retrieval using an LDAP directory.
+ * The ActionEvent object is serializable and is supplied by the java.desktop
+ * module.
+ */
+
+package test;
+
+import java.awt.event.ActionEvent;
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+public class StoreObject {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/StoreObject.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   StoreObject <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java StoreObject ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the StoreObject.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Store objects in the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        System.out.println("StoreObject: connecting to " + ldapUri);
+        DirContext ctx = new InitialDirContext(env);
+        String dn = "cn=myevent";
+        String dn2 = "cn=myevent2";
+
+        try {
+            ctx.bind(dn, new ActionEvent("", 1, "Hello1"));
+            System.out.println("StoreObject: created entry '" + dn + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StoreObject: entry '" + dn +
+                "' already exists");
+            cleanup(ctx, (String)null);
+            return;
+        }
+
+        try {
+            ctx.bind(dn2, new ActionEvent("", 2, "Hello2"));
+            System.out.println("StoreObject: created entry '" + dn2 + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StoreObject: entry '" + dn2 +
+                "' already exists");
+            cleanup(ctx, dn);
+            return;
+        }
+
+        /*
+         * Retrieve objects from the LDAP directory
+         */
+
+        try {
+            ActionEvent b = (ActionEvent) ctx.lookup(dn);
+            System.out.println("StoreObject: retrieved object: " + b);
+        } catch (NamingException e) {
+            System.err.println("StoreObject: error retrieving entry '" +
+                dn + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        try {
+            ActionEvent t = (ActionEvent) ctx.lookup(dn2);
+            System.out.println("StoreObject: retrieved object: " + t);
+        } catch (NamingException e) {
+            System.err.println("StoreObject: error retrieving entry '" +
+                dn2 + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        cleanup(ctx, dn, dn2);
+        ctx.close();
+    }
+
+    /*
+     * Remove objects from the LDAP directory
+     */
+    private static void cleanup(DirContext ctx, String... dns)
+        throws NamingException {
+
+        for (String dn : dns) {
+            try {
+                ctx.destroySubcontext(dn);
+                System.out.println("StoreObject: removed entry '" + dn + "'");
+            } catch (NamingException e) {
+                System.err.println("StoreObject: error removing entry '" + dn +
+                    "' " + e);
+            }
+        }
+        ctx.close();
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreObject.ldap b/jdk/test/javax/naming/module/src/test/test/StoreObject.ldap
new file mode 100644
index 0000000..af1a5d5
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreObject.ldap
@@ -0,0 +1,664 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for StoreObject.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the StoreObject application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 1
+#   5   7:   [APPLICATION 0] {
+#   7   1:     INTEGER 3
+#  10   0:     OCTET STRING
+#  12   0:     [0]
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 01 60 07 02   01 03 04 00 80 00        0....`........
+
+# LDAP BindResponse:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 1
+#   5   7:   [APPLICATION 1] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP AddRequest:
+#
+#   0 597: SEQUENCE {
+#   4   1:   INTEGER 2
+#   7 561:   [APPLICATION 8] {
+#  11  33:     OCTET STRING 'cn=myevent,dc=ie,dc=oracle,dc=com'
+#  46 522:     SEQUENCE {
+#  50 253:       SEQUENCE {
+#  53  18:         OCTET STRING 'javaSerializedData'
+#  73 230:         SET {
+#  76 227:           OCTET STRING
+#        :             AC ED 00 05 73 72 00 1A 6A 61 76 61 2E 61 77 74
+#        :             2E 65 76 65 6E 74 2E 41 63 74 69 6F 6E 45 76 65
+#        :             6E 74 95 8A DA 7A 58 11 2F 2B 02 00 03 49 00 09
+#        :             6D 6F 64 69 66 69 65 72 73 4A 00 04 77 68 65 6E
+#        :             4C 00 0D 61 63 74 69 6F 6E 43 6F 6D 6D 61 6E 64
+#        :             74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74
+#        :             72 69 6E 67 3B 78 72 00 11 6A 61 76 61 2E 61 77
+#        :             74 2E 41 57 54 45 76 65 6E 74 E6 AB 2D E1 18 DF
+#        :             8A C3 02 00 03 5A 20 08 63 6F 6E 73 75 6D 65 64
+#        :             49 00 02 69 64 5B 00 05 62 64 61 74 61 74 00 02
+#        :             5B 42 78 72 00 15 6A 61 76 61 2E 75 74 69 6C 2E
+#        :             45 76 65 6E 74 4F 62 6A 65 63 74 4C 8D 09 4E 18
+#        :             6D 7D A8 02 00 00 78 70 00 00 00 00 01 70 00 00
+#        :             00 00 00 00 00 00 00 00 00 00 74 00 06 48 65 6C
+#        :             6C 6F 31
+#        :           }
+#        :         }
+# 306  69:       SEQUENCE {
+# 308  11:         OCTET STRING 'objectClass'
+# 321  54:         SET {
+# 323   3:           OCTET STRING 'top'
+# 328  13:           OCTET STRING 'javaContainer'
+# 343  10:           OCTET STRING 'javaObject'
+# 355  20:           OCTET STRING 'javaSerializedObject'
+#        :           }
+#        :         }
+# 377 128:       SEQUENCE {
+# 380  14:         OCTET STRING 'javaClassNames'
+# 396 110:         SET {
+# 398  26:           OCTET STRING 'java.awt.event.ActionEvent'
+# 426  17:           OCTET STRING 'java.awt.AWTEvent'
+# 445  21:           OCTET STRING 'java.util.EventObject'
+# 468  16:           OCTET STRING 'java.lang.Object'
+# 486  20:           OCTET STRING 'java.io.Serializable'
+#        :           }
+#        :         }
+# 508  45:       SEQUENCE {
+# 510  13:         OCTET STRING 'javaClassName'
+# 525  28:         SET {
+# 527  26:           OCTET STRING 'java.awt.event.ActionEvent'
+#        :           }
+#        :         }
+# 555  15:       SEQUENCE {
+# 557   2:         OCTET STRING 'cn'
+# 561   9:         SET {
+# 563   7:           OCTET STRING 'myevent'
+#        :           }
+#        :         }
+#        :       }
+#        :     }
+# 572  27:   [0] {
+# 574  25:     SEQUENCE {
+# 576  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 82 02 55 02 01 02 68   82 02 31 04 21 63 6E 3D  0..U...h..1.!cn=
+0010: 6D 79 65 76 65 6E 74 2C   64 63 3D 69 65 2C 64 63  myevent,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 82  =oracle,dc=com0.
+0030: 02 0A 30 81 FD 04 12 6A   61 76 61 53 65 72 69 61  ..0....javaSeria
+0040: 6C 69 7A 65 64 44 61 74   61 31 81 E6 04 81 E3 AC  lizedData1......
+0050: ED 00 05 73 72 00 1A 6A   61 76 61 2E 61 77 74 2E  ...sr..java.awt.
+0060: 65 76 65 6E 74 2E 41 63   74 69 6F 6E 45 76 65 6E  event.ActionEven
+0070: 74 95 8A DA 7A 58 11 2F   2B 02 00 03 49 00 09 6D  t...zX./+...I..m
+0080: 6F 64 69 66 69 65 72 73   4A 00 04 77 68 65 6E 4C  odifiersJ..whenL
+0090: 00 0D 61 63 74 69 6F 6E   43 6F 6D 6D 61 6E 64 74  ..actionCommandt
+00A0: 00 12 4C 6A 61 76 61 2F   6C 61 6E 67 2F 53 74 72  ..Ljava/lang/Str
+00B0: 69 6E 67 3B 78 72 00 11   6A 61 76 61 2E 61 77 74  ing;xr..java.awt
+00C0: 2E 41 57 54 45 76 65 6E   74 E6 AB 2D E1 18 DF 8A  .AWTEvent..-....
+00D0: C3 02 00 03 5A 00 08 63   6F 6E 73 75 6D 65 64 49  ....Z..consumedI
+00E0: 00 02 69 64 5B 00 05 62   64 61 74 61 74 00 02 5B  ..id[..bdatat..[
+00F0: 42 78 72 00 15 6A 61 76   61 2E 75 74 69 6C 2E 45  Bxr..java.util.E
+0100: 76 65 6E 74 4F 62 6A 65   63 74 4C 8D 09 4E 18 6D  ventObjectL..N.m
+0110: 7D A8 02 00 00 78 70 00   00 00 00 01 70 00 00 00  .....xp.....p...
+0120: 00 00 00 00 00 00 00 00   00 74 00 06 48 65 6C 6C  .........t..Hell
+0130: 6F 31 30 45 04 0B 6F 62   6A 65 63 74 43 6C 61 73  o10E..objectClas
+0140: 73 31 36 04 03 74 6F 70   04 0D 6A 61 76 61 43 6F  s16..top..javaCo
+0150: 6E 74 61 69 6E 65 72 04   0A 6A 61 76 61 4F 62 6A  ntainer..javaObj
+0160: 65 63 74 04 14 6A 61 76   61 53 65 72 69 61 6C 69  ect..javaSeriali
+0170: 7A 65 64 4F 62 6A 65 63   74 30 81 80 04 0E 6A 61  zedObject0....ja
+0180: 76 61 43 6C 61 73 73 4E   61 6D 65 73 31 6E 04 1A  vaClassNames1n..
+0190: 6A 61 76 61 2E 61 77 74   2E 65 76 65 6E 74 2E 41  java.awt.event.A
+01A0: 63 74 69 6F 6E 45 76 65   6E 74 04 11 6A 61 76 61  ctionEvent..java
+01B0: 2E 61 77 74 2E 41 57 54   45 76 65 6E 74 04 15 6A  .awt.AWTEvent..j
+01C0: 61 76 61 2E 75 74 69 6C   2E 45 76 65 6E 74 4F 62  ava.util.EventOb
+01D0: 6A 65 63 74 04 10 6A 61   76 61 2E 6C 61 6E 67 2E  ject..java.lang.
+01E0: 4F 62 6A 65 63 74 04 14   6A 61 76 61 2E 69 6F 2E  Object..java.io.
+01F0: 53 65 72 69 61 6C 69 7A   61 62 6C 65 30 2D 04 0D  Serializable0-..
+0200: 6A 61 76 61 43 6C 61 73   73 4E 61 6D 65 31 1C 04  javaClassName1..
+0210: 1A 6A 61 76 61 2E 61 77   74 2E 65 76 65 6E 74 2E  .java.awt.event.
+0220: 41 63 74 69 6F 6E 45 76   65 6E 74 30 0F 04 02 63  ActionEvent0...c
+0230: 6E 31 09 04 07 6D 79 65   76 65 6E 74 A0 1B 30 19  n1...myevent..0.
+0240: 04 17 32 2E 31 36 2E 38   34 30 2E 31 2E 31 31 33  ..2.16.840.1.113
+0250: 37 33 30 2E 33 2E 34 2E   32                       730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 2
+#   5   7:   [APPLICATION 9] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 02 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP AddRequest:
+#
+#   0 599: SEQUENCE {
+#   4   1:   INTEGER 3
+#   7 563:   [APPLICATION 8] {
+#  11  34:     OCTET STRING 'cn=myevent2,dc=ie,dc=oracle,dc=com'
+#  47 523:     SEQUENCE {
+#  51 253:       SEQUENCE {
+#  54  18:         OCTET STRING 'javaSerializedData'
+#  74 230:         SET {
+#  77 227:           OCTET STRING
+#        :             AC ED 00 05 73 72 00 1A 6A 61 76 61 2E 61 77 74
+#        :             2E 65 76 65 6E 74 2E 41 63 74 69 6F 6E 45 76 65
+#        :             6E 74 95 8A DA 7A 58 11 2F 2B 02 00 03 49 00 09
+#        :             6D 6F 64 69 66 69 65 72 73 4A 00 04 77 68 65 6E
+#        :             4C 00 0D 61 63 74 69 6F 6E 43 6F 6D 6D 61 6E 64
+#        :             74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74
+#        :             72 69 6E 67 3B 78 72 00 11 6A 61 76 61 2E 61 77
+#        :             74 2E 41 57 54 45 76 65 6E 74 E6 AB 2D E1 18 DF
+#        :             8A C3 02 00 03 5A 20 08 63 6F 6E 73 75 6D 65 64
+#        :             49 00 02 69 64 5B 00 05 62 64 61 74 61 74 00 02
+#        :             5B 42 78 72 00 15 6A 61 76 61 2E 75 74 69 6C 2E
+#        :             45 76 65 6E 74 4F 62 6A 65 63 74 4C 8D 09 4E 18
+#        :             6D 7D A8 02 00 00 78 70 00 00 00 00 02 70 00 00
+#        :             00 00 00 00 00 00 00 00 00 00 74 00 06 48 65 6C
+#        :             6C 6F 32
+#        :           }
+#        :         }
+# 307  69:       SEQUENCE {
+# 309  11:         OCTET STRING 'objectClass'
+# 322  54:         SET {
+# 324   3:           OCTET STRING 'top'
+# 325  13:           OCTET STRING 'javaContainer'
+# 344  10:           OCTET STRING 'javaObject'
+# 356  20:           OCTET STRING 'javaSerializedObject'
+#        :           }
+#        :         }
+# 378 128:       SEQUENCE {
+# 381  14:         OCTET STRING 'javaClassNames'
+# 397 110:         SET {
+# 399  26:           OCTET STRING 'java.awt.event.ActionEvent'
+# 427  17:           OCTET STRING 'java.awt.AWTEvent'
+# 446  21:           OCTET STRING 'java.util.EventObject'
+# 469  16:           OCTET STRING 'java.lang.Object'
+# 487  20:           OCTET STRING 'java.io.Serializable'
+#        :           }
+#        :         }
+# 509  45:       SEQUENCE {
+# 511  13:         OCTET STRING 'javaClassName'
+# 526  28:         SET {
+# 528  26:           OCTET STRING 'java.awt.event.ActionEvent'
+#        :           }
+#        :         }
+# 556  15:       SEQUENCE {
+# 558   2:         OCTET STRING 'cn'
+# 562  10:         SET {
+# 564   8:           OCTET STRING 'myevent2'
+#        :           }
+#        :         }
+#        :       }
+#        :     }
+# 574  27:   [0] {
+# 576  25:     SEQUENCE {
+# 578  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 82 02 57 02 01 03 68   82 02 33 04 22 63 6E 3D  0..W...h..3."cn=
+0010: 6D 79 65 76 65 6E 74 32   2C 64 63 3D 69 65 2C 64  myevent2,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 82 02 0B 30 81 FD 04 12   6A 61 76 61 53 65 72 69  ...0....javaSeri
+0040: 61 6C 69 7A 65 64 44 61   74 61 31 81 E6 04 81 E3  alizedData1.....
+0050: AC ED 00 05 73 72 00 1A   6A 61 76 61 2E 61 77 74  ....sr..java.awt
+0060: 2E 65 76 65 6E 74 2E 41   63 74 69 6F 6E 45 76 65  .event.ActionEve
+0070: 6E 74 95 8A DA 7A 58 11   2F 2B 02 00 03 49 00 09  nt...zX./+...I..
+0080: 6D 6F 64 69 66 69 65 72   73 4A 00 04 77 68 65 6E  modifiersJ..when
+0090: 4C 00 0D 61 63 74 69 6F   6E 43 6F 6D 6D 61 6E 64  L..actionCommand
+00A0: 74 00 12 4C 6A 61 76 61   2F 6C 61 6E 67 2F 53 74  t..Ljava/lang/St
+00B0: 72 69 6E 67 3B 78 72 00   11 6A 61 76 61 2E 61 77  ring;xr..java.aw
+00C0: 74 2E 41 57 54 45 76 65   6E 74 E6 AB 2D E1 18 DF  t.AWTEvent..-...
+00D0: 8A C3 02 00 03 5A 00 08   63 6F 6E 73 75 6D 65 64  .....Z..consumed
+00E0: 49 00 02 69 64 5B 00 05   62 64 61 74 61 74 00 02  I..id[..bdatat..
+00F0: 5B 42 78 72 00 15 6A 61   76 61 2E 75 74 69 6C 2E  [Bxr..java.util.
+0100: 45 76 65 6E 74 4F 62 6A   65 63 74 4C 8D 09 4E 18  EventObjectL..N.
+0110: 6D 7D A8 02 00 00 78 70   00 00 00 00 02 70 00 00  m.....xp.....p..
+0120: 00 00 00 00 00 00 00 00   00 00 74 00 06 48 65 6C  ..........t..Hel
+0130: 6C 6F 32 30 45 04 0B 6F   62 6A 65 63 74 43 6C 61  lo20E..objectCla
+0140: 73 73 31 36 04 03 74 6F   70 04 0D 6A 61 76 61 43  ss16..top..javaC
+0150: 6F 6E 74 61 69 6E 65 72   04 0A 6A 61 76 61 4F 62  ontainer..javaOb
+0160: 6A 65 63 74 04 14 6A 61   76 61 53 65 72 69 61 6C  ject..javaSerial
+0170: 69 7A 65 64 4F 62 6A 65   63 74 30 81 80 04 0E 6A  izedObject0....j
+0180: 61 76 61 43 6C 61 73 73   4E 61 6D 65 73 31 6E 04  avaClassNames1n.
+0190: 1A 6A 61 76 61 2E 61 77   74 2E 65 76 65 6E 74 2E  .java.awt.event.
+01A0: 41 63 74 69 6F 6E 45 76   65 6E 74 04 11 6A 61 76  ActionEvent..jav
+01B0: 61 2E 61 77 74 2E 41 57   54 45 76 65 6E 74 04 15  a.awt.AWTEvent..
+01C0: 6A 61 76 61 2E 75 74 69   6C 2E 45 76 65 6E 74 4F  java.util.EventO
+01D0: 62 6A 65 63 74 04 10 6A   61 76 61 2E 6C 61 6E 67  bject..java.lang
+01E0: 2E 4F 62 6A 65 63 74 04   14 6A 61 76 61 2E 69 6F  .Object..java.io
+01F0: 2E 53 65 72 69 61 6C 69   7A 61 62 6C 65 30 2D 04  .Serializable0-.
+0200: 0D 6A 61 76 61 43 6C 61   73 73 4E 61 6D 65 31 1C  .javaClassName1.
+0210: 04 1A 6A 61 76 61 2E 61   77 74 2E 65 76 65 6E 74  ..java.awt.event
+0220: 2E 41 63 74 69 6F 6E 45   76 65 6E 74 30 10 04 02  .ActionEvent0...
+0230: 63 6E 31 0A 04 08 6D 79   65 76 65 6E 74 32 A0 1B  cn1...myevent2..
+0240: 30 19 04 17 32 2E 31 36   2E 38 34 30 2E 31 2E 31  0...2.16.840.1.1
+0250: 31 33 37 33 30 2E 33 2E   34 2E 32                 13730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 3
+#   5   7:   [APPLICATION 9] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 03 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP SearchRequest:
+#
+#   0  99: SEQUENCE {
+#   2   1:   INTEGER 4
+#   5  65:   [APPLICATION 3] {
+#   7  33:     OCTET STRING 'cn=myevent,dc=ie,dc=oracle,dc=com'
+#  42   1:     ENUMERATED 0
+#  45   1:     ENUMERATED 0
+#  48   1:     INTEGER 0
+#  51   1:     INTEGER 0
+#  54   1:     BOOLEAN FALSE
+#  57  11:     [7] 'objectClass'
+#  70   0:     SEQUENCE {}
+#        :     }
+#  72  27:   [0] {
+#  74  25:     SEQUENCE {
+#  76  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 63 02 01 04 63 41 04   21 63 6E 3D 6D 79 65 76  0c...cA.!cn=myev
+0010: 65 6E 74 2C 64 63 3D 69   65 2C 64 63 3D 6F 72 61  ent,dc=ie,dc=ora
+0020: 63 6C 65 2C 64 63 3D 63   6F 6D 0A 01 00 0A 01 03  cle,dc=com......
+0030: 02 01 00 02 01 00 01 01   00 87 0B 6F 62 6A 65 63  ...........objec
+0040: 74 43 6C 61 73 73 30 00   A0 1B 30 19 04 17 32 2E  tClass0...0...2.
+0050: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0060: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0 568: SEQUENCE {
+#   4   1:   INTEGER 4
+#   7 561:   [APPLICATION 4] {
+#  11  33:     OCTET STRING 'cn=myevent,dc=ie,dc=oracle,dc=com'
+#  46 522:     SEQUENCE {
+#  50  15:       SEQUENCE {
+#  52   2:         OCTET STRING 'cn'
+#  56   9:         SET {
+#  58   7:           OCTET STRING 'myevent'
+#        :           }
+#        :         }
+#  67 128:       SEQUENCE {
+#  70  14:         OCTET STRING 'javaClassNames'
+#  86 110:         SET {
+#  88  26:           OCTET STRING 'java.awt.event.ActionEvent'
+# 116  17:           OCTET STRING 'java.awt.AWTEvent'
+# 135  21:           OCTET STRING 'java.util.EventObject'
+# 158  16:           OCTET STRING 'java.lang.Object'
+# 176  20:           OCTET STRING 'java.io.Serializable'
+#        :           }
+#        :         }
+# 198  45:       SEQUENCE {
+# 200  13:         OCTET STRING 'javaClassName'
+# 215  28:         SET {
+# 217  26:           OCTET STRING 'java.awt.event.ActionEvent'
+#        :           }
+#        :         }
+# 245  69:       SEQUENCE {
+# 247  11:         OCTET STRING 'objectClass'
+# 260  54:         SET {
+# 262  10:           OCTET STRING 'javaObject'
+# 274   3:           OCTET STRING 'top'
+# 279  20:           OCTET STRING 'javaSerializedObject'
+# 301  13:           OCTET STRING 'javaContainer'
+#        :           }
+#        :         }
+# 316 253:       SEQUENCE {
+# 319  18:         OCTET STRING 'javaSerializedData'
+# 339 230:         SET {
+# 342 227:           OCTET STRING
+#        :             AC ED 00 05 73 72 00 1A 6A 61 76 61 2E 61 77 74
+#        :             2E 65 76 65 6E 74 2E 41 63 74 69 6F 6E 45 76 65
+#        :             6E 74 95 8A DA 7A 58 11 2F 2B 02 00 03 49 00 09
+#        :             6D 6F 64 69 66 69 65 72 73 4A 00 04 77 68 65 6E
+#        :             4C 00 0D 61 63 74 69 6F 6E 43 6F 6D 6D 61 6E 64
+#        :             74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74
+#        :             72 69 6E 67 3B 78 72 00 11 6A 61 76 61 2E 61 77
+#        :             74 2E 41 57 54 45 76 65 6E 74 E6 AB 2D E1 18 DF
+#        :             8A C3 02 00 03 5A 20 08 63 6F 6E 73 75 6D 65 64
+#        :             49 00 02 69 64 5B 00 05 62 64 61 74 61 74 00 02
+#        :             5B 42 78 72 00 15 6A 61 76 61 2E 75 74 69 6C 2E
+#        :             45 76 65 6E 74 4F 62 6A 65 63 74 4C 8D 09 4E 18
+#        :             6D 7D A8 02 00 00 78 70 00 00 00 00 01 70 00 00
+#        :             00 00 00 00 00 00 00 00 00 00 74 00 06 48 65 6C
+#        :             6C 6F 31
+#        :           }
+#        :         }
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 82 02 38 02 01 04 64   82 02 31 04 21 63 6E 3D  0..8...d..1.!cn=
+0010: 6D 79 65 76 65 6E 74 2C   64 63 3D 69 65 2C 64 63  myevent,dc=ie,dc
+0020: 3D 6F 72 61 63 6C 65 2C   64 63 3D 63 6F 6D 30 82  =oracle,dc=com0.
+0030: 02 0A 30 0F 04 02 63 6E   31 09 04 07 6D 79 65 76  ..0...cn1...myev
+0040: 65 6E 74 30 81 80 04 0E   6A 61 76 61 43 6C 61 73  ent0....javaClas
+0050: 73 4E 61 6D 65 73 31 6E   04 1A 6A 61 76 61 2E 61  sNames1n..java.a
+0060: 77 74 2E 65 76 65 6E 74   2E 41 63 74 69 6F 6E 45  wt.event.ActionE
+0070: 76 65 6E 74 04 11 6A 61   76 61 2E 61 77 74 2E 41  vent..java.awt.A
+0080: 57 54 45 76 65 6E 74 04   15 6A 61 76 61 2E 75 74  WTEvent..java.ut
+0090: 69 6C 2E 45 76 65 6E 74   4F 62 6A 65 63 74 04 10  il.EventObject..
+00A0: 6A 61 76 61 2E 6C 61 6E   67 2E 4F 62 6A 65 63 74  java.lang.Object
+00B0: 04 14 6A 61 76 61 2E 69   6F 2E 53 65 72 69 61 6C  ..java.io.Serial
+00C0: 69 7A 61 62 6C 65 30 2D   04 0D 6A 61 76 61 43 6C  izable0-..javaCl
+00D0: 61 73 73 4E 61 6D 65 31   1C 04 1A 6A 61 76 61 2E  assName1...java.
+00E0: 61 77 74 2E 65 76 65 6E   74 2E 41 63 74 69 6F 6E  awt.event.Action
+00F0: 45 76 65 6E 74 30 45 04   0B 6F 62 6A 65 63 74 43  Event0E..objectC
+0100: 6C 61 73 73 31 36 04 0A   6A 61 76 61 4F 62 6A 65  lass16..javaObje
+0110: 63 74 04 03 74 6F 70 04   14 6A 61 76 61 53 65 72  ct..top..javaSer
+0120: 69 61 6C 69 7A 65 64 4F   62 6A 65 63 74 04 0D 6A  ializedObject..j
+0130: 61 76 61 43 6F 6E 74 61   69 6E 65 72 30 81 FD 04  avaContainer0...
+0140: 12 6A 61 76 61 53 65 72   69 61 6C 69 7A 65 64 44  .javaSerializedD
+0150: 61 74 61 31 81 E6 04 81   E3 AC ED 00 05 73 72 00  ata1.........sr.
+0160: 1A 6A 61 76 61 2E 61 77   74 2E 65 76 65 6E 74 2E  .java.awt.event.
+0170: 41 63 74 69 6F 6E 45 76   65 6E 74 95 8A DA 7A 58  ActionEvent...zX
+0180: 11 2F 2B 02 00 03 49 00   09 6D 6F 64 69 66 69 65  ./+...I..modifie
+0190: 72 73 4A 00 04 77 68 65   6E 4C 00 0D 61 63 74 69  rsJ..whenL..acti
+01A0: 6F 6E 43 6F 6D 6D 61 6E   64 74 00 12 4C 6A 61 76  onCommandt..Ljav
+01B0: 61 2F 6C 61 6E 67 2F 53   74 72 69 6E 67 3B 78 72  a/lang/String;xr
+01C0: 00 11 6A 61 76 61 2E 61   77 74 2E 41 57 54 45 76  ..java.awt.AWTEv
+01D0: 65 6E 74 E6 AB 2D E1 18   DF 8A C3 02 00 03 5A 00  ent..-........Z.
+01E0: 08 63 6F 6E 73 75 6D 65   64 49 00 02 69 64 5B 00  .consumedI..id[.
+01F0: 05 62 64 61 74 61 74 00   02 5B 42 78 72 00 15 6A  .bdatat..[Bxr..j
+0200: 61 76 61 2E 75 74 69 6C   2E 45 76 65 6E 74 4F 62  ava.util.EventOb
+0210: 6A 65 63 74 4C 8D 09 4E   18 6D 7D A8 02 00 00 78  jectL..N.m.....x
+0220: 70 00 00 00 00 01 70 00   00 00 00 00 00 00 00 00  p.....p.........
+0230: 00 00 00 74 00 06 48 65   6C 6C 6F 31              ...t..Hello1
+
+# LDAP SearchResultDone:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 4
+#   5   7:   [APPLICATION 5] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 04 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP SearchRequest:
+#
+#   0 100: SEQUENCE {
+#   2   1:   INTEGER 5
+#   5  66:   [APPLICATION 3] {
+#   7  34:     OCTET STRING 'cn=myevent2,dc=ie,dc=oracle,dc=com'
+#  43   1:     ENUMERATED 0
+#  46   1:     ENUMERATED 0
+#  49   1:     INTEGER 0
+#  52   1:     INTEGER 0
+#  55   1:     BOOLEAN FALSE
+#  58  11:     [7] 'objectClass'
+#  71   0:     SEQUENCE {}
+#        :     }
+#  73  27:   [0] {
+#  75  25:     SEQUENCE {
+#  77  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 64 02 01 05 63 42 04   22 63 6E 3D 6D 79 65 76  0d...cB."cn=myev
+0010: 65 6E 74 32 2C 64 63 3D   69 65 2C 64 63 3D 6F 72  ent2,dc=ie,dc=or
+0020: 61 63 6C 65 2C 64 63 3D   63 6F 6D 0A 01 00 0A 01  acle,dc=com.....
+0030: 03 02 01 00 02 01 00 01   01 00 87 0B 6F 62 6A 65  ............obje
+0040: 63 74 43 6C 61 73 73 30   00 A0 1B 30 19 04 17 32  ctClass0...0...2
+0050: 2E 31 36 2E 38 34 30 2E   31 2E 31 31 33 37 33 30  .16.840.1.113730
+0060: 2E 33 2E 34 2E 32                                  .3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0 570: SEQUENCE {
+#   4   1:   INTEGER 5
+#   7 563:   [APPLICATION 4] {
+#  11  34:     OCTET STRING 'cn=myevent2,dc=ie,dc=oracle,dc=com'
+#  47 523:     SEQUENCE {
+#  51  16:       SEQUENCE {
+#  53   2:         OCTET STRING 'cn'
+#  57  10:         SET {
+#  59   8:           OCTET STRING 'myevent2'
+#        :           }
+#        :         }
+#  69 128:       SEQUENCE {
+#  72  14:         OCTET STRING 'javaClassNames'
+#  88 110:         SET {
+#  90  26:           OCTET STRING 'java.awt.event.ActionEvent'
+# 118  17:           OCTET STRING 'java.awt.AWTEvent'
+# 137  21:           OCTET STRING 'java.util.EventObject'
+# 160  16:           OCTET STRING 'java.lang.Object'
+# 178  20:           OCTET STRING 'java.io.Serializable'
+#        :           }
+#        :         }
+# 200  45:       SEQUENCE {
+# 202  13:         OCTET STRING 'javaClassName'
+# 217  28:         SET {
+# 219  26:           OCTET STRING 'java.awt.event.ActionEvent'
+#        :           }
+#        :         }
+# 247  69:       SEQUENCE {
+# 249  11:         OCTET STRING 'objectClass'
+# 262  54:         SET {
+# 264  10:           OCTET STRING 'javaObject'
+# 276   3:           OCTET STRING 'top'
+# 281  20:           OCTET STRING 'javaSerializedObject'
+# 303  13:           OCTET STRING 'javaContainer'
+#        :           }
+#        :         }
+# 318 253:       SEQUENCE {
+# 321  18:         OCTET STRING 'javaSerializedData'
+# 341 230:         SET {
+# 344 227:           OCTET STRING
+#        :             AC ED 00 05 73 72 00 1A 6A 61 76 61 2E 61 77 74
+#        :             2E 65 76 65 6E 74 2E 41 63 74 69 6F 6E 45 76 65
+#        :             6E 74 95 8A DA 7A 58 11 2F 2B 02 00 03 49 00 09
+#        :             6D 6F 64 69 66 69 65 72 73 4A 00 04 77 68 65 6E
+#        :             4C 00 0D 61 63 74 69 6F 6E 43 6F 6D 6D 61 6E 64
+#        :             74 00 12 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74
+#        :             72 69 6E 67 3B 78 72 00 11 6A 61 76 61 2E 61 77
+#        :             74 2E 41 57 54 45 76 65 6E 74 E6 AB 2D E1 18 DF
+#        :             8A C3 02 00 03 5A 20 08 63 6F 6E 73 75 6D 65 64
+#        :             49 00 02 69 64 5B 00 05 62 64 61 74 61 74 00 02
+#        :             5B 42 78 72 00 15 6A 61 76 61 2E 75 74 69 6C 2E
+#        :             45 76 65 6E 74 4F 62 6A 65 63 74 4C 8D 09 4E 18
+#        :             6D 7D A8 02 00 00 78 70 00 00 00 00 02 70 00 00
+#        :             00 00 00 00 00 00 00 00 00 00 74 00 06 48 65 6C
+#        :             6C 6F 32
+#        :           }
+#        :         }
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 82 02 3A 02 01 05 64   82 02 33 04 22 63 6E 3D  0..:...d..3."cn=
+0010: 6D 79 65 76 65 6E 74 32   2C 64 63 3D 69 65 2C 64  myevent2,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 82 02 0B 30 10 04 02 63   6E 31 0A 04 08 6D 79 65  ...0...cn1...mye
+0040: 76 65 6E 74 32 30 81 80   04 0E 6A 61 76 61 43 6C  vent20....javaCl
+0050: 61 73 73 4E 61 6D 65 73   31 6E 04 1A 6A 61 76 61  assNames1n..java
+0060: 2E 61 77 74 2E 65 76 65   6E 74 2E 41 63 74 69 6F  .awt.event.Actio
+0070: 6E 45 76 65 6E 74 04 11   6A 61 76 61 2E 61 77 74  nEvent..java.awt
+0080: 2E 41 57 54 45 76 65 6E   74 04 15 6A 61 76 61 2E  .AWTEvent..java.
+0090: 75 74 69 6C 2E 45 76 65   6E 74 4F 62 6A 65 63 74  util.EventObject
+00A0: 04 10 6A 61 76 61 2E 6C   61 6E 67 2E 4F 62 6A 65  ..java.lang.Obje
+00B0: 63 74 04 14 6A 61 76 61   2E 69 6F 2E 53 65 72 69  ct..java.io.Seri
+00C0: 61 6C 69 7A 61 62 6C 65   30 2D 04 0D 6A 61 76 61  alizable0-..java
+00D0: 43 6C 61 73 73 4E 61 6D   65 31 1C 04 1A 6A 61 76  ClassName1...jav
+00E0: 61 2E 61 77 74 2E 65 76   65 6E 74 2E 41 63 74 69  a.awt.event.Acti
+00F0: 6F 6E 45 76 65 6E 74 30   45 04 0B 6F 62 6A 65 63  onEvent0E..objec
+0100: 74 43 6C 61 73 73 31 36   04 0A 6A 61 76 61 4F 62  tClass16..javaOb
+0110: 6A 65 63 74 04 03 74 6F   70 04 14 6A 61 76 61 53  ject..top..javaS
+0120: 65 72 69 61 6C 69 7A 65   64 4F 62 6A 65 63 74 04  erializedObject.
+0130: 0D 6A 61 76 61 43 6F 6E   74 61 69 6E 65 72 30 81  .javaContainer0.
+0140: FD 04 12 6A 61 76 61 53   65 72 69 61 6C 69 7A 65  ...javaSerialize
+0150: 64 44 61 74 61 31 81 E6   04 81 E3 AC ED 00 05 73  dData1.........s
+0160: 72 00 1A 6A 61 76 61 2E   61 77 74 2E 65 76 65 6E  r..java.awt.even
+0170: 74 2E 41 63 74 69 6F 6E   45 76 65 6E 74 95 8A DA  t.ActionEvent...
+0180: 7A 58 11 2F 2B 02 00 03   49 00 09 6D 6F 64 69 66  zX./+...I..modif
+0190: 69 65 72 73 4A 00 04 77   68 65 6E 4C 00 0D 61 63  iersJ..whenL..ac
+01A0: 74 69 6F 6E 43 6F 6D 6D   61 6E 64 74 00 12 4C 6A  tionCommandt..Lj
+01B0: 61 76 61 2F 6C 61 6E 67   2F 53 74 72 69 6E 67 3B  ava/lang/String;
+01C0: 78 72 00 11 6A 61 76 61   2E 61 77 74 2E 41 57 54  xr..java.awt.AWT
+01D0: 45 76 65 6E 74 E6 AB 2D   E1 18 DF 8A C3 02 00 03  Event..-........
+01E0: 5A 00 08 63 6F 6E 73 75   6D 65 64 49 00 02 69 64  Z..consumedI..id
+01F0: 5B 00 05 62 64 61 74 61   74 00 02 5B 42 78 72 00  [..bdatat..[Bxr.
+0200: 15 6A 61 76 61 2E 75 74   69 6C 2E 45 76 65 6E 74  .java.util.Event
+0210: 4F 62 6A 65 63 74 4C 8D   09 4E 18 6D 7D A8 02 00  ObjectL..N.m....
+0220: 00 78 70 00 00 00 00 02   70 00 00 00 00 00 00 00  .xp.....p.......
+0230: 00 00 00 00 00 74 00 06   48 65 6C 6C 6F 32        .....t..Hello2
+
+# LDAP SearchResultDone:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 5
+#   5   7:   [APPLICATION 5] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 05 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP DeleteRequest:
+#
+#   0  67: SEQUENCE {
+#   2   1:   INTEGER 6
+#   5  33:   [APPLICATION 10] 'cn=myevent,dc=ie,dc=oracle,dc=com'
+#  40  27:   [0] {
+#  42  25:     SEQUENCE {
+#  44  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 43 02 01 06 4A 21 63   6E 3D 6D 79 65 76 65 6E  0C...J!cn=myeven
+0010: 74 2C 64 63 3D 69 65 2C   64 63 3D 6F 72 61 63 6C  t,dc=ie,dc=oracl
+0020: 65 2C 64 63 3D 63 6F 6D   A0 1B 30 19 04 17 32 2E  e,dc=com..0...2.
+0030: 31 36 2E 38 34 30 2E 31   2E 31 31 33 37 33 30 2E  16.840.1.113730.
+0040: 33 2E 34 2E 32                                     3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 6
+#   5   7:   [APPLICATION 11] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 06 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP DeleteRequest:
+#
+#   0  68: SEQUENCE {
+#   2   1:   INTEGER 7
+#   5  34:   [APPLICATION 10] 'cn=myevent2,dc=ie,dc=oracle,dc=com'
+#  41  27:   [0] {
+#  43  25:     SEQUENCE {
+#  45  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 44 02 01 07 4A 22 63   6E 3D 6D 79 65 76 65 6E  0D...J"cn=myeven
+0010: 74 32 2C 64 63 3D 69 65   2C 64 63 3D 6F 72 61 63  t2,dc=ie,dc=orac
+0020: 6C 65 2C 64 63 3D 63 6F   6D A0 1B 30 19 04 17 32  le,dc=com..0...2
+0030: 2E 31 36 2E 38 34 30 2E   31 2E 31 31 33 37 33 30  .16.840.1.113730
+0040: 2E 33 2E 34 2E 32                                  .3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0  12: SEQUENCE {
+#   2   1:   INTEGER 7
+#   5   7:   [APPLICATION 11] {
+#   7   1:     ENUMERATED 0
+#  10   0:     OCTET STRING
+#  12   0:     OCTET STRING
+#        :     }
+#        :   }
+#
+0000: 30 0C 02 01 07 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP UnbindRequest:
+#
+#   0  34: SEQUENCE {
+#   2   1:   INTEGER 8
+#   5   0:   [APPLICATION 2]
+#   7  27:   [0] {
+#   9  25:     SEQUENCE {
+#  11  23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#        :       }
+#        :     }
+#        :   }
+#
+0000: 30 22 02 01 08 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
+
diff --git a/jdk/test/javax/naming/module/src/test/test/StorePerson.java b/jdk/test/javax/naming/module/src/test/test/StorePerson.java
new file mode 100644
index 0000000..4b6e174
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StorePerson.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate Java object storage and retrieval using an LDAP directory.
+ * The Person object and its associated object and state factory is supplied by
+ * a third-party module. As the Person object does not implement
+ * javax.naming.Referenceable, the classname of its state and object factory
+ * must be specified to the JNDI initial context.
+ */
+
+package test;
+
+import java.net.*;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+import org.example.person.Person;
+
+public class StorePerson {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/StorePerson.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   StorePerson <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java StorePerson ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the StorePerson.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Store Person objects in the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+    "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        // Specify the factory classname explicitly
+        env.put(Context.STATE_FACTORIES, "org.example.person.PersonFactory");
+        env.put(Context.OBJECT_FACTORIES, "org.example.person.PersonFactory");
+
+        System.out.println("StorePerson: connecting to " + ldapUri);
+        DirContext ctx = new InitialDirContext(env);
+        Person person = null;
+        String name = "John Smith";
+        String dn = "cn=" + name;
+
+        try {
+            person = new Person(name, "Smith");
+            person.setMailAddress("jsmith@smith.com");
+            ctx.bind(dn, person);
+            System.out.println("StorePerson: created entry '" + dn + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StorePerson: entry '" + dn +
+                "' already exists");
+            cleanup(ctx, (String)null);
+            return;
+        }
+
+        name = "Jill Smyth";
+        String dn2 = "cn=" + name;
+        Person person2 = new Person(name, "Smyth");
+        person2.setMailAddress("jsmyth@smith.com");
+
+        try {
+            ctx.bind(dn2, person2);
+            System.out.println("StorePerson: created entry '" + dn2 + "'");
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StorePerson: entry '" + dn2 +
+                "' already exists");
+            cleanup(ctx, dn);
+            return;
+        }
+
+        /*
+         * Retrieve Person objects from the LDAP directory
+         */
+
+        try {
+            Person person3 = (Person) ctx.lookup(dn);
+            System.out.println("StorePerson: retrieved object: " + person3);
+            if (person.getAttributes().equals(person3.getAttributes())) {
+                System.out.println(
+                    "StorePerson: retrieved person matches original");
+            } else {
+                System.out.println(
+                    "StorePerson: retrieved person does NOT match original");
+            }
+        } catch (NamingException e) {
+            System.err.println("StorePerson: error retrieving entry '" +
+                dn + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        try {
+            Person person4 = (Person) ctx.lookup(dn2);
+            System.out.println("StorePerson: retrieved object: " + person4);
+            if (person2.getAttributes().equals(person4.getAttributes())) {
+                System.out.println(
+                    "StorePerson: retrieved person matches original");
+            } else {
+                System.out.println(
+                    "StorePerson: retrieved person does NOT match original");
+            }
+        } catch (NamingException e) {
+            System.err.println("StorePerson: error retrieving entry '" +
+                dn2 + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn, dn2);
+            return;
+        }
+
+        cleanup(ctx, dn, dn2);
+        return;
+    }
+
+    /*
+     * Remove objects from the LDAP directory
+     */
+    private static void cleanup(DirContext ctx, String... dns)
+        throws NamingException {
+
+        for (String dn : dns) {
+            try {
+                ctx.destroySubcontext(dn);
+                System.out.println("StorePerson: removed entry '" + dn + "'");
+            } catch (NamingException e) {
+                System.err.println("StorePerson: error removing entry '" + dn +
+                    "' " + e);
+            }
+        }
+        ctx.close();
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/StorePerson.ldap b/jdk/test/javax/naming/module/src/test/test/StorePerson.ldap
new file mode 100644
index 0000000..c4de6ab
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StorePerson.ldap
@@ -0,0 +1,456 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for StorePerson.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the StorePerson application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10    0:     OCTET STRING
+#  12    0:     [0]
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 60 07 02   01 03 04 00 80 00        0....`........
+
+# LDAP BindResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP AddRequest:
+#
+#   0  183: SEQUENCE {
+#   3    1:   INTEGER 2
+#   6  148:   [APPLICATION 8] {
+#   9   36:     OCTET STRING 'cn=John Smith,dc=ie,dc=oracle,dc=com'
+#  47  108:     SEQUENCE {
+#  49   26:       SEQUENCE {
+#  51    4:         OCTET STRING 'mail'
+#  57   18:         SET {
+#  59   16:           OCTET STRING 'jsmith@smith.com'
+#         :           }
+#         :         }
+#  77   43:       SEQUENCE {
+#  79   11:         OCTET STRING 'objectClass'
+#  92   28:         SET {
+#  94    3:           OCTET STRING 'top'
+#  99    6:           OCTET STRING 'person'
+# 107   13:           OCTET STRING 'inetOrgPerson'
+#         :           }
+#         :         }
+# 122   13:       SEQUENCE {
+# 124    2:         OCTET STRING 73 6E
+# 128    7:         SET {
+# 130    5:           OCTET STRING 'Smith'
+#         :           }
+#         :         }
+# 137   18:       SEQUENCE {
+# 139    2:         OCTET STRING 63 6E
+# 143   12:         SET {
+# 145   10:           OCTET STRING 'John Smith'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+# 157   27:   [0] {
+# 159   25:     SEQUENCE {
+# 161   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 81 B7 02 01 02 68 81   94 04 24 63 6E 3D 4A 6F  0.....h...$cn=Jo
+0010: 68 6E 20 53 6D 69 74 68   2C 64 63 3D 69 65 2C 64  hn Smith,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 6C 30 1A 04 04 6D 61 69   6C 31 12 04 10 6A 73 6D  l0...mail1...jsm
+0040: 69 74 68 40 73 6D 69 74   68 2E 63 6F 6D 30 2B 04  ith@smith.com0+.
+0050: 0B 6F 62 6A 65 63 74 43   6C 61 73 73 31 1C 04 03  .objectClass1...
+0060: 74 6F 70 04 06 70 65 72   73 6F 6E 04 0D 69 6E 65  top..person..ine
+0070: 74 4F 72 67 50 65 72 73   6F 6E 30 0D 04 02 73 6E  tOrgPerson0...sn
+0080: 31 07 04 05 53 6D 69 74   68 30 12 04 02 63 6E 31  1...Smith0...cn1
+0090: 0C 04 0A 4A 6F 68 6E 20   53 6D 69 74 68 A0 1B 30  ...John Smith..0
+00A0: 19 04 17 32 2E 31 36 2E   38 34 30 2E 31 2E 31 31  ...2.16.840.1.11
+00B0: 33 37 33 30 2E 33 2E 34   2E 32                    3730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    7:   [APPLICATION 9] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 02 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP AddRequest:
+#
+#   0  183: SEQUENCE {
+#   3    1:   INTEGER 3
+#   6  148:   [APPLICATION 8] {
+#   9   36:     OCTET STRING 'cn=Jill Smyth,dc=ie,dc=oracle,dc=com'
+#  47  108:     SEQUENCE {
+#  49   26:       SEQUENCE {
+#  51    4:         OCTET STRING 'mail'
+#  57   18:         SET {
+#  59   16:           OCTET STRING 'jsmyth@smith.com'
+#         :           }
+#         :         }
+#  77   43:       SEQUENCE {
+#  79   11:         OCTET STRING 'objectClass'
+#  92   28:         SET {
+#  94    3:           OCTET STRING 'top'
+#  99    6:           OCTET STRING 'person'
+# 107   13:           OCTET STRING 'inetOrgPerson'
+#         :           }
+#         :         }
+# 122   13:       SEQUENCE {
+# 124    2:         OCTET STRING 73 6E
+# 128    7:         SET {
+# 130    5:           OCTET STRING 'Smyth'
+#         :           }
+#         :         }
+# 137   18:       SEQUENCE {
+# 139    2:         OCTET STRING 63 6E
+# 143   12:         SET {
+# 145   10:           OCTET STRING 'Jill Smyth'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+# 157   27:   [0] {
+# 159   25:     SEQUENCE {
+# 161   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 81 B7 02 01 03 68 81   94 04 24 63 6E 3D 4A 69  0.....h...$cn=Ji
+0010: 6C 6C 20 53 6D 79 74 68   2C 64 63 3D 69 65 2C 64  ll Smyth,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 6C 30 1A 04 04 6D 61 69   6C 31 12 04 10 6A 73 6D  l0...mail1...jsm
+0040: 79 74 68 40 73 6D 69 74   68 2E 63 6F 6D 30 2B 04  yth@smith.com0+.
+0050: 0B 6F 62 6A 65 63 74 43   6C 61 73 73 31 1C 04 03  .objectClass1...
+0060: 74 6F 70 04 06 70 65 72   73 6F 6E 04 0D 69 6E 65  top..person..ine
+0070: 74 4F 72 67 50 65 72 73   6F 6E 30 0D 04 02 73 6E  tOrgPerson0...sn
+0080: 31 07 04 05 53 6D 79 74   68 30 12 04 02 63 6E 31  1...Smyth0...cn1
+0090: 0C 04 0A 4A 69 6C 6C 20   53 6D 79 74 68 A0 1B 30  ...Jill Smyth..0
+00A0: 19 04 17 32 2E 31 36 2E   38 34 30 2E 31 2E 31 31  ...2.16.840.1.11
+00B0: 33 37 33 30 2E 33 2E 34   2E 32                    3730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 3
+#   5    7:   [APPLICATION 9] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 03 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP SearchRequest:
+#
+#   0  102: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5   68:   [APPLICATION 3] {
+#   7   36:     OCTET STRING 'cn=John Smith,dc=ie,dc=oracle,dc=com'
+#  45    1:     ENUMERATED 0
+#  48    1:     ENUMERATED 3
+#  51    1:     INTEGER 0
+#  54    1:     INTEGER 0
+#  57    1:     BOOLEAN FALSE
+#  60   11:     [7] 'objectClass'
+#  73    0:     SEQUENCE {}
+#         :     }
+#  75   27:   [0] {
+#  77   25:     SEQUENCE {
+#  79   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 66 02 01 04 63 44 04   24 63 6E 3D 4A 6F 68 6E  0f...cD.$cn=John
+0010: 20 53 6D 69 74 68 2C 64   63 3D 69 65 2C 64 63 3D   Smith,dc=ie,dc=
+0020: 6F 72 61 63 6C 65 2C 64   63 3D 63 6F 6D 0A 01 00  oracle,dc=com...
+0030: 0A 01 03 02 01 00 02 01   00 01 01 00 87 0B 6F 62  ..............ob
+0040: 6A 65 63 74 43 6C 61 73   73 30 00 A0 1B 30 19 04  jectClass0...0..
+0050: 17 32 2E 31 36 2E 38 34   30 2E 31 2E 31 31 33 37  .2.16.840.1.1137
+0060: 33 30 2E 33 2E 34 2E 32                            30.3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0  154: SEQUENCE {
+#   3    1:   INTEGER 4
+#   6  148:   [APPLICATION 4] {
+#   9   36:     OCTET STRING 'cn=John Smith,dc=ie,dc=oracle,dc=com'
+#  47  108:     SEQUENCE {
+#  49   26:       SEQUENCE {
+#  51    4:         OCTET STRING 'mail'
+#  57   18:         SET {
+#  59   16:           OCTET STRING 'jsmith@smith.com'
+#         :           }
+#         :         }
+#  77   43:       SEQUENCE {
+#  79   11:         OCTET STRING 'objectClass'
+#  92   28:         SET {
+#  94    3:           OCTET STRING 'top'
+#  99    6:           OCTET STRING 'person'
+# 107   13:           OCTET STRING 'inetOrgPerson'
+#         :           }
+#         :         }
+# 122   13:       SEQUENCE {
+# 124    2:         OCTET STRING 73 6E
+# 128    7:         SET {
+# 130    5:           OCTET STRING 'Smith'
+#         :           }
+#         :         }
+# 137   18:       SEQUENCE {
+# 139    2:         OCTET STRING 63 6E
+# 143   12:         SET {
+# 145   10:           OCTET STRING 'John Smith'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 81 9A 02 01 04 64 81   94 04 24 63 6E 3D 4A 6F  0.....d...$cn=Jo
+0010: 68 6E 20 53 6D 69 74 68   2C 64 63 3D 69 65 2C 64  hn Smith,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 6C 30 1A 04 04 6D 61 69   6C 31 12 04 10 6A 73 6D  l0...mail1...jsm
+0040: 69 74 68 40 73 6D 69 74   68 2E 63 6F 6D 30 2B 04  ith@smith.com0+.
+0050: 0B 6F 62 6A 65 63 74 43   6C 61 73 73 31 1C 04 03  .objectClass1...
+0060: 74 6F 70 04 06 70 65 72   73 6F 6E 04 0D 69 6E 65  top..person..ine
+0070: 74 4F 72 67 50 65 72 73   6F 6E 30 0D 04 02 73 6E  tOrgPerson0...sn
+0080: 31 07 04 05 53 6D 69 74   68 30 12 04 02 63 6E 31  1...Smith0...cn1
+0090: 0C 04 0A 4A 6F 68 6E 20   53 6D 69 74 68           ...John Smith
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 04 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP SearchRequest:
+#
+#   0  102: SEQUENCE {
+#   2    1:   INTEGER 5
+#   5   68:   [APPLICATION 3] {
+#   7   36:     OCTET STRING 'cn=Jill Smyth,dc=ie,dc=oracle,dc=com'
+#  45    1:     ENUMERATED 0
+#  48    1:     ENUMERATED 3
+#  51    1:     INTEGER 0
+#  54    1:     INTEGER 0
+#  57    1:     BOOLEAN FALSE
+#  60   11:     [7] 'objectClass'
+#  73    0:     SEQUENCE {}
+#         :     }
+#  75   27:   [0] {
+#  77   25:     SEQUENCE {
+#  79   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 66 02 01 05 63 44 04   24 63 6E 3D 4A 69 6C 6C  0f...cD.$cn=Jill
+0010: 20 53 6D 79 74 68 2C 64   63 3D 69 65 2C 64 63 3D   Smyth,dc=ie,dc=
+0020: 6F 72 61 63 6C 65 2C 64   63 3D 63 6F 6D 0A 01 00  oracle,dc=com...
+0030: 0A 01 03 02 01 00 02 01   00 01 01 00 87 0B 6F 62  ..............ob
+0040: 6A 65 63 74 43 6C 61 73   73 30 00 A0 1B 30 19 04  jectClass0...0..
+0050: 17 32 2E 31 36 2E 38 34   30 2E 31 2E 31 31 33 37  .2.16.840.1.1137
+0060: 33 30 2E 33 2E 34 2E 32                            30.3.4.2
+
+# LDAP SearchResultEntry:
+#
+#   0  154: SEQUENCE {
+#   3    1:   INTEGER 5
+#   6  148:   [APPLICATION 4] {
+#   9   36:     OCTET STRING 'cn=Jill Smyth,dc=ie,dc=oracle,dc=com'
+#  47  108:     SEQUENCE {
+#  49   26:       SEQUENCE {
+#  51    4:         OCTET STRING 'mail'
+#  57   18:         SET {
+#  59   16:           OCTET STRING 'jsmyth@smith.com'
+#         :           }
+#         :         }
+#  77   43:       SEQUENCE {
+#  79   11:         OCTET STRING 'objectClass'
+#  92   28:         SET {
+#  94    3:           OCTET STRING 'top'
+#  99    6:           OCTET STRING 'person'
+# 107   13:           OCTET STRING 'inetOrgPerson'
+#         :           }
+#         :         }
+# 122   13:       SEQUENCE {
+# 124    2:         OCTET STRING 73 6E
+# 128    7:         SET {
+# 130    5:           OCTET STRING 'Smyth'
+#         :           }
+#         :         }
+# 137   18:       SEQUENCE {
+# 139    2:         OCTET STRING 63 6E
+# 143   12:         SET {
+# 145   10:           OCTET STRING 'Jill Smyth'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 81 9A 02 01 05 64 81   94 04 24 63 6E 3D 4A 69  0.....d...$cn=Ji
+0010: 6C 6C 20 53 6D 79 74 68   2C 64 63 3D 69 65 2C 64  ll Smyth,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 6C 30 1A 04 04 6D 61 69   6C 31 12 04 10 6A 73 6D  l0...mail1...jsm
+0040: 79 74 68 40 73 6D 69 74   68 2E 63 6F 6D 30 2B 04  yth@smith.com0+.
+0050: 0B 6F 62 6A 65 63 74 43   6C 61 73 73 31 1C 04 03  .objectClass1...
+0060: 74 6F 70 04 06 70 65 72   73 6F 6E 04 0D 69 6E 65  top..person..ine
+0070: 74 4F 72 67 50 65 72 73   6F 6E 30 0D 04 02 73 6E  tOrgPerson0...sn
+0080: 31 07 04 05 53 6D 79 74   68 30 12 04 02 63 6E 31  1...Smyth0...cn1
+0090: 0C 04 0A 4A 69 6C 6C 20   53 6D 79 74 68           ...Jill Smyth
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 5
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 05 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP DeleteRequest:
+#
+#   0   70: SEQUENCE {
+#   2    1:   INTEGER 6
+#   5   36:   [APPLICATION 10] 'cn=John Smith,dc=ie,dc=oracle,dc=com'
+#  43   27:   [0] {
+#  45   25:     SEQUENCE {
+#  47   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 46 02 01 06 4A 24 63   6E 3D 4A 6F 68 6E 20 53  0F...J$cn=John S
+0010: 6D 69 74 68 2C 64 63 3D   69 65 2C 64 63 3D 6F 72  mith,dc=ie,dc=or
+0020: 61 63 6C 65 2C 64 63 3D   63 6F 6D A0 1B 30 19 04  acle,dc=com..0..
+0030: 17 32 2E 31 36 2E 38 34   30 2E 31 2E 31 31 33 37  .2.16.840.1.1137
+0040: 33 30 2E 33 2E 34 2E 32                            30.3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 6
+#   5    7:   [APPLICATION 11] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 06 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP DeleteRequest:
+#
+#   0   70: SEQUENCE {
+#   2    1:   INTEGER 7
+#   5   36:   [APPLICATION 10] 'cn=Jill Smyth,dc=ie,dc=oracle,dc=com'
+#  43   27:   [0] {
+#  45   25:     SEQUENCE {
+#  47   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 46 02 01 07 4A 24 63   6E 3D 4A 69 6C 6C 20 53  0F...J$cn=Jill S
+0010: 6D 79 74 68 2C 64 63 3D   69 65 2C 64 63 3D 6F 72  myth,dc=ie,dc=or
+0020: 61 63 6C 65 2C 64 63 3D   63 6F 6D A0 1B 30 19 04  acle,dc=com..0..
+0030: 17 32 2E 31 36 2E 38 34   30 2E 31 2E 31 31 33 37  .2.16.840.1.1137
+0040: 33 30 2E 33 2E 34 2E 32                            30.3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 7
+#   5    7:   [APPLICATION 11] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 07 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 8
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 08 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
+
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreRemote.java b/jdk/test/javax/naming/module/src/test/test/StoreRemote.java
new file mode 100644
index 0000000..95dea1b
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreRemote.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+/**
+ * Demonstrate Java Remote object storage and retrieval using an LDAP directory.
+ * The RMI object is supplied by a third-party module.
+ */
+
+package test;
+
+import java.io.*;
+import java.net.*;
+import java.rmi.Remote;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+import org.example.hello.*;
+
+public class StoreRemote {
+
+    // LDAP capture file
+    private static final String LDAP_CAPTURE_FILE =
+        System.getProperty("test.src") + "/src/test/test/StoreRemote.ldap";
+    // LDAPServer socket
+    private static ServerSocket serverSocket;
+
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * Process arguments
+         */
+
+        int argc = args.length;
+        if ((argc < 1) ||
+            ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) {
+
+            System.err.println("\nUsage:   StoreRemote <ldapurl>\n");
+            System.err.println("        <ldapurl> is the LDAP URL of the parent entry\n");
+            System.err.println("example:");
+            System.err.println("        java StoreRemote ldap://oasis/o=airius.com");
+            return;
+        }
+
+        /*
+         * Launch the LDAP server with the StoreRemote.ldap capture file
+         */
+
+        serverSocket = new ServerSocket(0);
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    new LDAPServer(serverSocket, LDAP_CAPTURE_FILE);
+               } catch (Exception e) {
+                   System.out.println("ERROR: unable to launch LDAP server");
+                   e.printStackTrace();
+               }
+            }
+        }).start();
+
+        /*
+         * Store a Remote object in the LDAP directory
+         */
+
+        Hashtable<String,Object> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+            "com.sun.jndi.ldap.LdapCtxFactory");
+        URI ldapUri = new URI(args[0]);
+        if (ldapUri.getPort() == -1) {
+            ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(),
+                serverSocket.getLocalPort(), ldapUri.getPath(), null, null);
+        }
+        env.put(Context.PROVIDER_URL, ldapUri.toString());
+        if (args[args.length - 1].equalsIgnoreCase("-trace")) {
+            env.put("com.sun.jndi.ldap.trace.ber", System.out);
+        }
+
+        System.out.println("StoreRemote: connecting to " + ldapUri);
+        DirContext ctx = new InitialDirContext(env);
+        String dn = "cn=myremote";
+
+        try {
+            Hello hello = new HelloImpl();
+            ctx.bind(dn, hello);
+            System.out.println("StoreRemote: created entry '" + dn + "'");
+
+            // Explicitly release the RMI object
+            UnicastRemoteObject.unexportObject(hello, true);
+
+        } catch (NameAlreadyBoundException e) {
+            System.err.println("StoreRemote: entry '" + dn +
+                "' already exists");
+            cleanup(ctx, (String)null);
+            return;
+        }
+
+        /*
+         * Retrieve the Remote object from the LDAP directory
+         */
+
+        try {
+            Hello obj = (Hello) ctx.lookup(dn);
+            System.out.println("StoreRemote: retrieved object: " + obj);
+            System.out.println("StoreRemote: calling Hello.sayHello()...\n" +
+                obj.sayHello());
+
+            // Explicitly release the RMI object
+            UnicastRemoteObject.unexportObject(obj, true);
+
+        } catch (NamingException e) {
+            System.err.println("StoreRemote: error retrieving entry '" +
+                dn + "' " + e);
+            e.printStackTrace();
+            cleanup(ctx, dn);
+            return;
+        }
+
+        cleanup(ctx, dn);
+    }
+
+    /*
+     * Remove objects from the LDAP directory
+     */
+    private static void cleanup(DirContext ctx, String... dns)
+        throws NamingException {
+
+        for (String dn : dns) {
+            try {
+                ctx.destroySubcontext(dn);
+                System.out.println("StoreRemote: removed entry '" + dn + "'");
+            } catch (NamingException e) {
+                System.err.println("StoreRemote: error removing entry '" + dn +
+                    "' " + e);
+            }
+        }
+        ctx.close();
+    }
+}
diff --git a/jdk/test/javax/naming/module/src/test/test/StoreRemote.ldap b/jdk/test/javax/naming/module/src/test/test/StoreRemote.ldap
new file mode 100644
index 0000000..f5c8ea8
--- /dev/null
+++ b/jdk/test/javax/naming/module/src/test/test/StoreRemote.ldap
@@ -0,0 +1,411 @@
+#
+# 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.
+#
+
+################################################################################
+# Capture file for StoreRemote.java
+#
+# NOTE: This hexadecimal dump of LDAP protocol messages was generated by
+#       running the StoreRemote application program against a real LDAP
+#       server and setting the JNDI/LDAP environment property:
+#       com.sun.jndi.ldap.trace.ber to activate LDAP message tracing.
+#
+#      (The ASN.1 annotations were generated separately by the dumpasn1
+#       utility and added only for clarity.)
+#
+################################################################################
+
+# LDAP BindRequest:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 0] {
+#   7    1:     INTEGER 3
+#  10    0:     OCTET STRING
+#  12    0:     [0]
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 60 07 02   01 03 04 00 80 00        0....`........
+
+# LDAP BindResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 1
+#   5    7:   [APPLICATION 1] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 01 61 07 0A   01 00 04 00 04 00        0....a........
+
+# LDAP AddRequest:
+#
+#   0  791: SEQUENCE {
+#   4    1:   INTEGER 2
+#   7  755:   [APPLICATION 8] {
+#  11   34:     OCTET STRING 'cn=myremote,dc=ie,dc=oracle,dc=com'
+#  47  715:     SEQUENCE {
+#  51  344:       SEQUENCE {
+#  55   18:         OCTET STRING 'javaSerializedData'
+#  75  320:         SET {
+#  79  316:           OCTET STRING
+#         :             AC ED 00 05 73 72 00 1B 6F 72 67 2E 65 78 61 6D
+#         :             70 6C 65 2E 68 65 6C 6C 6F 2E 48 65 6C 6C 6F 49
+#         :             6D 70 6C A9 56 08 D1 0C 92 18 98 02 00 00 78 72
+#         :             00 23 6A 61 76 61 2E 72 6D 69 2E 73 65 72 76 65
+#         :             72 2E 55 6E 69 63 61 73 74 52 65 6D 6F 74 65 4F
+#         :             62 6A 65 63 74 45 09 12 15 F5 E2 7E 31 02 00 03
+#         :             49 00 04 70 6F 72 74 4C 00 03 63 73 66 74 00 28
+#         :             4C 6A 61 76 61 2F 72 6D 69 2F 73 65 72 76 65 72
+#         :             2F 52 4D 49 43 6C 69 65 6E 74 53 6F 63 6B 65 74
+#         :             46 61 63 74 6F 72 79 3B 4C 00 03 73 73 66 74 00
+#         :             28 4C 6A 61 76 61 2F 72 6D 69 2F 73 65 72 76 65
+#         :             72 2F 52 4D 49 53 65 72 76 65 72 53 6F 63 6B 65
+#         :             74 46 61 63 74 6F 72 79 3B 78 72 00 1C 6A 61 76
+#         :             61 2E 72 6D 69 2E 73 65 72 76 65 72 2E 52 65 6D
+#         :             6F 74 65 53 65 72 76 65 72 C7 19 07 12 68 F3 39
+#         :             FB 02 00 00 78 72 00 1C 6A 61 76 61 2E 72 6D 69
+#         :             2E 73 65 72 76 65 72 2E 52 65 6D 6F 74 65 4F 62
+#         :             6A 65 63 74 D3 61 B4 91 0C 61 33 1E 03 00 00 78
+#         :             70 77 12 00 10 55 6E 69 63 61 73 74 53 65 72 76
+#         :             65 72 52 65 66 78 00 00 00 00 70 70
+#         :           }
+#         :         }
+# 399   69:       SEQUENCE {
+# 401   11:         OCTET STRING 'objectClass'
+# 414   54:         SET {
+# 416    3:           OCTET STRING 'top'
+# 421   13:           OCTET STRING 'javaContainer'
+# 436   10:           OCTET STRING 'javaObject'
+# 448   20:           OCTET STRING 'javaSerializedObject'
+#         :           }
+#         :         }
+# 470  227:       SEQUENCE {
+# 473   14:         OCTET STRING 'javaClassNames'
+# 489  208:         SET {
+# 492   27:           OCTET STRING 'org.example.hello.HelloImpl'
+# 521   35:           OCTET STRING 'java.rmi.server.UnicastRemoteObject'
+# 558   28:           OCTET STRING 'java.rmi.server.RemoteServer'
+# 588   28:           OCTET STRING 'java.rmi.server.RemoteObject'
+# 618   16:           OCTET STRING 'java.lang.Object'
+# 636   15:           OCTET STRING 'java.rmi.Remote'
+# 653   20:           OCTET STRING 'java.io.Serializable'
+# 675   23:           OCTET STRING 'org.example.hello.Hello'
+#         :           }
+#         :         }
+# 700   46:       SEQUENCE {
+# 702   13:         OCTET STRING 'javaClassName'
+# 717   29:         SET {
+# 719   27:           OCTET STRING 'org.example.hello.HelloImpl'
+#         :           }
+#         :         }
+# 748   16:       SEQUENCE {
+# 750    2:         OCTET STRING 63 6E
+# 754   10:         SET {
+# 756    8:           OCTET STRING 'myremote'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+# 766   27:   [0] {
+# 768   25:     SEQUENCE {
+# 770   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 03 17 02 01 02 68   82 02 F3 04 22 63 6E 3D  0......h...."cn=
+0010: 6D 79 72 65 6D 6F 74 65   2C 64 63 3D 69 65 2C 64  myremote,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 82 02 CB 30 82 01 58 04   12 6A 61 76 61 53 65 72  ...0..X..javaSer
+0040: 69 61 6C 69 7A 65 64 44   61 74 61 31 82 01 40 04  ializedData1..@.
+0050: 82 01 3C AC ED 00 05 73   72 00 1B 6F 72 67 2E 65  ..<....sr..org.e
+0060: 78 61 6D 70 6C 65 2E 68   65 6C 6C 6F 2E 48 65 6C  xample.hello.Hel
+0070: 6C 6F 49 6D 70 6C A9 56   08 D1 0C 92 18 98 02 00  loImpl.V........
+0080: 00 78 72 00 23 6A 61 76   61 2E 72 6D 69 2E 73 65  .xr.#java.rmi.se
+0090: 72 76 65 72 2E 55 6E 69   63 61 73 74 52 65 6D 6F  rver.UnicastRemo
+00A0: 74 65 4F 62 6A 65 63 74   45 09 12 15 F5 E2 7E 31  teObjectE......1
+00B0: 02 00 03 49 00 04 70 6F   72 74 4C 00 03 63 73 66  ...I..portL..csf
+00C0: 74 00 28 4C 6A 61 76 61   2F 72 6D 69 2F 73 65 72  t.(Ljava/rmi/ser
+00D0: 76 65 72 2F 52 4D 49 43   6C 69 65 6E 74 53 6F 63  ver/RMIClientSoc
+00E0: 6B 65 74 46 61 63 74 6F   72 79 3B 4C 00 03 73 73  ketFactory;L..ss
+00F0: 66 74 00 28 4C 6A 61 76   61 2F 72 6D 69 2F 73 65  ft.(Ljava/rmi/se
+0100: 72 76 65 72 2F 52 4D 49   53 65 72 76 65 72 53 6F  rver/RMIServerSo
+0110: 63 6B 65 74 46 61 63 74   6F 72 79 3B 78 72 00 1C  cketFactory;xr..
+0120: 6A 61 76 61 2E 72 6D 69   2E 73 65 72 76 65 72 2E  java.rmi.server.
+0130: 52 65 6D 6F 74 65 53 65   72 76 65 72 C7 19 07 12  RemoteServer....
+0140: 68 F3 39 FB 02 00 00 78   72 00 1C 6A 61 76 61 2E  h.9....xr..java.
+0150: 72 6D 69 2E 73 65 72 76   65 72 2E 52 65 6D 6F 74  rmi.server.Remot
+0160: 65 4F 62 6A 65 63 74 D3   61 B4 91 0C 61 33 1E 03  eObject.a...a3..
+0170: 00 00 78 70 77 12 00 10   55 6E 69 63 61 73 74 53  ..xpw...UnicastS
+0180: 65 72 76 65 72 52 65 66   78 00 00 00 00 70 70 30  erverRefx....pp0
+0190: 45 04 0B 6F 62 6A 65 63   74 43 6C 61 73 73 31 36  E..objectClass16
+01A0: 04 03 74 6F 70 04 0D 6A   61 76 61 43 6F 6E 74 61  ..top..javaConta
+01B0: 69 6E 65 72 04 0A 6A 61   76 61 4F 62 6A 65 63 74  iner..javaObject
+01C0: 04 14 6A 61 76 61 53 65   72 69 61 6C 69 7A 65 64  ..javaSerialized
+01D0: 4F 62 6A 65 63 74 30 81   E3 04 0E 6A 61 76 61 43  Object0....javaC
+01E0: 6C 61 73 73 4E 61 6D 65   73 31 81 D0 04 1B 6F 72  lassNames1....or
+01F0: 67 2E 65 78 61 6D 70 6C   65 2E 68 65 6C 6C 6F 2E  g.example.hello.
+0200: 48 65 6C 6C 6F 49 6D 70   6C 04 23 6A 61 76 61 2E  HelloImpl.#java.
+0210: 72 6D 69 2E 73 65 72 76   65 72 2E 55 6E 69 63 61  rmi.server.Unica
+0220: 73 74 52 65 6D 6F 74 65   4F 62 6A 65 63 74 04 1C  stRemoteObject..
+0230: 6A 61 76 61 2E 72 6D 69   2E 73 65 72 76 65 72 2E  java.rmi.server.
+0240: 52 65 6D 6F 74 65 53 65   72 76 65 72 04 1C 6A 61  RemoteServer..ja
+0250: 76 61 2E 72 6D 69 2E 73   65 72 76 65 72 2E 52 65  va.rmi.server.Re
+0260: 6D 6F 74 65 4F 62 6A 65   63 74 04 10 6A 61 76 61  moteObject..java
+0270: 2E 6C 61 6E 67 2E 4F 62   6A 65 63 74 04 0F 6A 61  .lang.Object..ja
+0280: 76 61 2E 72 6D 69 2E 52   65 6D 6F 74 65 04 14 6A  va.rmi.Remote..j
+0290: 61 76 61 2E 69 6F 2E 53   65 72 69 61 6C 69 7A 61  ava.io.Serializa
+02A0: 62 6C 65 04 17 6F 72 67   2E 65 78 61 6D 70 6C 65  ble..org.example
+02B0: 2E 68 65 6C 6C 6F 2E 48   65 6C 6C 6F 30 2E 04 0D  .hello.Hello0...
+02C0: 6A 61 76 61 43 6C 61 73   73 4E 61 6D 65 31 1D 04  javaClassName1..
+02D0: 1B 6F 72 67 2E 65 78 61   6D 70 6C 65 2E 68 65 6C  .org.example.hel
+02E0: 6C 6F 2E 48 65 6C 6C 6F   49 6D 70 6C 30 10 04 02  lo.HelloImpl0...
+02F0: 63 6E 31 0A 04 08 6D 79   72 65 6D 6F 74 65 A0 1B  cn1...myremote..
+0300: 30 19 04 17 32 2E 31 36   2E 38 34 30 2E 31 2E 31  0...2.16.840.1.1
+0310: 31 33 37 33 30 2E 33 2E   34 2E 32                 13730.3.4.2
+
+# LDAP AddResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 2
+#   5    7:   [APPLICATION 9] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 02 69 07 0A   01 00 04 00 04 00        0....i........
+
+# LDAP SearchRequest:
+#
+#   0  100: SEQUENCE {
+#   2    1:   INTEGER 3
+#   5   66:   [APPLICATION 3] {
+#   7   34:     OCTET STRING 'cn=myremote,dc=ie,dc=oracle,dc=com'
+#  43    1:     ENUMERATED 0
+#  46    1:     ENUMERATED 3
+#  49    1:     INTEGER 0
+#  52    1:     INTEGER 0
+#  55    1:     BOOLEAN FALSE
+#  58   11:     [7] 'objectClass'
+#  71    0:     SEQUENCE {}
+#         :     }
+#  73   27:   [0] {
+#  75   25:     SEQUENCE {
+#  77   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 64 02 01 03 63 42 04   22 63 6E 3D 6D 79 72 65  0d...cB."cn=myre
+0010: 6D 6F 74 65 2C 64 63 3D   69 65 2C 64 63 3D 6F 72  mote,dc=ie,dc=or
+0020: 61 63 6C 65 2C 64 63 3D   63 6F 6D 0A 01 00 0A 01  acle,dc=com.....
+0030: 03 02 01 00 02 01 00 01   01 00 87 0B 6F 62 6A 65  ............obje
+0040: 63 74 43 6C 61 73 73 30   00 A0 1B 30 19 04 17 32  ctClass0...0...2
+0050: 2E 31 36 2E 38 34 30 2E   31 2E 31 31 33 37 33 30  .16.840.1.113730
+0060: 2E 33 2E 34 2E 32                                  .3.4.2
+
+# LDAP SearchResultEntry:
+#
+#
+#   0  762: SEQUENCE {
+#   4    1:   INTEGER 3
+#   7  755:   [APPLICATION 4] {
+#  11   34:     OCTET STRING 'cn=myremote,dc=ie,dc=oracle,dc=com'
+#  47  715:     SEQUENCE {
+#  51  344:       SEQUENCE {
+#  55   18:         OCTET STRING 'javaSerializedData'
+#  75  320:         SET {
+#  79  316:           OCTET STRING
+#         :             AC ED 00 05 73 72 00 1B 6F 72 67 2E 65 78 61 6D
+#         :             70 6C 65 2E 68 65 6C 6C 6F 2E 48 65 6C 6C 6F 49
+#         :             6D 70 6C A9 56 08 D1 0C 92 18 98 02 00 00 78 72
+#         :             00 23 6A 61 76 61 2E 72 6D 69 2E 73 65 72 76 65
+#         :             72 2E 55 6E 69 63 61 73 74 52 65 6D 6F 74 65 4F
+#         :             62 6A 65 63 74 45 09 12 15 F5 E2 7E 31 02 00 03
+#         :             49 00 04 70 6F 72 74 4C 00 03 63 73 66 74 00 28
+#         :             4C 6A 61 76 61 2F 72 6D 69 2F 73 65 72 76 65 72
+#         :             2F 52 4D 49 43 6C 69 65 6E 74 53 6F 63 6B 65 74
+#         :             46 61 63 74 6F 72 79 3B 4C 00 03 73 73 66 74 00
+#         :             28 4C 6A 61 76 61 2F 72 6D 69 2F 73 65 72 76 65
+#         :             72 2F 52 4D 49 53 65 72 76 65 72 53 6F 63 6B 65
+#         :             74 46 61 63 74 6F 72 79 3B 78 72 00 1C 6A 61 76
+#         :             61 2E 72 6D 69 2E 73 65 72 76 65 72 2E 52 65 6D
+#         :             6F 74 65 53 65 72 76 65 72 C7 19 07 12 68 F3 39
+#         :             FB 02 00 00 78 72 00 1C 6A 61 76 61 2E 72 6D 69
+#         :             2E 73 65 72 76 65 72 2E 52 65 6D 6F 74 65 4F 62
+#         :             6A 65 63 74 D3 61 B4 91 0C 61 33 1E 03 00 00 78
+#         :             70 77 12 00 10 55 6E 69 63 61 73 74 53 65 72 76
+#         :             65 72 52 65 66 78 00 00 00 00 70 70
+#         :           }
+#         :         }
+# 399   69:       SEQUENCE {
+# 401   11:         OCTET STRING 'objectClass'
+# 414   54:         SET {
+# 416    3:           OCTET STRING 'top'
+# 421   13:           OCTET STRING 'javaContainer'
+# 436   10:           OCTET STRING 'javaObject'
+# 448   20:           OCTET STRING 'javaSerializedObject'
+#         :           }
+#         :         }
+# 470  227:       SEQUENCE {
+# 473   14:         OCTET STRING 'javaClassNames'
+# 489  208:         SET {
+# 492   27:           OCTET STRING 'org.example.hello.HelloImpl'
+# 521   35:           OCTET STRING 'java.rmi.server.UnicastRemoteObject'
+# 558   28:           OCTET STRING 'java.rmi.server.RemoteServer'
+# 588   28:           OCTET STRING 'java.rmi.server.RemoteObject'
+# 618   16:           OCTET STRING 'java.lang.Object'
+# 636   15:           OCTET STRING 'java.rmi.Remote'
+# 653   20:           OCTET STRING 'java.io.Serializable'
+# 675   23:           OCTET STRING 'org.example.hello.Hello'
+#         :           }
+#         :         }
+# 700   46:       SEQUENCE {
+# 702   13:         OCTET STRING 'javaClassName'
+# 717   29:         SET {
+# 719   27:           OCTET STRING 'org.example.hello.HelloImpl'
+#         :           }
+#         :         }
+# 748   16:       SEQUENCE {
+# 750    2:         OCTET STRING 63 6E
+# 754   10:         SET {
+# 756    8:           OCTET STRING 'myremote'
+#         :           }
+#         :         }
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 82 02 FA 02 01 03 64   82 02 F3 04 22 63 6E 3D  0......d...."cn=
+0010: 6D 79 72 65 6D 6F 74 65   2C 64 63 3D 69 65 2C 64  myremote,dc=ie,d
+0020: 63 3D 6F 72 61 63 6C 65   2C 64 63 3D 63 6F 6D 30  c=oracle,dc=com0
+0030: 82 02 CB 30 82 01 58 04   12 6A 61 76 61 53 65 72  ...0..X..javaSer
+0040: 69 61 6C 69 7A 65 64 44   61 74 61 31 82 01 40 04  ializedData1..@.
+0050: 82 01 3C AC ED 00 05 73   72 00 1B 6F 72 67 2E 65  ..<....sr..org.e
+0060: 78 61 6D 70 6C 65 2E 68   65 6C 6C 6F 2E 48 65 6C  xample.hello.Hel
+0070: 6C 6F 49 6D 70 6C A9 56   08 D1 0C 92 18 98 02 00  loImpl.V........
+0080: 00 78 72 00 23 6A 61 76   61 2E 72 6D 69 2E 73 65  .xr.#java.rmi.se
+0090: 72 76 65 72 2E 55 6E 69   63 61 73 74 52 65 6D 6F  rver.UnicastRemo
+00A0: 74 65 4F 62 6A 65 63 74   45 09 12 15 F5 E2 7E 31  teObjectE......1
+00B0: 02 00 03 49 00 04 70 6F   72 74 4C 00 03 63 73 66  ...I..portL..csf
+00C0: 74 00 28 4C 6A 61 76 61   2F 72 6D 69 2F 73 65 72  t.(Ljava/rmi/ser
+00D0: 76 65 72 2F 52 4D 49 43   6C 69 65 6E 74 53 6F 63  ver/RMIClientSoc
+00E0: 6B 65 74 46 61 63 74 6F   72 79 3B 4C 00 03 73 73  ketFactory;L..ss
+00F0: 66 74 00 28 4C 6A 61 76   61 2F 72 6D 69 2F 73 65  ft.(Ljava/rmi/se
+0100: 72 76 65 72 2F 52 4D 49   53 65 72 76 65 72 53 6F  rver/RMIServerSo
+0110: 63 6B 65 74 46 61 63 74   6F 72 79 3B 78 72 00 1C  cketFactory;xr..
+0120: 6A 61 76 61 2E 72 6D 69   2E 73 65 72 76 65 72 2E  java.rmi.server.
+0130: 52 65 6D 6F 74 65 53 65   72 76 65 72 C7 19 07 12  RemoteServer....
+0140: 68 F3 39 FB 02 00 00 78   72 00 1C 6A 61 76 61 2E  h.9....xr..java.
+0150: 72 6D 69 2E 73 65 72 76   65 72 2E 52 65 6D 6F 74  rmi.server.Remot
+0160: 65 4F 62 6A 65 63 74 D3   61 B4 91 0C 61 33 1E 03  eObject.a...a3..
+0170: 00 00 78 70 77 12 00 10   55 6E 69 63 61 73 74 53  ..xpw...UnicastS
+0180: 65 72 76 65 72 52 65 66   78 00 00 00 00 70 70 30  erverRefx....pp0
+0190: 45 04 0B 6F 62 6A 65 63   74 43 6C 61 73 73 31 36  E..objectClass16
+01A0: 04 03 74 6F 70 04 0D 6A   61 76 61 43 6F 6E 74 61  ..top..javaConta
+01B0: 69 6E 65 72 04 0A 6A 61   76 61 4F 62 6A 65 63 74  iner..javaObject
+01C0: 04 14 6A 61 76 61 53 65   72 69 61 6C 69 7A 65 64  ..javaSerialized
+01D0: 4F 62 6A 65 63 74 30 81   E3 04 0E 6A 61 76 61 43  Object0....javaC
+01E0: 6C 61 73 73 4E 61 6D 65   73 31 81 D0 04 1B 6F 72  lassNames1....or
+01F0: 67 2E 65 78 61 6D 70 6C   65 2E 68 65 6C 6C 6F 2E  g.example.hello.
+0200: 48 65 6C 6C 6F 49 6D 70   6C 04 23 6A 61 76 61 2E  HelloImpl.#java.
+0210: 72 6D 69 2E 73 65 72 76   65 72 2E 55 6E 69 63 61  rmi.server.Unica
+0220: 73 74 52 65 6D 6F 74 65   4F 62 6A 65 63 74 04 1C  stRemoteObject..
+0230: 6A 61 76 61 2E 72 6D 69   2E 73 65 72 76 65 72 2E  java.rmi.server.
+0240: 52 65 6D 6F 74 65 53 65   72 76 65 72 04 1C 6A 61  RemoteServer..ja
+0250: 76 61 2E 72 6D 69 2E 73   65 72 76 65 72 2E 52 65  va.rmi.server.Re
+0260: 6D 6F 74 65 4F 62 6A 65   63 74 04 10 6A 61 76 61  moteObject..java
+0270: 2E 6C 61 6E 67 2E 4F 62   6A 65 63 74 04 0F 6A 61  .lang.Object..ja
+0280: 76 61 2E 72 6D 69 2E 52   65 6D 6F 74 65 04 14 6A  va.rmi.Remote..j
+0290: 61 76 61 2E 69 6F 2E 53   65 72 69 61 6C 69 7A 61  ava.io.Serializa
+02A0: 62 6C 65 04 17 6F 72 67   2E 65 78 61 6D 70 6C 65  ble..org.example
+02B0: 2E 68 65 6C 6C 6F 2E 48   65 6C 6C 6F 30 2E 04 0D  .hello.Hello0...
+02C0: 6A 61 76 61 43 6C 61 73   73 4E 61 6D 65 31 1D 04  javaClassName1..
+02D0: 1B 6F 72 67 2E 65 78 61   6D 70 6C 65 2E 68 65 6C  .org.example.hel
+02E0: 6C 6F 2E 48 65 6C 6C 6F   49 6D 70 6C 30 10 04 02  lo.HelloImpl0...
+02F0: 63 6E 31 0A 04 08 6D 79   72 65 6D 6F 74 65        cn1...myremote
+
+# LDAP SearchResultDone:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 3
+#   5    7:   [APPLICATION 5] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 03 65 07 0A   01 00 04 00 04 00        0....e........
+
+# LDAP DeleteRequest:
+#
+#   0   68: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5   34:   [APPLICATION 10] 'cn=myremote,dc=ie,dc=oracle,dc=com'
+#  41   27:   [0] {
+#  43   25:     SEQUENCE {
+#  45   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 44 02 01 04 4A 22 63   6E 3D 6D 79 72 65 6D 6F  0D...J"cn=myremo
+0010: 74 65 2C 64 63 3D 69 65   2C 64 63 3D 6F 72 61 63  te,dc=ie,dc=orac
+0020: 6C 65 2C 64 63 3D 63 6F   6D A0 1B 30 19 04 17 32  le,dc=com..0...2
+0030: 2E 31 36 2E 38 34 30 2E   31 2E 31 31 33 37 33 30  .16.840.1.113730
+0040: 2E 33 2E 34 2E 32                                  .3.4.2
+
+# LDAP DeleteResponse:
+#
+#   0   12: SEQUENCE {
+#   2    1:   INTEGER 4
+#   5    7:   [APPLICATION 11] {
+#   7    1:     ENUMERATED 0
+#  10    0:     OCTET STRING
+#  12    0:     OCTET STRING
+#         :     }
+#         :   }
+#
+0000: 30 0C 02 01 04 6B 07 0A   01 00 04 00 04 00        0....k........
+
+# LDAP UnbindRequest:
+#
+#   0   34: SEQUENCE {
+#   2    1:   INTEGER 5
+#   5    0:   [APPLICATION 2]
+#   7   27:   [0] {
+#   9   25:     SEQUENCE {
+#  11   23:       OCTET STRING '2.16.840.1.113730.3.4.2'
+#         :       }
+#         :     }
+#         :   }
+#
+0000: 30 22 02 01 05 42 00 A0   1B 30 19 04 17 32 2E 31  0"...B...0...2.1
+0010: 36 2E 38 34 30 2E 31 2E   31 31 33 37 33 30 2E 33  6.840.1.113730.3
+0020: 2E 34 2E 32                                        .4.2
diff --git a/jdk/test/javax/net/ssl/Stapling/TEST.properties b/jdk/test/javax/net/ssl/Stapling/TEST.properties
new file mode 100644
index 0000000..f4117a3
--- /dev/null
+++ b/jdk/test/javax/net/ssl/Stapling/TEST.properties
@@ -0,0 +1,5 @@
+modules = \
+    java.base/sun.security.provider.certpath \
+    java.base/sun.security.util \
+    java.base/sun.security.validator \
+    java.base/sun.security.x509 
diff --git a/jdk/test/javax/security/auth/login/modules/JaasClient.java b/jdk/test/javax/security/auth/login/modules/JaasClient.java
new file mode 100644
index 0000000..6f1ef40
--- /dev/null
+++ b/jdk/test/javax/security/auth/login/modules/JaasClient.java
@@ -0,0 +1,103 @@
+/*
+ * 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 client;
+
+import java.io.IOException;
+import java.security.Principal;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.LoginContext;
+import com.sun.security.auth.UnixPrincipal;
+
+/**
+ * JAAS client which will try to authenticate a user through a custom JAAS LOGIN
+ * Module.
+ */
+public class JaasClient {
+
+    private static final String USER_NAME = "testUser";
+    private static final String PASSWORD = "testPassword";
+    private static final String LOGIN_CONTEXT = "ModularLoginConf";
+
+    public static void main(String[] args) {
+        try {
+            LoginContext lc = new LoginContext(LOGIN_CONTEXT,
+                    new MyCallbackHandler());
+            lc.login();
+            checkPrincipal(lc, true);
+            lc.logout();
+            checkPrincipal(lc, false);
+        } catch (LoginException le) {
+            throw new RuntimeException(le);
+        }
+        System.out.println("Test passed.");
+
+    }
+
+    /*
+     * Check context for principal of the test user.
+     */
+    private static void checkPrincipal(LoginContext loginContext,
+            boolean principalShouldExist) {
+        if (!principalShouldExist) {
+            if (loginContext.getSubject().getPrincipals().size() != 0) {
+                throw new RuntimeException("Test failed. Principal was not "
+                        + "cleared.");
+            }
+            return;
+        }
+        for (Principal p : loginContext.getSubject().getPrincipals()) {
+            if (p instanceof UnixPrincipal
+                    && USER_NAME.equals(p.getName())) {
+                //Proper principal was found, return.
+                return;
+            }
+        }
+        throw new RuntimeException("Test failed. UnixPrincipal "
+                + USER_NAME + " expected.");
+
+    }
+
+    private static class MyCallbackHandler implements CallbackHandler {
+
+        @Override
+        public void handle(Callback[] callbacks) throws IOException,
+                UnsupportedCallbackException {
+            for (Callback callback : callbacks) {
+                if (callback instanceof NameCallback) {
+                    ((NameCallback) callback).setName(USER_NAME);
+                } else if (callback instanceof PasswordCallback) {
+                    ((PasswordCallback) callback).setPassword(
+                            PASSWORD.toCharArray());
+                } else {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        }
+    }
+
+}
diff --git a/jdk/test/javax/security/auth/login/modules/JaasModularClientTest.java b/jdk/test/javax/security/auth/login/modules/JaasModularClientTest.java
new file mode 100644
index 0000000..d662d0e
--- /dev/null
+++ b/jdk/test/javax/security/auth/login/modules/JaasModularClientTest.java
@@ -0,0 +1,292 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Arrays;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.util.ArrayList;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.BeforeTest;
+
+/**
+ * @test
+ * @bug 8078813
+ * @library /lib/testlibrary
+ * @library /java/security/modules
+ * @build CompilerUtils JarUtils
+ * @summary Test custom JAAS module with all possible modular option. The test
+ *          includes different combination of JAAS client/login modules
+ *          interaction with or without service description.
+ * @run testng JaasModularClientTest
+ */
+public class JaasModularClientTest extends ModularTest {
+
+    private static final Path S_SRC = SRC.resolve("TestLoginModule.java");
+    private static final String S_PKG = "login";
+    private static final String S_JAR_NAME = S_PKG + JAR_EXTN;
+    private static final String S_DESCR_JAR_NAME = S_PKG + DESCRIPTOR
+            + JAR_EXTN;
+    private static final String MS_JAR_NAME = MODULAR + S_PKG + JAR_EXTN;
+    private static final String MS_DESCR_JAR_NAME = MODULAR + S_PKG + DESCRIPTOR
+            + JAR_EXTN;
+
+    private static final Path C_SRC = SRC.resolve("JaasClient.java");
+    private static final String C_PKG = "client";
+    private static final String C_JAR_NAME = C_PKG + JAR_EXTN;
+    private static final String MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME = MODULAR
+            + C_PKG + AUTO + JAR_EXTN;
+    private static final String MC_JAR_NAME = MODULAR + C_PKG + JAR_EXTN;
+
+    private static final Path BUILD_DIR = Paths.get(".").resolve("build");
+    private static final Path COMPILE_DIR = BUILD_DIR.resolve("bin");
+    private static final Path S_BUILD_DIR = COMPILE_DIR.resolve(S_PKG);
+    private static final Path S_WITH_META_DESCR_BUILD_DIR = COMPILE_DIR.resolve(
+            S_PKG + DESCRIPTOR);
+    private static final Path C_BUILD_DIR = COMPILE_DIR.resolve(C_PKG);
+    private static final Path M_BASE_PATH = BUILD_DIR.resolve("mbase");
+    private static final Path ARTIFACTS_DIR = BUILD_DIR.resolve("artifacts");
+
+    private static final Path S_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(S_PKG);
+    private static final Path S_JAR = S_ARTIFACTS_DIR.resolve(S_JAR_NAME);
+    private static final Path S_WITH_DESCRIPTOR_JAR = S_ARTIFACTS_DIR.resolve(
+            S_DESCR_JAR_NAME);
+    private static final Path MS_JAR = S_ARTIFACTS_DIR.resolve(MS_JAR_NAME);
+    private static final Path MS_WITH_DESCR_JAR = S_ARTIFACTS_DIR.resolve(
+            MS_DESCR_JAR_NAME);
+
+    private static final Path C_ARTIFACTS_DIR = ARTIFACTS_DIR.resolve(C_PKG);
+    private static final Path C_JAR = C_ARTIFACTS_DIR.resolve(C_JAR_NAME);
+    private static final Path MC_JAR = C_ARTIFACTS_DIR.resolve(MC_JAR_NAME);
+    private static final Path MC_DEPENDS_ON_AUTO_SERVICE_JAR = C_ARTIFACTS_DIR
+            .resolve(MC_DEPENDS_ON_AUTO_SERVICE_JAR_NAME);
+
+    private static final String MAIN = C_PKG + ".JaasClient";
+    private static final String S_INTERFACE
+            = "javax.security.auth.spi.LoginModule";
+    private static final String S_IMPL = S_PKG + ".TestLoginModule";
+    private static final List<String> M_REQUIRED = Arrays.asList("java.base",
+            "jdk.security.auth");
+    private static final Path META_DESCR_PATH = Paths.get("META-INF")
+            .resolve("services").resolve(S_INTERFACE);
+    private static final Path S_META_DESCR_FPATH = S_WITH_META_DESCR_BUILD_DIR
+            .resolve(META_DESCR_PATH);
+
+    private static final boolean WITH_S_DESCR = true;
+    private static final boolean WITHOUT_S_DESCR = false;
+    private static final String LOGIN_MODULE_NOT_FOUND_MSG
+            = "No LoginModule found";
+    private static final String NO_FAILURE = null;
+    private static final Map<String, String> VM_ARGS = new LinkedHashMap<>();
+
+    /**
+     * Generates Test specific input parameters.
+     */
+    @Override
+    public Object[][] getTestInput() {
+
+        List<List<Object>> params = new ArrayList<>();
+        String[] args = new String[]{};
+        //PARAMETER ORDERS -
+        //client Module Type, Service Module Type,
+        //Service META Descriptor Required,
+        //Expected Failure message, mechanism used to find the provider
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.EXPLICIT,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.AUTO,
+                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.EXPLICIT, MODULE_TYPE.UNNAMED,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.EXPLICIT,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.AUTO,
+                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.AUTO, MODULE_TYPE.UNNAMED,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.EXPLICIT,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.AUTO,
+                WITHOUT_S_DESCR, LOGIN_MODULE_NOT_FOUND_MSG, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
+                WITH_S_DESCR, NO_FAILURE, args));
+        params.add(Arrays.asList(MODULE_TYPE.UNNAMED, MODULE_TYPE.UNNAMED,
+                WITHOUT_S_DESCR, NO_FAILURE, args));
+        return params.stream().map(p -> p.toArray()).toArray(Object[][]::new);
+    }
+
+    /**
+     * Pre-compile and generate the artifacts required to run this test before
+     * running each test cases.
+     */
+    @BeforeTest
+    public void buildArtifacts() {
+
+        boolean done = true;
+        try {
+            VM_ARGS.put("-Duser.language=", "en");
+            VM_ARGS.put("-Duser.region", "US");
+            VM_ARGS.put("-Djava.security.auth.login.config=", SRC.resolve(
+                    "jaas.conf").toFile().getCanonicalPath());
+
+            done = CompilerUtils.compile(S_SRC, S_BUILD_DIR);
+            done &= CompilerUtils.compile(S_SRC, S_WITH_META_DESCR_BUILD_DIR);
+            done &= createMetaInfServiceDescriptor(S_META_DESCR_FPATH, S_IMPL);
+            //Generate regular/modular jars with(out) META-INF
+            //service descriptor
+            generateJar(true, MODULE_TYPE.EXPLICIT, MS_JAR, S_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.EXPLICIT, MS_WITH_DESCR_JAR,
+                    S_WITH_META_DESCR_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.UNNAMED, S_JAR, S_BUILD_DIR, false);
+            generateJar(true, MODULE_TYPE.UNNAMED, S_WITH_DESCRIPTOR_JAR,
+                    S_WITH_META_DESCR_BUILD_DIR, false);
+            //Generate regular/modular(depends on explicit/auto service)
+            //jars for client
+            done &= CompilerUtils.compile(C_SRC, C_BUILD_DIR);
+            generateJar(false, MODULE_TYPE.EXPLICIT, MC_JAR, C_BUILD_DIR, true);
+            generateJar(false, MODULE_TYPE.EXPLICIT,
+                    MC_DEPENDS_ON_AUTO_SERVICE_JAR, C_BUILD_DIR, false);
+            generateJar(false, MODULE_TYPE.UNNAMED, C_JAR, C_BUILD_DIR, false);
+            System.out.format("%nArtifacts generated successfully? %s", done);
+            if (!done) {
+                throw new RuntimeException("Artifact generation failed");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Generate modular/regular jar based on module type for this test.
+     */
+    private void generateJar(boolean isService, MODULE_TYPE moduleType,
+            Path jar, Path compilePath, boolean depends) throws IOException {
+
+        ModuleDescriptor mDescriptor = null;
+        if (isService) {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, S_PKG,
+                    S_PKG, S_INTERFACE, S_IMPL, null, M_REQUIRED, depends);
+        } else {
+            mDescriptor = generateModuleDescriptor(isService, moduleType, C_PKG,
+                    C_PKG, S_INTERFACE, null, S_PKG, M_REQUIRED, depends);
+        }
+        generateJar(mDescriptor, jar, compilePath);
+    }
+
+    /**
+     * Holds Logic for the test client. This method will get called with each
+     * test parameter.
+     */
+    @Override
+    public OutputAnalyzer executeTestClient(MODULE_TYPE cModuleType,
+            Path cJarPath, MODULE_TYPE sModuletype, Path sJarPath,
+            String... args) throws Exception {
+
+        OutputAnalyzer output = null;
+        try {
+            //For automated/explicit module type copy the corresponding
+            //jars to module base folder, which will be considered as
+            //module base path during execution.
+            if (!(cModuleType == MODULE_TYPE.UNNAMED
+                    && sModuletype == MODULE_TYPE.UNNAMED)) {
+                copyJarsToModuleBase(cModuleType, cJarPath, M_BASE_PATH);
+                copyJarsToModuleBase(sModuletype, sJarPath, M_BASE_PATH);
+            }
+
+            System.out.format("%nExecuting java client with required"
+                    + " custom service in class/module path.");
+            String mName = getModuleName(cModuleType, cJarPath,
+                    C_PKG);
+            Path cmBasePath = (cModuleType != MODULE_TYPE.UNNAMED
+                    || sModuletype != MODULE_TYPE.UNNAMED) ? M_BASE_PATH : null;
+            String cPath = buildClassPath(cModuleType, cJarPath, sModuletype,
+                    sJarPath);
+            output = ProcessTools.executeTestJava(
+                    getJavaCommand(cmBasePath, cPath, mName, MAIN, VM_ARGS,
+                            args)).outputTo(System.out).errorTo(System.out);
+        } finally {
+            //clean module path so that the modulepath can hold only
+            //the required jars for next run.
+            cleanModuleBasePath(M_BASE_PATH);
+            System.out.println("--------------------------------------------");
+        }
+        return output;
+    }
+
+    /**
+     * Decide the pre-generated client/service jar path for each test case
+     * based on client/service module type.
+     */
+    @Override
+    public Path findJarPath(boolean service, MODULE_TYPE moduleType,
+            boolean addMetaDesc, boolean dependsOnServiceModule) {
+        if (service) {
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                if (addMetaDesc) {
+                    return MS_WITH_DESCR_JAR;
+                } else {
+                    return MS_JAR;
+                }
+            } else {
+                if (addMetaDesc) {
+                    return S_WITH_DESCRIPTOR_JAR;
+                } else {
+                    return S_JAR;
+                }
+            }
+        } else {
+            if (moduleType == MODULE_TYPE.EXPLICIT) {
+                if (dependsOnServiceModule) {
+                    return MC_JAR;
+                } else {
+                    return MC_DEPENDS_ON_AUTO_SERVICE_JAR;
+                }
+            } else {
+                return C_JAR;
+            }
+        }
+    }
+
+}
diff --git a/jdk/test/javax/security/auth/login/modules/TEST.properties b/jdk/test/javax/security/auth/login/modules/TEST.properties
new file mode 100644
index 0000000..348c119
--- /dev/null
+++ b/jdk/test/javax/security/auth/login/modules/TEST.properties
@@ -0,0 +1 @@
+modules java.base/jdk.internal.module
diff --git a/jdk/test/javax/security/auth/login/modules/TestLoginModule.java b/jdk/test/javax/security/auth/login/modules/TestLoginModule.java
new file mode 100644
index 0000000..166dda9
--- /dev/null
+++ b/jdk/test/javax/security/auth/login/modules/TestLoginModule.java
@@ -0,0 +1,140 @@
+/*
+ * 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 login;
+
+import java.io.IOException;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import com.sun.security.auth.UnixPrincipal;
+
+/**
+ * Custom JAAS login module which will be loaded through Java LoginContext when
+ * it is bundled by Strict/Auto/Unnamed modules.
+ */
+public class TestLoginModule implements LoginModule {
+
+    private static final String USER_NAME = "testUser";
+    private static final String PASSWORD = "testPassword";
+    private Subject subject;
+    private CallbackHandler callbackHandler;
+    private UnixPrincipal userPrincipal;
+    private String username;
+    private String password;
+    private boolean succeeded = false;
+    private boolean commitSucceeded = false;
+
+    @Override
+    public void initialize(Subject subject, CallbackHandler callbackHandler,
+            Map<String, ?> sharedState, Map<String, ?> options) {
+
+        this.subject = subject;
+        this.callbackHandler = callbackHandler;
+        System.out.println(String.format(
+                "'%s' login module initialized", this.getClass()));
+    }
+
+    /*
+     * Authenticate the user by prompting for a username and password.
+     */
+    @Override
+    public boolean login() throws LoginException {
+        if (callbackHandler == null) {
+            throw new LoginException("No CallbackHandler available");
+        }
+
+        Callback[] callbacks = new Callback[2];
+        callbacks[0] = new NameCallback("Username: ");
+        callbacks[1] = new PasswordCallback("Password: ", false);
+
+        try {
+            callbackHandler.handle(callbacks);
+            username = ((NameCallback) callbacks[0]).getName();
+            password = new String(((PasswordCallback) callbacks[1])
+                    .getPassword());
+            System.out.println(String.format("'%s' login module found username"
+                    + " as '%s' and password as '%s'", this.getClass(),
+                    username, password));
+            if (username.equals(USER_NAME)
+                    && password.equals(PASSWORD)) {
+                System.out.println(String.format("'%s' login module "
+                        + "authentication done successfully", this.getClass()));
+                succeeded = true;
+                return true;
+            }
+            throw new IllegalArgumentException("Incorrect username/password!");
+        } catch (IOException | UnsupportedCallbackException e) {
+            throw new LoginException("Login failed: " + e.getMessage());
+        }
+    }
+
+    @Override
+    public boolean commit() throws LoginException {
+        if (succeeded == false) {
+            return false;
+        }
+        userPrincipal = new UnixPrincipal(username);
+        if (!subject.getPrincipals().contains(userPrincipal)) {
+            subject.getPrincipals().add(userPrincipal);
+        }
+        System.out.println(String.format("'%s' login module authentication "
+                + "committed", this.getClass()));
+        password = null;
+        commitSucceeded = true;
+        return true;
+    }
+
+    @Override
+    public boolean abort() throws LoginException {
+        if (succeeded == false) {
+            return false;
+        }
+        System.out.println(String.format(
+                "'%s' login module aborted", this.getClass()));
+        clearState();
+        return true;
+    }
+
+    @Override
+    public boolean logout() throws LoginException {
+        clearState();
+        System.out.println(String.format(
+                "'%s' login module logout completed", this.getClass()));
+        return true;
+    }
+
+    private void clearState() {
+        if (commitSucceeded) {
+            subject.getPrincipals().remove(userPrincipal);
+        }
+        username = null;
+        password = null;
+        userPrincipal = null;
+    }
+}
diff --git a/jdk/test/javax/security/auth/login/modules/jaas.conf b/jdk/test/javax/security/auth/login/modules/jaas.conf
new file mode 100644
index 0000000..c4b536e
--- /dev/null
+++ b/jdk/test/javax/security/auth/login/modules/jaas.conf
@@ -0,0 +1,3 @@
+ModularLoginConf {
+    login.TestLoginModule required;
+};
diff --git a/jdk/test/javax/swing/JComboBox/8080972/TestBasicComboBoxEditor.java b/jdk/test/javax/swing/JComboBox/8080972/TestBasicComboBoxEditor.java
new file mode 100644
index 0000000..205aecc
--- /dev/null
+++ b/jdk/test/javax/swing/JComboBox/8080972/TestBasicComboBoxEditor.java
@@ -0,0 +1,73 @@
+/*
+ * 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 javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.basic.BasicComboBoxEditor;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestBasicComboBoxEditor {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestBasicComboBoxEditor::testBasicComboBoxEditor);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestBasicComboBoxEditor::testBasicComboBoxEditor);
+    }
+
+    private static void testBasicComboBoxEditor() {
+
+        BasicComboBoxEditor comboBoxEditor = new BasicComboBoxEditor();
+        comboBoxEditor.setItem(new UserComboBoxEditorType("100"));
+
+        JTextField editor = (JTextField) comboBoxEditor.getEditorComponent();
+        editor.setText("200");
+        UserComboBoxEditorType item = (UserComboBoxEditorType) comboBoxEditor.getItem();
+
+        if (!item.str.equals("200")) {
+            throw new RuntimeException("Wrong itme value!");
+        }
+    }
+
+    public static class UserComboBoxEditorType {
+
+        String str;
+
+        public UserComboBoxEditorType(String str) {
+            this.str = str;
+        }
+
+        public static UserComboBoxEditorType valueOf(String str) {
+            return new UserComboBoxEditorType(str);
+        }
+
+        @Override
+        public String toString() {
+            return "UserComboBoxEditorType: " + str;
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/JEditorPane/8080972/TestJEditor.java b/jdk/test/javax/swing/JEditorPane/8080972/TestJEditor.java
new file mode 100644
index 0000000..7e12100
--- /dev/null
+++ b/jdk/test/javax/swing/JEditorPane/8080972/TestJEditor.java
@@ -0,0 +1,115 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
+import javax.swing.text.Document;
+import javax.swing.text.EditorKit;
+import javax.swing.text.ViewFactory;
+
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+public class TestJEditor {
+
+    public static void main(String[] args) throws Exception {
+
+        SwingUtilities.invokeAndWait(TestJEditor::testJEditorPane);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestJEditor::testJEditorPane);
+    }
+
+    private static void testJEditorPane() {
+
+        try {
+
+            JEditorPane.registerEditorKitForContentType("text/html", UserEditorKit.class.getName());
+            EditorKit editorKit = JEditorPane.createEditorKitForContentType("text/html");
+
+            if (!(editorKit instanceof UserEditorKit)) {
+                throw new RuntimeException("Editor kit is not UserEditorKit!");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static class UserEditorKit extends EditorKit {
+
+        @Override
+        public String getContentType() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public ViewFactory getViewFactory() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Action[] getActions() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Caret createCaret() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Document createDefaultDocument() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void read(InputStream in, Document doc, int pos) throws IOException, BadLocationException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void write(OutputStream out, Document doc, int pos, int len) throws IOException, BadLocationException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/JFormattedTextField/8080972/TestDefaultFormatter.java b/jdk/test/javax/swing/JFormattedTextField/8080972/TestDefaultFormatter.java
new file mode 100644
index 0000000..eabb026
--- /dev/null
+++ b/jdk/test/javax/swing/JFormattedTextField/8080972/TestDefaultFormatter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.text.ParseException;
+import javax.swing.SwingUtilities;
+import javax.swing.text.DefaultFormatter;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestDefaultFormatter {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestDefaultFormatter::testDefaultFormatter);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestDefaultFormatter::testDefaultFormatter);
+    }
+    private static void testDefaultFormatter() {
+        testDefaultFormatter(new DefaultFormatter() {
+        });
+        testDefaultFormatter(new DefaultFormatter());
+    }
+
+    private static void testDefaultFormatter(DefaultFormatter formatter ) {
+        try {
+            System.out.println("formatter: " + formatter.getClass());
+            formatter.setValueClass(UserValueClass.class);
+            UserValueClass userValue = (UserValueClass) formatter.stringToValue("test");
+
+            if (!userValue.str.equals("test")) {
+                throw new RuntimeException("String value is wrong!");
+            }
+        } catch (ParseException ex) {
+            throw new RuntimeException(ex);
+        }
+
+    }
+
+    public static class UserValueClass {
+
+        String str;
+
+        public UserValueClass(String str) {
+            this.str = str;
+        }
+
+        @Override
+        public String toString() {
+            return "UserValueClass: " + str;
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/JTable/8080972/TestJTableCellEditor.java b/jdk/test/javax/swing/JTable/8080972/TestJTableCellEditor.java
new file mode 100644
index 0000000..592044a
--- /dev/null
+++ b/jdk/test/javax/swing/JTable/8080972/TestJTableCellEditor.java
@@ -0,0 +1,90 @@
+/*
+ * 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 javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellEditor;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestJTableCellEditor {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestJTableCellEditor::testJTableCellEditor);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestJTableCellEditor::testJTableCellEditor);
+    }
+
+    private static void testJTableCellEditor() {
+
+        final Class cls = UserEditor.class;
+
+        JTable table = new JTable(new AbstractTableModel() {
+            public int getRowCount() {
+                return 0;
+            }
+
+            public int getColumnCount() {
+                return 1;
+            }
+
+            public Object getValueAt(int r, int c) {
+                return "Some Value";
+            }
+
+            public Class getColumnClass(int c) {
+                return cls;
+            }
+        });
+
+        TableCellEditor editor = table.getDefaultEditor(Object.class);
+        editor.getTableCellEditorComponent(table,
+                UserEditor.TEST_VALUE, false, 0, 0);
+        editor.stopCellEditing();
+        Object obj = editor.getCellEditorValue();
+
+        if (obj == null) {
+            throw new RuntimeException("Editor object is null!");
+        }
+
+        if (!UserEditor.TEST_VALUE.equals(((UserEditor) obj).value)) {
+            throw new RuntimeException("Value is incorrect!");
+        }
+    }
+
+    public static class UserEditor {
+
+        private static final String TEST_VALUE = "Test Value";
+
+        private final String value;
+
+        public UserEditor(String value) {
+            this.value = value;
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/UIDefaults/8080972/TestProxyLazyValue.java b/jdk/test/javax/swing/UIDefaults/8080972/TestProxyLazyValue.java
new file mode 100644
index 0000000..e36dba2
--- /dev/null
+++ b/jdk/test/javax/swing/UIDefaults/8080972/TestProxyLazyValue.java
@@ -0,0 +1,156 @@
+/*
+ * 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 javax.swing.SwingUtilities;
+import javax.swing.UIDefaults;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestProxyLazyValue {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestProxyLazyValue::testUserProxyLazyValue);
+        SwingUtilities.invokeAndWait(TestProxyLazyValue::testProxyLazyValue);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestProxyLazyValue::testUserProxyLazyValue);
+        SwingUtilities.invokeAndWait(TestProxyLazyValue::testProxyLazyValue);
+    }
+
+    private static void testUserProxyLazyValue() {
+
+        Object obj = new UserProxyLazyValue(
+                UserLazyClass.class.getName()).createValue(null);
+
+        if (!(obj instanceof UserLazyClass)) {
+            throw new RuntimeException("Object is not UserLazyClass!");
+        }
+
+        obj = new UserProxyLazyValue(UserLazyClass.class.getName(),
+                new Object[]{UserLazyClass.CONSTRUCTOR_ARG}).createValue(null);
+
+        if (!(obj instanceof UserLazyClass)) {
+            throw new RuntimeException("Object is not UserLazyClass!");
+        }
+
+        if (((UserLazyClass) obj).arg != UserLazyClass.CONSTRUCTOR_ARG) {
+            throw new RuntimeException("Constructt argument is wrong!");
+        }
+
+        obj = new UserProxyLazyValue(UserLazyClass.class.getName(),
+                "method1").createValue(null);
+
+        if (!UserLazyClass.RESULT_1.equals(obj)) {
+            throw new RuntimeException("Result is wrong!");
+        }
+
+        obj = new UserProxyLazyValue(UserLazyClass.class.getName(),
+                "method2", new Object[]{UserLazyClass.RESULT_2}).createValue(null);
+
+        if (!UserLazyClass.RESULT_2.equals(obj)) {
+            throw new RuntimeException("Result is wrong!");
+        }
+    }
+
+    private static void testProxyLazyValue() {
+
+        Object obj = new UIDefaults.ProxyLazyValue(
+                UserLazyClass.class.getName()).createValue(null);
+
+        if (!(obj instanceof UserLazyClass)) {
+            throw new RuntimeException("Object is not UserLazyClass!");
+        }
+
+        obj = new UIDefaults.ProxyLazyValue(UserLazyClass.class.getName(),
+                new Object[]{UserLazyClass.CONSTRUCTOR_ARG}).createValue(null);
+
+        if (!(obj instanceof UserLazyClass)) {
+            throw new RuntimeException("Object is not UserLazyClass!");
+        }
+
+        if (((UserLazyClass) obj).arg != UserLazyClass.CONSTRUCTOR_ARG) {
+            throw new RuntimeException("Constructt argument is wrong!");
+        }
+
+        obj = new UIDefaults.ProxyLazyValue(UserLazyClass.class.getName(),
+                "method1").createValue(null);
+
+        if (!UserLazyClass.RESULT_1.equals(obj)) {
+            throw new RuntimeException("Result is wrong!");
+        }
+
+        obj = new UIDefaults.ProxyLazyValue(UserLazyClass.class.getName(),
+                "method2", new Object[]{UserLazyClass.RESULT_2}).createValue(null);
+
+        if (!UserLazyClass.RESULT_2.equals(obj)) {
+            throw new RuntimeException("Result is wrong!");
+        }
+    }
+
+    public static class UserLazyClass {
+
+        static final int CONSTRUCTOR_ARG = 100;
+        static final String RESULT_1 = "1";
+        static final String RESULT_2 = "2";
+
+        int arg;
+
+        public UserLazyClass() {
+        }
+
+        public UserLazyClass(int arg) {
+            this.arg = arg;
+        }
+
+        public static String method1() {
+            return RESULT_1;
+        }
+
+        public static String method2(String arg) {
+            return arg;
+        }
+    }
+
+    public static class UserProxyLazyValue extends UIDefaults.ProxyLazyValue {
+
+        public UserProxyLazyValue(String className) {
+            super(className);
+        }
+
+        public UserProxyLazyValue(String className, Object[] constructorArgs) {
+            super(className, constructorArgs);
+        }
+
+        public UserProxyLazyValue(String className, String methodName) {
+            super(className, methodName);
+        }
+
+        public UserProxyLazyValue(String className, String methodName,
+                Object[] methodArgs) {
+            super(className, methodName, methodArgs);
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/dnd/8080972/TestTransferHandler.java b/jdk/test/javax/swing/dnd/8080972/TestTransferHandler.java
new file mode 100644
index 0000000..a7cf675
--- /dev/null
+++ b/jdk/test/javax/swing/dnd/8080972/TestTransferHandler.java
@@ -0,0 +1,99 @@
+/*
+ * 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.awt.Color;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.TransferHandler;
+import java.awt.datatransfer.*;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestTransferHandler {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestTransferHandler::testTransferHandler);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestTransferHandler::testTransferHandler);
+    }
+
+    private static void testTransferHandler() {
+        try {
+            TransferHandler transferHandler = new TransferHandler("userColor");
+            UserJComponent comp = new UserJComponent();
+
+            final String colorType = DataFlavor.javaJVMLocalObjectMimeType
+                    + ";class=java.awt.Color";
+            final DataFlavor colorFlavor = new DataFlavor(colorType);
+
+            Transferable transferable = new Transferable() {
+
+                public DataFlavor[] getTransferDataFlavors() {
+                    return new DataFlavor[]{colorFlavor};
+
+                }
+
+                public boolean isDataFlavorSupported(DataFlavor flavor) {
+                    return true;
+                }
+
+                public Object getTransferData(DataFlavor flavor) {
+                    return UserJComponent.TEST_COLOR;
+                }
+
+            };
+
+            transferHandler.importData(comp, transferable);
+
+            if (!UserJComponent.TEST_COLOR.equals(comp.color)) {
+                throw new RuntimeException("Wrong color!");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static class UserJComponent extends JComponent {
+
+        public static final Color USER_COLOR = new Color(10, 20, 30);
+        public static final Color TEST_COLOR = new Color(15, 25, 35);
+
+        Color color = USER_COLOR;
+
+        public UserJComponent() {
+
+        }
+
+        public Color getUserColor() {
+            return color;
+        }
+
+        public void setUserColor(Color color) {
+            this.color = color;
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/plaf/nimbus/8080972/TestAbstractRegionPainter.java b/jdk/test/javax/swing/plaf/nimbus/8080972/TestAbstractRegionPainter.java
new file mode 100644
index 0000000..f2b1872
--- /dev/null
+++ b/jdk/test/javax/swing/plaf/nimbus/8080972/TestAbstractRegionPainter.java
@@ -0,0 +1,97 @@
+/*
+ * 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.awt.Color;
+import java.awt.Graphics2D;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.nimbus.AbstractRegionPainter;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestAbstractRegionPainter {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestAbstractRegionPainter::testAbstractRegionPainter);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestAbstractRegionPainter::testAbstractRegionPainter);
+    }
+
+    private static void testAbstractRegionPainter() {
+        UserAbstractRegionPainter painter = new UserAbstractRegionPainter();
+
+        JComponent userComponent = new UserJComponent();
+
+        Color color = painter.getUserComponentColor(userComponent, "UserColor",
+                Color.yellow, 0, 0, 0);
+
+        if (!UserJComponent.USER_COLOR.equals(color)) {
+            throw new RuntimeException("Wrong color: " + color);
+        }
+    }
+
+    public static class UserJComponent extends JComponent {
+
+        public static final Color USER_COLOR = new Color(10, 20, 30);
+        public static final Color TEST_COLOR = new Color(15, 25, 35);
+
+        Color color = USER_COLOR;
+
+        public UserJComponent() {
+
+        }
+
+        public Color getUserColor() {
+            return color;
+        }
+
+        public void setUserColor(Color color) {
+            this.color = color;
+        }
+    }
+
+    public static class UserAbstractRegionPainter extends AbstractRegionPainter {
+
+        public Color getUserComponentColor(JComponent c, String property,
+                Color defaultColor,
+                float saturationOffset,
+                float brightnessOffset,
+                int alphaOffset) {
+            return getComponentColor(c, property, defaultColor, saturationOffset, brightnessOffset, alphaOffset);
+        }
+
+        @Override
+        protected AbstractRegionPainter.PaintContext getPaintContext() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+}
diff --git a/jdk/test/javax/swing/text/View/8080972/TestObjectView.java b/jdk/test/javax/swing/text/View/8080972/TestObjectView.java
new file mode 100644
index 0000000..772447e
--- /dev/null
+++ b/jdk/test/javax/swing/text/View/8080972/TestObjectView.java
@@ -0,0 +1,196 @@
+/*
+ * 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.awt.Color;
+import java.awt.Component;
+import java.util.Enumeration;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.ObjectView;
+/*
+ * @test
+ * @bug 8080972
+ * @summary Audit Core Reflection in module java.desktop for places that will
+ *          require changes to work with modules
+ * @author Alexander Scherbatiy
+ */
+
+public class TestObjectView {
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TestObjectView::testObjectView);
+        System.setSecurityManager(new SecurityManager());
+        SwingUtilities.invokeAndWait(TestObjectView::testObjectView);
+    }
+
+    private static void testObjectView() {
+
+        UserObjectView objectView = new UserObjectView(new UserElement());
+
+        Component comp = objectView.createComponent();
+
+        if (!(comp instanceof UserJComponent)) {
+            throw new RuntimeException("Component is not UserJComponent!");
+        }
+    }
+    public static class UserJComponent extends JComponent {
+
+        public static final Color USER_COLOR = new Color(10, 20, 30);
+        public static final Color TEST_COLOR = new Color(15, 25, 35);
+
+        Color color = USER_COLOR;
+
+        public UserJComponent() {
+
+        }
+
+        public Color getUserColor() {
+            System.out.println("[user component] get user color");
+            return color;
+        }
+
+        public void setUserColor(Color color) {
+            System.out.println("[user component] set user color");
+            this.color = color;
+        }
+
+    }
+
+    public static class UserObjectView extends ObjectView {
+
+        public UserObjectView(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        public Component createComponent() {
+            return super.createComponent();
+        }
+    }
+
+    public static class UserElement implements Element {
+
+        @Override
+        public Document getDocument() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Element getParentElement() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public String getName() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public AttributeSet getAttributes() {
+            return new AttributeSet() {
+
+                @Override
+                public int getAttributeCount() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public boolean isDefined(Object attrName) {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public boolean isEqual(AttributeSet attr) {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public AttributeSet copyAttributes() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public Object getAttribute(Object key) {
+                    if (key.equals(HTML.Attribute.CLASSID)) {
+                        return UserJComponent.class.getName();
+                    }
+
+                    return null;
+                }
+
+                @Override
+                public Enumeration<?> getAttributeNames() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public boolean containsAttribute(Object name, Object value) {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public boolean containsAttributes(AttributeSet attributes) {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+
+                @Override
+                public AttributeSet getResolveParent() {
+                    throw new UnsupportedOperationException("Not supported yet.");
+                }
+            };
+        }
+
+        @Override
+        public int getStartOffset() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public int getEndOffset() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public int getElementIndex(int offset) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public int getElementCount() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Element getElement(int index) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public boolean isLeaf() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+}
diff --git a/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java b/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
index 8d74fd2..daa9451 100644
--- a/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
+++ b/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
@@ -39,6 +39,7 @@
 import com.sun.org.apache.xml.internal.serializer.EncodingInfo;
 import com.sun.org.apache.xml.internal.serializer.Encodings;
 import java.io.InputStreamReader;
+import java.lang.reflect.Module;
 import java.lang.reflect.Method;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
@@ -61,7 +62,8 @@
 
     public static void main(String[] args) throws Exception {
         Properties props = new Properties();
-        try (InputStreamReader is = new InputStreamReader(ClassLoader.getSystemResourceAsStream(ENCODINGS_FILE))) {
+        Module xmlModule = EncodingInfo.class.getModule();
+        try (InputStreamReader is = new InputStreamReader(xmlModule.getResourceAsStream(ENCODINGS_FILE))) {
             props.load(is);
         }
 
@@ -71,7 +73,7 @@
            // Check that the content of the Encodings.properties included in
            // the tested build image matches the content of the file in the source
            // jaxp tree of the jdk forest.
-           throw new RuntimeException("UTF8 key missing in " + ClassLoader.getSystemResource(ENCODINGS_FILE));
+           throw new RuntimeException("UTF8 key missing in " + ENCODINGS_FILE);
        }
 
         //printAllCharsets();
diff --git a/jdk/test/javax/xml/jaxp/common/8035437/run.sh b/jdk/test/javax/xml/jaxp/common/8035437/run.sh
index 413edeb..2ebe7ce 100644
--- a/jdk/test/javax/xml/jaxp/common/8035437/run.sh
+++ b/jdk/test/javax/xml/jaxp/common/8035437/run.sh
@@ -28,17 +28,18 @@
 # @summary Tests that java.lang.AbstractMethodError is not thrown when
 #    serializing improper version of DocumentImpl class.
 
-mkdir -p exec compile
+mkdir -p exec/java.xml compile/java.xml
 
 $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-   -d compile $TESTSRC/Document.java $TESTSRC/Node.java || exit 1
+   -d compile/java.xml -Xmodule:java.xml $TESTSRC/Document.java $TESTSRC/Node.java || exit 1
 
 $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-   -Xbootclasspath/p:compile -d exec $TESTSRC/DocumentImpl.java || exit 1
+   -d exec/java.xml -Xpatch:compile -Xmodule:java.xml $TESTSRC/DocumentImpl.java || exit 2
 
 $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-   $TESTSRC/AbstractMethodErrorTest.java -d exec || exit 1
+   $TESTSRC/AbstractMethodErrorTest.java -d exec || exit 3
 
-$TESTJAVA/bin/java ${TESTVMOPTS} -Xbootclasspath/p:exec -cp exec AbstractMethodErrorTest || exit 1
+$TESTJAVA/bin/java ${TESTVMOPTS} -Xpatch:exec -cp exec AbstractMethodErrorTest || exit 4
 
 exit 0
+
diff --git a/jdk/test/javax/xml/soap/XmlTest.java b/jdk/test/javax/xml/soap/XmlTest.java
new file mode 100644
index 0000000..fedd52d
--- /dev/null
+++ b/jdk/test/javax/xml/soap/XmlTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 javax.xml.soap.AttachmentPart;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.Name;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.transform.stream.StreamSource;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+
+/*
+ * @test
+ * @summary tests JAF DataHandler can be instantiated; test serialize and
+ *   deserialize SOAP message containing xml attachment
+ */
+public class XmlTest {
+
+    public void test() throws Exception {
+
+        File file = new File("message.xml");
+        file.deleteOnExit();
+
+        MessageFactory mf = MessageFactory.newInstance();
+        SOAPMessage msg = createMessage(mf);
+
+        // Save the soap message to file
+        try (FileOutputStream sentFile = new FileOutputStream(file)) {
+            msg.writeTo(sentFile);
+        }
+
+        // See if we get the image object back
+        try (FileInputStream fin = new FileInputStream(file)) {
+            SOAPMessage newMsg = mf.createMessage(msg.getMimeHeaders(), fin);
+
+            newMsg.writeTo(new ByteArrayOutputStream());
+
+            Iterator<?> i = newMsg.getAttachments();
+            while (i.hasNext()) {
+                AttachmentPart att = (AttachmentPart) i.next();
+                Object obj = att.getContent();
+                if (!(obj instanceof StreamSource)) {
+                    fail("Got incorrect attachment type [" + obj.getClass() + "], " +
+                         "expected [javax.xml.transform.stream.StreamSource]");
+                }
+            }
+        }
+
+    }
+
+    private SOAPMessage createMessage(MessageFactory mf) throws SOAPException, IOException {
+        SOAPMessage msg = mf.createMessage();
+        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
+        Name name = envelope.createName("hello", "ex", "http://example.com");
+        envelope.getBody().addChildElement(name).addTextNode("THERE!");
+
+        String s = "<root><hello>THERE!</hello></root>";
+
+        AttachmentPart ap = msg.createAttachmentPart(
+                new StreamSource(new ByteArrayInputStream(s.getBytes())),
+                "text/xml"
+        );
+        msg.addAttachmentPart(ap);
+        msg.saveChanges();
+
+        return msg;
+    }
+
+    private void fail(String s) {
+        throw new RuntimeException(s);
+    }
+
+    public static void main(String[] args) throws Exception {
+        new XmlTest().test();
+    }
+
+}
diff --git a/jdk/test/jdk/asm/AsmSanity.java b/jdk/test/jdk/asm/AsmSanity.java
index 0ae1cad..8f9cc3c 100644
--- a/jdk/test/jdk/asm/AsmSanity.java
+++ b/jdk/test/jdk/asm/AsmSanity.java
@@ -32,7 +32,7 @@
  * - Verify that if user code is compiled without ct.sym, it can't access asm classes
  *   at runtime when a security manager is in use.
  *
- * @compile/fail AsmSanity.java
+ * @modules java.base/jdk.internal.org.objectweb.asm
  *
  * @compile -XDignore.symbol.file=true AsmSanity.java
  * @run main/othervm AsmSanity
@@ -44,11 +44,6 @@
 
 // Verify that the expected asm pkgs are present
 import jdk.internal.org.objectweb.asm.*;
-import jdk.internal.org.objectweb.asm.commons.*;
-import jdk.internal.org.objectweb.asm.signature.*;
-import jdk.internal.org.objectweb.asm.tree.*;
-import jdk.internal.org.objectweb.asm.tree.analysis.*;
-import jdk.internal.org.objectweb.asm.util.*;
 
 // Verify that we can actually run some of the asm code.
 public class AsmSanity {
diff --git a/jdk/test/jdk/internal/jimage/ExecutableTest.java b/jdk/test/jdk/internal/jimage/ExecutableTest.java
deleted file mode 100644
index b65230b..0000000
--- a/jdk/test/jdk/internal/jimage/ExecutableTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2015 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.PosixFilePermission;
-import static java.nio.file.attribute.PosixFilePermission.*;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-
-/*
- * @test
- * @bug 8132475
- * @summary Check that the executables in the current JDK image
- *          are executable by all users.
- * @run main ExecutableTest
- * @author Volker Simonis
- */
-
-public class ExecutableTest {
-
-    // The bin/ directory may contain non-executable files (see 8132704)
-    private static final String[] exclude = { "jmc.ini" };
-    private static final Set<String> excludeSet =
-        new HashSet<String>(Arrays.asList(exclude));
-
-    public static void main(String args[]) throws Throwable {
-        String JAVA_HOME = System.getProperty("java.home");
-        Path binPath = Paths.get(JAVA_HOME, "bin");
-        DirectoryStream<Path> stream = Files.newDirectoryStream(binPath);
-        EnumSet<PosixFilePermission> execPerms =
-            EnumSet.of(GROUP_EXECUTE, OTHERS_EXECUTE, OWNER_EXECUTE);
-        for (Path entry : stream) {
-            if (excludeSet.contains(entry.getFileName().toString())) continue;
-            if (Files.isRegularFile(entry)) {
-                if (!Files.isExecutable(entry)) {
-                    throw new Error(entry + " is not executable!");
-                }
-                try {
-                    Set<PosixFilePermission> perm = Files.getPosixFilePermissions(entry);
-                    if (!perm.containsAll(execPerms)) {
-                        throw new Error(entry + " has not all executable permissions!\n" +
-                                        "Should have: " + execPerms + "\nbut has: " + perm);
-                    }
-                } catch (UnsupportedOperationException e) {}
-            }
-        }
-    }
-}
diff --git a/jdk/test/jdk/internal/jimage/JImageReadTest.java b/jdk/test/jdk/internal/jimage/JImageReadTest.java
index b840d14..feb31a5 100644
--- a/jdk/test/jdk/internal/jimage/JImageReadTest.java
+++ b/jdk/test/jdk/internal/jimage/JImageReadTest.java
@@ -23,20 +23,23 @@
 
 /*
  * @test
- * @modules java.base/jdk.internal.jimage
- * @run testng JImageReadTest
  * @summary Unit test for libjimage JIMAGE_Open/Read/Close
+ * @modules java.base/jdk.internal.jimage
  */
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 
 import jdk.internal.jimage.BasicImageReader;
-import jdk.internal.jimage.ImageNativeSubstrate;
+import jdk.internal.jimage.ImageReader;
+import jdk.internal.jimage.ImageLocation;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Optional;
@@ -49,9 +52,7 @@
 public class JImageReadTest {
 
     static String javaHome = System.getProperty("java.home");
-    static String imageFile = javaHome + File.separator + "lib"
-            + File.separator + "modules" + File.separator
-            + "bootmodules.jimage";
+    static Path imageFile = Paths.get(javaHome, "lib", "modules");
 
     @DataProvider(name="classes")
     static Object[][] loadClasses() {
@@ -66,16 +67,6 @@
         };
     }
 
-
-    @DataProvider(name="packages")
-    static Object[][] loadPackages() {
-        return new Object[][] {
-                {"java.base", "java/lang"},
-                {"java.base", "java/io"},
-                {"java.logging", "java/util/logging"},
-        };
-    }
-
     /**
      * Test a class is correctly accessible from the image in a module.
      *
@@ -86,60 +77,46 @@
     @Test(dataProvider="classes")
     public static void test1_ReadClasses(String moduleName, String className) throws Exception {
         final int classMagic = 0xCAFEBABE;
-        final long NOT_FOUND = 0L;
 
-        if (!(new File(imageFile)).exists()) {
+        if (!Files.exists(imageFile)) {
             System.out.printf("Test skipped; no jimage file");
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertTrue(reader != null, "JIMAGE_Open failed: " + imageFile);
 
-        long[] sizeArray = new long[1];
-        long locationHandle =
-                ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle,
-                moduleName, "9.0", className, sizeArray);
-        long size = sizeArray[0];
-        System.out.printf("reading: module: %s, path: %s, handle: %16x, " +
-                        "location: %d, size: %d%n",
-                moduleName, className, jimageHandle, locationHandle, size);
+        ImageLocation location = reader.findLocation(moduleName, className);
+
+        if (location != null && !location.verify("/" + moduleName + "/" + className)) {
+            location = null;
+        }
+
+        long size = location != null ? location.getUncompressedSize() : 0;
+
+        System.out.printf("reading: module: %s, path: %s, size: %d%n",
+                moduleName, className, size);
         if (moduleName.contains("NOSUCH") || className.contains("NOSUCH")) {
-            Assert.assertEquals(locationHandle, NOT_FOUND,
+            Assert.assertTrue(location == null,
                     "location found for non-existing module: "
                     + moduleName
                     + ", or class: " + className);
             return;         // no more to test for non-existing class
         } else {
-            Assert.assertTrue(locationHandle != NOT_FOUND, "location not found: " + className);
+            Assert.assertTrue(location != null, "location not found: " + className);
             Assert.assertTrue(size > 0, "size of should be > 0: " + className);
         }
 
         // positive: read whole class
-        ByteBuffer buffer = ByteBuffer.allocate((int)size);
-        long actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle,
-                locationHandle, buffer.array(), size);
-        Assert.assertEquals(actual, size, "bytes read not equal bytes requested");
+        ByteBuffer buffer = reader.getResourceBuffer(location);
+        Assert.assertTrue(buffer != null, "bytes read not equal bytes requested");
 
         if (className.endsWith(".class")) {
             int m = buffer.getInt();
             Assert.assertEquals(m, classMagic, "Classfile has bad magic number");
         }
 
-        // Read less than the size of the artifact
-        buffer.rewind();
-        Arrays.fill(buffer.array(), (byte)0xc0);
-        long sizeExpected = size - 10;
-        actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle,
-                locationHandle, buffer.array(), sizeExpected);
-        Assert.assertEquals(actual, sizeExpected, "bytes read not equal bytes requested");
-
-        if (className.endsWith(".class")) {
-            int m1 = buffer.getInt();
-            Assert.assertEquals(m1, classMagic, "Read operation succeeded but has bad magic number");
-        }
-
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
     /**
@@ -149,63 +126,37 @@
      */
     @Test
     static void test2_ImageResources() throws IOException {
-        if (!(new File(imageFile)).exists()) {
+        if (!Files.exists(imageFile)) {
             System.out.printf("Test skipped; no jimage file");
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertTrue(reader != null, "JIMAGE_Open failed: " + imageFile);
 
-        String[] names = new String[4096];
-        int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle,
-                names);
+        String[] names = reader.getEntryNames();
 
         // Repeat with count available
-        names = new String[max + 1];
-        int count = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle,
-                names);
+        int count = names.length;
+
         System.out.printf(" count: %d, a class: %s\n", count, names[0]);
+
         int minEntryCount = 16000;
-        Assert.assertTrue(max > minEntryCount,
-                "missing entries, should be more than " + minEntryCount +
-                ", reported: " + count);
-        Assert.assertTrue(count == max,
+        Assert.assertTrue(minEntryCount < count,
                 "unexpected count of entries, count: " + count
-                        + ", max: " + max);
+                        + ", min: " + minEntryCount);
         for (int i = 0; i < count; i++) {
             checkFullName(names[i]);
         }
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
-    /**
-     * Tests that a package exists and correctly mapped to the module.
-     *
-     * @param moduleName the module name
-     * @param packageName the package name
-     * @throws IOException thrown if an error occurs
-     */
-    @Test(dataProvider="packages")
-    static void test3_PackageToModule(String moduleName, String packageName) throws IOException {
-        if (!(new File(imageFile)).exists()) {
-            System.out.printf("Test skipped; no jimage file");
+    static void checkFullName(String path) {
+        if (path.startsWith("/packages") || path.startsWith("/modules")) {
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
-
-        String result = ImageNativeSubstrate.JIMAGE_PackageToModule(jimageHandle, packageName);
-        System.out.printf(" package: %s, module: %s%n", packageName, result);
-        Assert.assertEquals(result, moduleName, "wrong module for package: " + packageName);
-
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
-    }
-
-
-    static void checkFullName(String path) {
         int next = 0;
         String m = null;
         String p = null;
@@ -241,8 +192,8 @@
      * from the BasicImageReader they are ignored.
      */
     @Test
-    static void test4_verifyNames() {
-        if (!(new File(imageFile)).exists()) {
+    static void test3_verifyNames() {
+        if (!Files.exists(imageFile)) {
             System.out.printf("Test skipped; no jimage file");
             return;
         }
@@ -271,9 +222,6 @@
             System.out.printf("native name count: %d, modCount: %d, pkgCount: %d, otherCount: %d%n",
                     names.length, modCount, pkgCount, otherCount);
 
-            Assert.assertEquals(modCount, 0, "JIMAGE_ResourceIterator should not return any '/modules' paths");
-            Assert.assertEquals(pkgCount, 0, "JIMAGE_ResourceIterator should not return any '/packages' paths");
-
             // Sort and merge the two arrays.  Every name should appear exactly twice.
             Arrays.sort(names);
             Arrays.sort(nativeNames);
@@ -336,21 +284,13 @@
      */
     static String[] JIMAGE_Names() throws IOException {
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertNotNull(reader, "JIMAGE_Open failed: " + imageFile);
 
-        String[] names = new String[50000];
-        int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names);
+        String[] names = reader.getEntryNames();
 
-        if (max > names.length) {
-            // Not all names fit, repeat with correct size
-            names = new String[max];
-            max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names);
-        } else {
-            names = Arrays.copyOf(names, max);
-        }
+        reader.close();
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
         return names;
     }
 
@@ -366,24 +306,55 @@
         System.out.printf(" %s: %d names%n", fname, names.length);
     }
 
-    @Test
-    static void test5_nameTooLong() throws IOException {
+    //@Test
+    static void test4_nameTooLong() throws IOException {
         long[] size = new long[1];
         String moduleName = "FictiousModuleName";
         String className = String.format("A%09999d", 1);
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertNotNull(reader, "JIMAGE_Open failed: " + imageFile);
 
-        long locationHandle =
-                ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle,
-                        moduleName, "9.0", className, size);
+        String name = "/" + moduleName + "/" + className;
+        ImageLocation location = reader.findLocation(name);
 
-        Assert.assertEquals(0, locationHandle, "Too long name should have failed");
+        if (location != null && !location.verify(name)) {
+            location = null;
+        }
+        Assert.assertTrue(location == null, "Too long name should have failed");
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
+    /**
+     * Verify that the ImageReader returned by ImageReader.open has the
+     * the requested endianness or fails with an IOException if not.
+     */
+    @Test
+    static void test5_imageReaderEndianness() throws IOException {
+        ImageReader nativeReader = ImageReader.open(imageFile);
+        Assert.assertEquals(nativeReader.getByteOrder(), ByteOrder.nativeOrder());
+
+        try {
+            ImageReader leReader = ImageReader.open(imageFile, ByteOrder.LITTLE_ENDIAN);
+            Assert.assertEquals(leReader.getByteOrder(), ByteOrder.LITTLE_ENDIAN);
+            leReader.close();
+        } catch (IOException io) {
+            // IOException expected if LITTLE_ENDIAN not the nativeOrder()
+            Assert.assertNotEquals(ByteOrder.nativeOrder(), ByteOrder.LITTLE_ENDIAN);
+        }
+
+        try {
+            ImageReader beReader = ImageReader.open(imageFile, ByteOrder.BIG_ENDIAN);
+            Assert.assertEquals(beReader.getByteOrder(), ByteOrder.BIG_ENDIAN);
+            beReader.close();
+        } catch (IOException io) {
+            // IOException expected if LITTLE_ENDIAN not the nativeOrder()
+            Assert.assertNotEquals(ByteOrder.nativeOrder(), ByteOrder.BIG_ENDIAN);
+        }
+
+        nativeReader.close();
+    }
     // main method to run standalone from jtreg
 
     @Test(enabled=false)
diff --git a/jdk/test/jdk/internal/jimage/JImageTest.java b/jdk/test/jdk/internal/jimage/JImageTest.java
deleted file mode 100644
index 2e7ec73..0000000
--- a/jdk/test/jdk/internal/jimage/JImageTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/*
- * @test
- * @library /lib/testlibrary
- * @build jdk.testlibrary.*
- * @summary Test to see if jimage tool extracts and recreates correctly.
- * @run main/timeout=360 JImageTest
- */
-
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import jdk.testlibrary.ProcessTools;
-
-
-/**
- * Basic test for jimage tool.
- */
-public class JImageTest {
-    private static void jimage(String... jimageArgs) throws Exception {
-        ArrayList<String> args = new ArrayList<>();
-        args.add("-ms8m");
-        args.add("jdk.tools.jimage.Main");
-        args.addAll(Arrays.asList(jimageArgs));
-
-        ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
-        int res = builder.inheritIO().start().waitFor();
-
-        if (res != 0) {
-            throw new RuntimeException("JImageTest tool FAILED");
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        final String JAVA_HOME = System.getProperty("java.home");
-        Path jimagePath = Paths.get(JAVA_HOME, "bin", "jimage");
-        Path bootimagePath = Paths.get(JAVA_HOME, "lib", "modules", "bootmodules.jimage");
-
-        if (Files.exists(jimagePath) && Files.exists(bootimagePath)) {
-            String jimage = jimagePath.toAbsolutePath().toString();
-            String bootimage = bootimagePath.toAbsolutePath().toString();
-            String extractDir = Paths.get(".", "extract").toAbsolutePath().toString();
-            String recreateImage = Paths.get(".", "recreate.jimage").toAbsolutePath().toString();
-            String relativeRecreateImage = Paths.get(".", "recreate2.jimage").toString();
-            jimage("extract", "--dir", extractDir, bootimage);
-            jimage("recreate", "--dir", extractDir, recreateImage);
-            jimage("recreate", "--dir", extractDir, relativeRecreateImage);
-
-            System.out.println("Test successful");
-         } else {
-            System.out.println("Test skipped, no module image");
-         }
-
-    }
-}
diff --git a/jdk/test/jdk/internal/jimage/TEST.properties b/jdk/test/jdk/internal/jimage/TEST.properties
new file mode 100644
index 0000000..db4e960
--- /dev/null
+++ b/jdk/test/jdk/internal/jimage/TEST.properties
@@ -0,0 +1,7 @@
+# This file identifies root(s) of the test-ng hierarchy.
+
+TestNG.dirs = .
+
+modules=java.base/jdk.internal.jimage
+
+javatest.maxOutputSize = 2500000
diff --git a/jdk/test/jdk/internal/jimage/VerifyJimage.java b/jdk/test/jdk/internal/jimage/VerifyJimage.java
deleted file mode 100644
index 406b1fb..0000000
--- a/jdk/test/jdk/internal/jimage/VerifyJimage.java
+++ /dev/null
@@ -1,240 +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.
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.DirectoryStream;
-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.Deque;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import jdk.internal.jimage.BasicImageReader;
-import jdk.internal.jimage.ImageLocation;
-
-/*
- * @test
- * @summary Verify jimage
- * @modules java.base/jdk.internal.jimage
- * @run main/othervm VerifyJimage
- */
-
-/**
- * This test runs in two modes:
- * (1) No argument: it verifies the jimage by loading all classes in the runtime
- * (2) path of exploded modules: it compares bytes of each file in the exploded
- *     module with the entry in jimage
- *
- * FIXME: exception thrown when findLocation from jimage by multiple threads
- * -Djdk.test.threads=<n> to specify the number of threads.
- */
-public class VerifyJimage {
-    private static final Deque<String> failed = new ConcurrentLinkedDeque<>();
-
-    public static void main(String... args) throws Exception {
-        long start = System.nanoTime();
-        int numThreads = Integer.getInteger("jdk.test.threads", 1);
-        List<JImageReader> readers = newJImageReaders();
-        VerifyJimage verify = new VerifyJimage(readers, numThreads);
-        if (args.length == 0) {
-            // load classes from jimage
-            verify.loadClasses();
-        } else {
-            Path dir = Paths.get(args[0]);
-            if (Files.notExists(dir) || !Files.isDirectory(dir)) {
-                throw new RuntimeException("Invalid argument: " + dir);
-            }
-            verify.compareExplodedModules(dir);
-        }
-        verify.waitForCompletion();
-        long end = System.nanoTime();
-        int entries = readers.stream()
-                             .mapToInt(JImageReader::entries)
-                             .sum();
-        System.out.format("%d entries %d files verified: %d ms %d errors%n",
-                          entries, verify.count.get(),
-                          TimeUnit.NANOSECONDS.toMillis(end - start), failed.size());
-        for (String f : failed) {
-            System.err.println(f);
-        }
-    }
-
-    private final AtomicInteger count = new AtomicInteger(0);
-    private final List<JImageReader> readers;
-    private final ExecutorService pool;
-
-    VerifyJimage(List<JImageReader> readers, int numThreads) {
-        this.readers = readers;
-        this.pool = Executors.newFixedThreadPool(numThreads);
-    }
-
-    private void waitForCompletion() throws InterruptedException {
-        pool.shutdown();
-        pool.awaitTermination(20, TimeUnit.SECONDS);
-    }
-
-    private void compareExplodedModules(Path dir) throws IOException {
-        System.out.println("comparing jimage with " + dir);
-
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
-            for (Path mdir : stream) {
-                if (Files.isDirectory(mdir)) {
-                    pool.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                Files.find(mdir, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
-                                           -> !Files.isDirectory(p) &&
-                                              !mdir.relativize(p).toString().startsWith("_") &&
-                                              !p.getFileName().toString().equals("MANIFEST.MF"))
-                                     .forEach(p -> compare(mdir, p, readers));
-                            } catch (IOException e) {
-                                throw new UncheckedIOException(e);
-                            }
-                        }
-                    });
-                }
-            }
-        }
-    }
-
-    private final List<String> BOOT_RESOURCES = Arrays.asList(
-        "java.base/META-INF/services/java.nio.file.spi.FileSystemProvider"
-    );
-    private final List<String> EXT_RESOURCES = Arrays.asList(
-        "jdk.zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider"
-    );
-    private final List<String> APP_RESOURCES = Arrays.asList(
-        "jdk.hotspot.agent/META-INF/services/com.sun.jdi.connect.Connector",
-        "jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector"
-    );
-
-    private void compare(Path mdir, Path p, List<JImageReader> readers) {
-        String entry = mdir.relativize(p).toString().replace(File.separatorChar, '/');
-
-        count.incrementAndGet();
-        String file = mdir.getFileName().toString() + "/" + entry;
-        if (APP_RESOURCES.contains(file)) {
-            // skip until the service config file is merged
-            System.out.println("Skipped " + file);
-            return;
-        }
-
-        String jimage;
-        if (BOOT_RESOURCES.contains(file)) {
-            jimage = "bootmodules.jimage";
-        } else if (EXT_RESOURCES.contains(file)) {
-            jimage = "extmodules.jimage";
-        } else {
-            jimage = "";
-        }
-        JImageReader reader = readers.stream()
-                .filter(r -> r.findLocation(entry) != null)
-                .filter(r -> jimage.isEmpty() || r.imageName().equals(jimage))
-                .findFirst().orElse(null);
-        if (reader == null) {
-            failed.add(entry + " not found: " + p.getFileName().toString());
-        } else {
-            reader.compare(entry, p);
-        }
-    }
-
-    private void loadClasses() {
-        ClassLoader loader = ClassLoader.getSystemClassLoader();
-        for (JImageReader reader : readers) {
-            Arrays.stream(reader.getEntryNames())
-                    .filter(n -> n.endsWith(".class"))
-                    .forEach(n -> {
-                        String cn = n.substring(0, n.length()-6).replace('/', '.');
-                        count.incrementAndGet();
-                        try {
-                            Class.forName(cn, false, loader);
-                        } catch (ClassNotFoundException e) {
-                            failed.add(reader.imageName() + ": " + cn + " not found");
-                        }
-                    });
-        }
-    }
-
-
-   private static List<JImageReader> newJImageReaders() throws IOException {
-        String home = System.getProperty("java.home");
-        Path mlib = Paths.get(home, "lib", "modules");
-        try (Stream<Path> paths = Files.list(mlib)) {
-            Set<Path> jimages = paths.filter(p -> p.toString().endsWith(".jimage"))
-                                     .collect(Collectors.toSet());
-            List<JImageReader> result = new ArrayList<>();
-            for (Path jimage: jimages) {
-                result.add(new JImageReader(jimage));
-                System.out.println("opened " + jimage);
-            }
-            return result;
-        }
-    }
-
-    static class JImageReader extends BasicImageReader {
-        final Path jimage;
-        JImageReader(Path p) throws IOException {
-            super(p.toString());
-            this.jimage = p;
-        }
-
-        String imageName() {
-            return jimage.getFileName().toString();
-        }
-
-        int entries() {
-            try {
-                return getHeader().getTableLength();
-            } catch (IOException ex) {
-                failed.add(imageName() + ": can't access header");
-                return 0;
-            }
-        }
-
-        void compare(String entry, Path p) {
-            try {
-                byte[] bytes = Files.readAllBytes(p);
-                byte[] imagebytes = getResource(entry);
-                if (!Arrays.equals(bytes, imagebytes)) {
-                    failed.add(imageName() + ": bytes differs than " + p.toString());
-                }
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        }
-    }
-}
diff --git a/jdk/test/jdk/internal/jrtfs/Basic.java b/jdk/test/jdk/internal/jrtfs/Basic.java
index 5b99a5c..0af30c5 100644
--- a/jdk/test/jdk/internal/jrtfs/Basic.java
+++ b/jdk/test/jdk/internal/jrtfs/Basic.java
@@ -28,8 +28,10 @@
  */
 
 import java.io.InputStream;
+import java.io.IOException;
 import java.io.DataInputStream;
 import java.nio.file.DirectoryStream;
+import java.nio.file.InvalidPathException;
 import java.nio.file.Files;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
@@ -38,16 +40,20 @@
 import java.nio.file.Paths;
 import java.net.URI;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.stream.Stream;
 
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.assertFalse;
 
@@ -57,6 +63,34 @@
 
 public class Basic {
 
+    private FileSystem theFileSystem;
+    private FileSystem fs;
+
+    @BeforeClass
+    public void setup() {
+        try {
+            theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
+            Map<String, String> env = new HashMap<>();
+            // set java.home property to be underlying java.home
+            // so that jrt-fs.jar loading is exercised.
+            env.put("java.home", System.getProperty("java.home"));
+            fs = FileSystems.newFileSystem(URI.create("jrt:/"), env);
+        } catch (IOException ioExp) {
+            throw new RuntimeException(ioExp);
+        }
+    }
+
+    @AfterClass
+    public void tearDown() {
+        try {
+            fs.close();
+        } catch (Exception ignored) {}
+    }
+
+    private FileSystem selectFileSystem(boolean theDefault) {
+        return theDefault? theFileSystem : fs;
+    }
+
     // Checks that the given FileSystem is a jrt file system.
     private void checkFileSystem(FileSystem fs) {
         assertTrue(fs.provider().getScheme().equalsIgnoreCase("jrt"));
@@ -95,17 +129,32 @@
         }
     }
 
+    @Test
+    public void testNewFileSystemWithJavaHome() throws Exception {
+        Map<String, String> env = new HashMap<>();
+        // set java.home property to be underlying java.home
+        // so that jrt-fs.jar loading is exercised.
+        env.put("java.home", System.getProperty("java.home"));
+        try (FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), env)) {
+            checkFileSystem(fs);
+            // jrt-fs.jar classes are loaded by another (non-boot) loader in this case
+            assertNotNull(fs.provider().getClass().getClassLoader());
+        }
+    }
+
     @DataProvider(name = "knownClassFiles")
     private Object[][] knownClassFiles() {
         return new Object[][] {
-            { "/modules/java.base/java/lang/Object.class" },
-            { "modules/java.base/java/lang/Object.class" },
+            { "/modules/java.base/java/lang/Object.class", true },
+            { "modules/java.base/java/lang/Object.class", true },
+            { "/modules/java.base/java/lang/Object.class", false },
+            { "modules/java.base/java/lang/Object.class", false },
         };
     }
 
     @Test(dataProvider = "knownClassFiles")
-    public void testKnownClassFiles(String path) throws Exception {
-        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+    public void testKnownClassFiles(String path, boolean theDefault) throws Exception {
+        FileSystem fs = selectFileSystem(theDefault);
         Path classFile = fs.getPath(path);
 
         assertTrue(Files.isRegularFile(classFile));
@@ -121,25 +170,38 @@
     @DataProvider(name = "knownDirectories")
     private Object[][] knownDirectories() {
         return new Object[][] {
-            { "/"                     },
-            { "."                     },
-            { "./"                    },
-            { "/."                    },
-            { "/./"                   },
-            { "/modules/java.base/.."         },
-            { "/modules/java.base/../"        },
-            { "/modules/java.base/../."       },
-            { "/modules/java.base"            },
-            { "/modules/java.base/java/lang"  },
-            { "modules/java.base/java/lang"   },
-            { "/modules/java.base/java/lang/" },
-            { "modules/java.base/java/lang/"  }
+            { "/", true                     },
+            { "." , true                    },
+            { "./", true                    },
+            { "/.", true                    },
+            { "/./", true                   },
+            { "/modules/java.base/..", true         },
+            { "/modules/java.base/../", true        },
+            { "/modules/java.base/../.", true       },
+            { "/modules/java.base", true            },
+            { "/modules/java.base/java/lang", true  },
+            { "modules/java.base/java/lang", true   },
+            { "/modules/java.base/java/lang/", true },
+            { "modules/java.base/java/lang/", true  },
+            { "/", false                     },
+            { "." , false                    },
+            { "./", false                    },
+            { "/.", false                    },
+            { "/./", false                   },
+            { "/modules/java.base/..", false         },
+            { "/modules/java.base/../", false        },
+            { "/modules/java.base/../.", false       },
+            { "/modules/java.base", false            },
+            { "/modules/java.base/java/lang", false  },
+            { "modules/java.base/java/lang", false   },
+            { "/modules/java.base/java/lang/", false },
+            { "modules/java.base/java/lang/", false  },
         };
     }
 
     @Test(dataProvider = "knownDirectories")
-    public void testKnownDirectories(String path) throws Exception {
-        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+    public void testKnownDirectories(String path, boolean theDefault) throws Exception {
+        FileSystem fs = selectFileSystem(theDefault);
         Path dir = fs.getPath(path);
 
         assertTrue(Files.isDirectory(dir));
@@ -383,6 +445,8 @@
             { "/modules/java.base/packages.offsets" },
             { "/modules/java.instrument/packages.offsets" },
             { "/modules/jdk.zipfs/packages.offsets" },
+            { "/modules/java.base/_the.java.base.vardeps" },
+            { "/modules/java.base/_the.java.base_batch" },
             { "/java/lang" },
             { "/java/util" },
         };
@@ -568,48 +632,55 @@
     }
 
     @Test
-    public void testPackagesSubDirList() throws Exception {
+    public void invalidPathTest() {
         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        String pathName = "/packages/javax.annotation";
-        Path path = fs.getPath(pathName);
-        boolean seenJavaCompiler = false, seenAnnotationsCommon = false;
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
-            for (Path p : stream) {
-               String str = p.toString();
-               if (str.equals(pathName + "/java.compiler")) {
-                   seenJavaCompiler = true;
-               } else if (str.equals(pathName + "/java.annotations.common")) {
-                   seenAnnotationsCommon = true;
-               }
-            }
+        InvalidPathException ipe = null;
+        try {
+            boolean res = Files.exists(fs.getPath("/packages/\ud834\udd7b"));
+            assertFalse(res);
+            return;
+        } catch (InvalidPathException e) {
+            ipe = e;
         }
-        assertTrue(seenJavaCompiler);
-        assertTrue(seenAnnotationsCommon);
+        assertTrue(ipe != null);
     }
 
-    @Test
-    public void testRootDirList() throws Exception {
+    @DataProvider(name="packagesLinkedDirs")
+    private Object[][] packagesLinkedDirs() {
+        return new Object[][] {
+            { "/packages/java.lang/java.base/java/lang/ref"             },
+            { "/./packages/java.lang/java.base/java/lang/ref"           },
+            { "packages/java.lang/java.base/java/lang/ref"              },
+            { "/packages/../packages/java.lang/java.base/java/lang/ref" },
+            { "/packages/java.lang/java.base/java/util/zip"             },
+            { "/./packages/java.lang/java.base/java/util/zip"           },
+            { "packages/java.lang/java.base/java/util/zip"              },
+            { "/packages/../packages/java.lang/java.base/java/util/zip" },
+            { "/packages/com.oracle/java.xml.ws/com"                    },
+            { "/./packages/com.oracle/java.xml.ws/com"                  },
+            { "packages/com.oracle/java.xml.ws/com"                     },
+            { "/packages/../packages/com.oracle/java.xml.ws/com"        }
+        };
+    }
+
+    // @bug 8141521: jrt file system's DirectoryStream reports child paths
+    // with wrong paths for directories under /packages
+    @Test(dataProvider = "packagesLinkedDirs")
+    public void dirStreamPackagesDirTest(String dirName) throws IOException {
         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        Path path = fs.getPath("/");
-        // check /packages and /modules are not repeated
-        // and seen once.
-        boolean packages = false, modules = false;
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
-            for (Path p : stream) {
-                String str = p.toString();
-                switch (str) {
-                    case "/packages":
-                        assertFalse(packages, "/packages repeated");
-                        packages = true;
-                        break;
-                    case "/modules":
-                        assertFalse(modules, "/modules repeated");
-                        modules = true;
-                        break;
+        Path path = fs.getPath(dirName);
+
+        int childCount = 0, dirPrefixOkayCount = 0;
+        try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(path)) {
+            for (Path child : dirStream) {
+                childCount++;
+                if (child.toString().startsWith(dirName)) {
+                    dirPrefixOkayCount++;
                 }
             }
         }
-        assertTrue(packages, "/packages missing in / list!");
-        assertTrue(modules, "/modules missing in / list!");
+
+        assertTrue(childCount != 0);
+        assertEquals(dirPrefixOkayCount, childCount);
     }
 }
diff --git a/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java b/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java
index 994cee3..a4296ec 100644
--- a/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java
+++ b/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 4954921 8009259
  * @library /test/lib/share/classes
+ * @modules java.base/jdk.internal.ref
  * @build jdk.test.lib.*
  * @build jdk.test.lib.process.*
  * @run main ExitOnThrow
diff --git a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java
new file mode 100644
index 0000000..6594a5c
--- /dev/null
+++ b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Verify the defining class loader of each module never delegates
+ *          to its child class loader. Also sanity check java.compact2
+ *          requires.
+ * @run testng VerifyModuleDelegation
+ */
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Layer;
+import java.util.Set;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+import org.testng.annotations.*;
+
+import static org.testng.Assert.*;
+
+public class VerifyModuleDelegation {
+    private static final String JAVA_BASE = "java.base";
+    private static final String JAVA_COMPACT1 = "java.compact1";
+    private static final String JAVA_COMPACT2 = "java.compact2";
+
+    private static final ModuleDescriptor BASE
+        = new ModuleDescriptor.Builder(JAVA_BASE).build();
+
+    private static final ModuleDescriptor COMPACT2
+        = new ModuleDescriptor.Builder(JAVA_COMPACT2)
+            .requires(MANDATED, JAVA_BASE)
+            .requires(PUBLIC, JAVA_COMPACT1)
+            .requires(PUBLIC, "java.rmi")
+            .requires(PUBLIC, "java.sql")
+            .requires(PUBLIC, "java.xml")
+            .build();
+
+    private static final Set<ModuleReference> MREFS
+            = ModuleFinder.ofSystem().findAll();
+
+    private void check(ModuleDescriptor md, ModuleDescriptor ref) {
+        assertTrue(md.requires().size() == ref.requires().size());
+        assertTrue(md.requires().containsAll(ref.requires()));
+    }
+
+    @Test
+    public void checkJavaBase() {
+        ModuleDescriptor md =
+                MREFS.stream().map(ModuleReference::descriptor)
+                     .filter(d -> d.name().equals(JAVA_BASE))
+                     .findFirst().orElseThrow(Error::new);
+
+        check(md, BASE);
+    }
+    @Test
+    public void checkCompact2() {
+        ModuleDescriptor md =
+                MREFS.stream().map(ModuleReference::descriptor)
+                     .filter(d -> d.name().equals(JAVA_COMPACT2))
+                     .findFirst().orElseThrow(Error::new);
+        check(md, COMPACT2);
+    }
+
+    @Test
+    public void checkLoaderDelegation() {
+        Layer boot = Layer.boot();
+        MREFS.stream().map(ModuleReference::descriptor)
+             .forEach(md -> md.requires().stream().forEach(req ->
+                 {
+                     // check if M requires D and D's loader must be either the
+                     // same or an ancestor of M's loader
+                     ClassLoader loader1 = boot.findLoader(md.name());
+                     ClassLoader loader2 = boot.findLoader(req.name());
+                     if (loader1 != loader2 && !isAncestor(loader2, loader1)) {
+                         throw new Error(md.name() + " can't delegate to " +
+                                         "find classes from " + req.name());
+                     }
+                 }));
+    }
+
+    // Returns true if p is an ancestor of cl i.e. class loader 'p' can
+    // be found in the cl's delegation chain
+    private static boolean isAncestor(ClassLoader p, ClassLoader cl) {
+        if (p != null && cl == null) {
+            return false;
+        }
+        ClassLoader acl = cl;
+        do {
+            acl = acl.getParent();
+            if (p == acl) {
+                return true;
+            }
+        } while (acl != null);
+        return false;
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java b/jdk/test/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java
new file mode 100644
index 0000000..4d1ebcf
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/RunWithAutomaticModules.java
@@ -0,0 +1,180 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build RunWithAutomaticModules CompilerUtils JarUtils
+ *        jdk.testlibrary.ProcessTools
+ * @run testng RunWithAutomaticModules
+ * @summary Runs tests that make use of automatic modules
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class RunWithAutomaticModules {
+
+    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");
+
+    /**
+     * Basic test that consists of 3 modules:
+     *
+     * basictest - the test itself
+     * httpserver - a JAR file (automatic module) with a dummy HTTP server
+     * logging - a JAR file (automatic module) with a dummy logging library
+     *
+     * The test runs the dummy HTTP server and checks that has the expected
+     * reads and exported packages.
+     *
+     * The HTTP server uses the logging library.
+     */
+
+    public void testBasic() throws Exception {
+        boolean compiled;
+
+        Path loggingSrc = SRC_DIR.resolve("logging");
+        Path loggingClasses = CLASSES_DIR.resolve("logging");
+
+        Path httpServerSrc = SRC_DIR.resolve("httpserver");
+        Path httpServerClasses = CLASSES_DIR.resolve("httpserver");
+
+        String testModule = "basictest";
+        String mainClass = "test.Main";
+
+
+        // compile + create mods/logging-1.0.jar
+
+        compiled = CompilerUtils.compile(loggingSrc, loggingClasses);
+        assertTrue(compiled);
+
+        JarUtils.createJarFile(MODS_DIR.resolve("logging-1.0.jar"),
+                               loggingClasses);
+
+
+        // compile + create mods/httpserver-9.0.0.jar
+
+        compiled = CompilerUtils.compile(httpServerSrc,
+                httpServerClasses,
+                "-cp", loggingClasses.toString());
+        assertTrue(compiled);
+
+        JarUtils.createJarFile(MODS_DIR.resolve("httpserver-9.0.0.jar"),
+                httpServerClasses);
+
+
+        // compile basictest to mods/basictest
+
+        compiled = CompilerUtils
+            .compile(SRC_DIR.resolve(testModule),
+                    MODS_DIR.resolve(testModule),
+                    "-mp", MODS_DIR.toString());
+        assertTrue(compiled);
+
+
+        // launch the test. Need -addmods because nothing explicitly depends on logging
+
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "logging",
+                              "-m", testModule + "/" + mainClass)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+
+    /**
+     * Test using a JAR file with a service provider as an automatic module.
+     *
+     * The consists of 2 modules:
+     *
+     * sptest - the test itself
+     * bananascript - a JAR file (automatic module) with a dummy ScriptEngineFactory
+     *
+     * The test uses ServiceLoader to locate and load ScriptEngineFactory
+     * implementations. It checks that bananascript is located.
+     */
+
+    public void testServiceProvider() throws Exception {
+        boolean compiled;
+
+        Path providerSrc = SRC_DIR.resolve("bananascript");
+        Path providerClasses = CLASSES_DIR.resolve("bananascript");
+
+        String testModule = "sptest";
+        String mainClass = "test.Main";
+
+
+        // create mods/bananascript-0.9.jar
+
+        compiled = CompilerUtils.compile(providerSrc, providerClasses);
+        assertTrue(compiled);
+
+        String config = "META-INF/services/javax.script.ScriptEngineFactory";
+        Path services = providerClasses.resolve(config).getParent();
+        Files.createDirectories(services);
+        Files.copy(providerSrc.resolve(config), providerClasses.resolve(config));
+
+        JarUtils.createJarFile(MODS_DIR.resolve("bananascript-0.9.jar"), providerClasses);
+
+
+        // compile sptest to mods/sptest
+
+        compiled = CompilerUtils
+                .compile(SRC_DIR.resolve(testModule),
+                        MODS_DIR.resolve(testModule),
+                        "-mp", MODS_DIR.toString());
+
+        assertTrue(compiled);
+
+
+        // launch the test
+
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-m", testModule + "/" + mainClass)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/META-INF/services/javax.script.ScriptEngineFactory b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..02241bb
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1,2 @@
+# Our test script engine factory
+org.banana.BananaScriptEngineFactory
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScript.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScript.java
new file mode 100644
index 0000000..ddaf1e1
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScript.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+package org.banana;
+
+import java.io.Reader;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class BananaScript implements ScriptEngine {
+
+    @Override
+    public Object eval(String script, ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(String script, Bindings n) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object eval(Reader reader , Bindings n) {
+        throw new RuntimeException();
+    }
+    @Override
+    public void put(String key, Object value) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Object get(String key) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings getBindings(int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setBindings(Bindings bindings, int scope) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public Bindings createBindings() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptContext getContext() {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public void setContext(ScriptContext context) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngineFactory getFactory() {
+        throw new RuntimeException();
+    }
+}
+
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScriptEngineFactory.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScriptEngineFactory.java
new file mode 100644
index 0000000..443415c
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/bananascript/org/banana/BananaScriptEngineFactory.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.banana;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class BananaScriptEngineFactory implements ScriptEngineFactory {
+
+    @Override
+    public String getEngineName() {
+        return "BananaScriptEngine";
+    }
+
+    @Override
+    public String getEngineVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public List<String> getExtensions() {
+        return Arrays.asList("banana");
+    }
+
+    @Override
+    public List<String> getMimeTypes() {
+        return Arrays.asList("application/x-bananascript");
+    }
+
+    @Override
+    public List<String> getNames() {
+        return Arrays.asList("BananaScript");
+    }
+
+    @Override
+    public String getLanguageName() {
+        return "BananaScript";
+    }
+
+    @Override
+    public String getLanguageVersion() {
+        return "1.0";
+    }
+
+    @Override
+    public Object getParameter(String key) {
+        return null;
+    }
+
+    @Override
+    public String getMethodCallSyntax(String obj, String m, String... args) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getOutputStatement(String toDisplay) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public String getProgram(String... statements) {
+        throw new RuntimeException();
+    }
+
+    @Override
+    public ScriptEngine getScriptEngine() {
+        return new BananaScript();
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/module-info.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/module-info.java
new file mode 100644
index 0000000..0bc9bd6
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 basictest {
+    requires httpserver;  // automatic module
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/test/Main.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/test/Main.java
new file mode 100644
index 0000000..01d8283
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/basictest/test/Main.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package test;
+
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+
+import http.HttpServer;
+
+/**
+ * Basic test using automatic modules.
+ */
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+
+        Module httpModule = HttpServer.class.getModule();
+
+        // automatic modules are named
+        assertTrue(httpModule.isNamed());
+
+        // and read all unnamed modules
+        ClassLoader cl;
+        cl = ClassLoader.getPlatformClassLoader();
+        assertTrue(httpModule.canRead(cl.getUnnamedModule()));
+        cl = ClassLoader.getSystemClassLoader();
+        assertTrue(httpModule.canRead(cl.getUnnamedModule()));
+
+        // and read all modules in the boot Layer
+        Layer layer = Layer.boot();
+        layer.modules().forEach(m -> assertTrue(httpModule.canRead(m)));
+
+        // run code in the automatic modue, ensures access is allowed
+        HttpServer http = HttpServer.create(80);
+        http.start();
+    }
+
+    static void assertTrue(boolean e) {
+        if (!e)
+            throw new RuntimeException();
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/HttpServer.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/HttpServer.java
new file mode 100644
index 0000000..eadb55d
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/HttpServer.java
@@ -0,0 +1,60 @@
+/*
+ * 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 http;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import http.spi.HttpServerProvider;
+import logging.Logger;
+
+/**
+ * A do-nothing HTTP server
+ */
+
+public class HttpServer {
+    private final int port;
+    private final Logger logger;
+
+    protected HttpServer(int port) {
+        this.port = port;
+        this.logger = new Logger();
+    }
+
+    public static HttpServer create(int port) {
+        ServiceLoader<HttpServerProvider> sl
+            = ServiceLoader.load(HttpServerProvider.class);
+        Iterator<HttpServerProvider> iterator = sl.iterator();
+        if (iterator.hasNext()) {
+            HttpServerProvider provider = iterator.next();
+            return provider.createHttpServer(port);
+        } else {
+            return new HttpServer(port) { };
+        }
+    }
+
+    public void start() {
+        logger.log("Start HTTP server on port " + port);
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/spi/HttpServerProvider.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/spi/HttpServerProvider.java
new file mode 100644
index 0000000..b2966ae
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/httpserver/http/spi/HttpServerProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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 http.spi;
+
+import http.HttpServer;
+
+public abstract class HttpServerProvider {
+
+    protected HttpServerProvider() { }
+
+    public abstract HttpServer createHttpServer(int port);
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/logging/logging/Logger.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/logging/logging/Logger.java
new file mode 100644
index 0000000..d0673c3
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/logging/logging/Logger.java
@@ -0,0 +1,36 @@
+/*
+ * 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 logging;
+
+/**
+ * A simple logger.
+ */
+
+public class Logger {
+    public Logger() { }
+
+    public void log(String msg) {
+        System.out.println(msg);
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/module-info.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/module-info.java
new file mode 100644
index 0000000..ce3c72d
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 sptest {
+    requires java.scripting;
+    uses javax.script.ScriptEngineFactory;
+}
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
new file mode 100644
index 0000000..05ff04d
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/test/Main.java
@@ -0,0 +1,83 @@
+/*
+ * 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 test;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.script.ScriptEngineFactory;
+
+/**
+ * Test that the automatic module "bananascript" is in the boot Layer and
+ * it behaves as a service provider.
+ */
+
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+
+        Optional<Module> om = Layer.boot().findModule("bananascript");
+        assertTrue(om.isPresent());
+
+        ModuleDescriptor descriptor = om.get().getDescriptor();
+
+        // requires java.base
+        Set<String> requires
+            = descriptor.requires().stream()
+                .map(Requires::name)
+                .collect(Collectors.toSet());
+        assertTrue(requires.size() == 1);
+        assertTrue(requires.contains("java.base"));
+
+        // uses ScriptEngineFactory
+        Map<String, Provides> provides = descriptor.provides();
+        assertTrue(provides.size() == 1);
+        String sn = ScriptEngineFactory.class.getName();
+        assertTrue(provides.containsKey(sn));
+
+        // Check that it is iterated over with ServiceLoader
+        ServiceLoader<ScriptEngineFactory> sl
+            = ServiceLoader.load(ScriptEngineFactory.class);
+        boolean found = false;
+        for (ScriptEngineFactory factory : sl) {
+            String name = factory.getEngineName();
+            System.out.println(name);
+            if (name.equals("BananaScriptEngine"))
+                found = true;
+        }
+        assertTrue(found);
+    }
+
+    static void assertTrue(boolean e) {
+        if (!e)
+            throw new RuntimeException();
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/ContainerTest.java b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java
new file mode 100644
index 0000000..36a7ac2
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/ContainerTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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
+ * 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.jartool/sun.tools.jar
+ *          jdk.compiler
+ * @build ContainerTest CompilerUtils jdk.testlibrary.*
+ * @run testng ContainerTest
+ * @summary Starts a simple container that uses dynamic configurations
+ *          and launches two applications in the same VM
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ContainerTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    private static final Path MLIB_DIR = Paths.get("mlib");
+    private static final Path APPLIB_DIR = Paths.get("applib");
+
+    private static final String CONTAINER_MODULE = "container";
+    private static final String CONTAINER_MAIN_CLASS = "container.Main";
+
+
+    /**
+     * Creates the container module in mlib/container@1.0.jmod
+     */
+    void buildContainer() throws Exception {
+
+        Path src = SRC_DIR.resolve(CONTAINER_MODULE);
+        Path output = MODS_DIR.resolve(CONTAINER_MODULE);
+
+        boolean compiled = CompilerUtils.compile(src, output);
+        assertTrue(compiled);
+
+        // jar --create ...
+        Path mlib = Files.createDirectories(MLIB_DIR);
+        String classes = output.toString();
+        String jar = mlib.resolve(CONTAINER_MODULE + "@1.0.jar").toString();
+        String[] args = {
+            "--create",
+            "--file=" + jar,
+            "--main-class=" + CONTAINER_MAIN_CLASS,
+            "-C", classes, "."
+        };
+        boolean success
+            = new sun.tools.jar.Main(System.out, System.out, "jar")
+                .run(args);
+        assertTrue(success);
+    }
+
+    /**
+     * Creates app1 and its bundled libraries in applib.
+     */
+    void buildApp1() throws Exception {
+        Path dir = Files.createDirectories(APPLIB_DIR);
+
+        // app1 uses its own copy of JAX-WS
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve("java.xml.ws"),
+                                    dir.resolve("java.xml.ws"));
+        assertTrue(compiled);
+
+        compiled = CompilerUtils.compile(SRC_DIR.resolve("app1"),
+                                         dir.resolve("app1"),
+                                         "-upgrademodulepath", dir.toString());
+        assertTrue(compiled);
+    }
+
+    /**
+     * Creates app2 and its bundled libraries in applib.
+     */
+    void buildApp2() throws Exception {
+        Path dir = Files.createDirectories(APPLIB_DIR);
+
+        // app2 uses JAX-RS
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve("java.ws.rs"),
+                                    dir.resolve("java.ws.rs"));
+        assertTrue(compiled);
+
+        compiled = CompilerUtils.compile(SRC_DIR.resolve("app2"),
+                                         dir.resolve("app2"),
+                                         "-mp", dir.toString());
+        assertTrue(compiled);
+    }
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+        buildContainer();
+        buildApp1();
+        buildApp2();
+    }
+
+    /**
+     * Launches the container
+     */
+    public void testContainer() throws Exception {
+
+        int exitValue
+            = executeTestJava("-mp", MLIB_DIR.toString(),
+                              "-m", CONTAINER_MODULE)
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/app1/app1/Main.java b/jdk/test/jdk/modules/scenarios/container/src/app1/app1/Main.java
new file mode 100644
index 0000000..fb47af1
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/app1/app1/Main.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package app1;
+
+import javax.xml.ws.WebService;
+
+public class Main {
+
+    static void trace(Class<?> c) {
+        System.out.format("%s loaded by %s\n", c, c.getClassLoader());
+    }
+
+    public static void main(String[] args) throws Exception {
+        trace(Main.class);
+
+        WebService ws = new WebService();
+        trace(ws.getClass());
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/app1/module-info.java b/jdk/test/jdk/modules/scenarios/container/src/app1/module-info.java
new file mode 100644
index 0000000..c11441f
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/app1/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 app1 {
+    requires java.base;
+    requires java.xml.ws;
+    exports app1;
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/app2/app2/Main.java b/jdk/test/jdk/modules/scenarios/container/src/app2/app2/Main.java
new file mode 100644
index 0000000..519e664
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/app2/app2/Main.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package app2;
+
+import javax.ws.rs.Client;
+
+public class Main {
+
+    static void trace(Class<?> c) {
+        System.out.format("%s loaded by %s\n", c, c.getClassLoader());
+    }
+
+    public static void main(String[] args) throws Exception {
+        trace(Main.class);
+
+        Client c = new Client();
+        trace(c.getClass());
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/app2/module-info.java b/jdk/test/jdk/modules/scenarios/container/src/app2/module-info.java
new file mode 100644
index 0000000..8a766fe
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/app2/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 app2 {
+    requires java.base;
+    requires java.ws.rs;
+    exports app2;
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java b/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java
new file mode 100644
index 0000000..4c86c6e
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/container/container/Main.java
@@ -0,0 +1,105 @@
+/*
+ * 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
+ * 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 container;
+
+import java.io.File;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ResolvedModule;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+/**
+ * Exercises dynamic configuration.
+ */
+
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+
+        System.out.println("Boot layer");
+        Layer.boot()
+             .modules()
+             .stream()
+             .map(Module::getName)
+             .sorted()
+             .forEach(System.out::println);
+
+        // "start" two applications in their own layers
+        start("applib", "app1", "app1.Main");
+        start("applib", "app2", "app2.Main");
+    }
+
+    static void start(String appModulePath,
+                      String appModuleName,
+                      String appMainClass) throws Exception {
+
+        System.out.format("Starting %s/%s ...%n", appModuleName, appMainClass);
+
+        String[] dirs = appModulePath.split(File.pathSeparator);
+        Path[] paths = new Path[dirs.length];
+        int i = 0;
+        for (String dir: dirs) {
+            paths[i++] = Paths.get(dir);
+        }
+
+        ModuleFinder finder = ModuleFinder.of(paths);
+
+        Configuration cf = Layer.boot().configuration()
+            .resolveRequiresAndUses(finder,
+                                    ModuleFinder.empty(),
+                                    Set.of(appModuleName));
+
+        System.out.println("Resolved");
+        cf.modules().stream()
+          .map(ResolvedModule::name)
+          .sorted()
+          .forEach(mn -> System.out.format("  %s%n", mn));
+
+        // reify the configuration as a Layer
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl);
+
+        // invoke application main method
+        ClassLoader loader = layer.findLoader(appModuleName);
+        Class<?> c = loader.loadClass(appMainClass);
+        Main.class.getModule().addReads(c.getModule());
+        Method mainMethod = c.getMethod("main", String[].class);
+
+        // set TCCL as that is the EE thing to do
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(loader);
+            mainMethod.invoke(null, (Object)new String[0]);
+        } finally {
+            Thread.currentThread().setContextClassLoader(tccl);
+        }
+
+        System.out.println();
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/container/module-info.java b/jdk/test/jdk/modules/scenarios/container/src/container/module-info.java
new file mode 100644
index 0000000..ea0cf50
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/container/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 container {
+    requires java.se;
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/javax/ws/rs/Client.java b/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/javax/ws/rs/Client.java
new file mode 100644
index 0000000..12fdcd1
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/javax/ws/rs/Client.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package javax.ws.rs;
+
+public class Client {
+    public Client() { }
+}
+
diff --git a/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/module-info.java b/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/module-info.java
new file mode 100644
index 0000000..9617784
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/java.ws.rs/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.ws.rs {
+    requires java.base;
+
+    exports javax.ws.rs;
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/javax/xml/ws/WebService.java b/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/javax/xml/ws/WebService.java
new file mode 100644
index 0000000..82149bc
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/javax/xml/ws/WebService.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package javax.xml.ws;
+
+public class WebService {
+    public WebService() { }
+}
diff --git a/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/module-info.java b/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/module-info.java
new file mode 100644
index 0000000..775df76
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/container/src/java.xml.ws/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.xml.ws {
+    requires java.base;
+
+    exports javax.xml.ws;
+}
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java
new file mode 100644
index 0000000..826e282
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/OverlappingPackagesTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build OverlappingPackagesTest CompilerUtils jdk.testlibrary.*
+ * @run testng OverlappingPackagesTest
+ * @summary Basic test to ensure that startup fails if two or more modules
+ *          in the boot Layer have the same package
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class OverlappingPackagesTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    // the names of the modules in this test
+    private static List<String> modules = Arrays.asList("m1", "m2", "test");
+
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        for (String mn : modules) {
+            Path src = SRC_DIR.resolve(mn);
+            Path mods = MODS_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(src, mods));
+        }
+        Path srcMisc = SRC_DIR.resolve("misc");
+        Path modsMisc = MODS_DIR.resolve("misc");
+        assertTrue(CompilerUtils.compile(srcMisc.resolve("sun")
+                                                .resolve("misc")
+                                                .resolve("Unsafe.java"),
+                                         modsMisc,
+                                         "-Xmodule:java.base"));
+        assertTrue(CompilerUtils.compile(srcMisc.resolve("module-info.java"),
+                                         modsMisc));
+    }
+
+    /**
+     * Sanity check that the test runs without error.
+     */
+    public void testNoOverlappingPackages() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-m", "test/test.Main")
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Run the test with "-addmods misc", the misc module has package
+     * sun.misc and so should overlap with the base module.
+     */
+    public void testOverlapWithBaseModule() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "misc",
+                              "-m", "test/test.Main")
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+    /**
+     * Run the test with "-addmods m1,m2". Both modules have package p.
+     */
+    public void testOverlap() throws Exception {
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "m1,m2",
+                              "-m", "test/test.Main")
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+}
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/module-info.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/module-info.java
new file mode 100644
index 0000000..967d553
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+}
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/p/C1.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/p/C1.java
new file mode 100644
index 0000000..a68906e
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m1/p/C1.java
@@ -0,0 +1,26 @@
+/*
+ * 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 C1 { }
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/module-info.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/module-info.java
new file mode 100644
index 0000000..b0fadc6
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+}
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/p/C2.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/p/C2.java
new file mode 100644
index 0000000..141d012
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/m2/p/C2.java
@@ -0,0 +1,26 @@
+/*
+ * 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 C2 { }
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java
new file mode 100644
index 0000000..65cc15d
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 misc {
+    exports sun.misc;
+}
+
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java
new file mode 100644
index 0000000..135652e
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/misc/sun/misc/Unsafe.java
@@ -0,0 +1,32 @@
+/*
+ * 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 sun.misc;
+
+public class Unsafe {
+    private Unsafe() { }
+
+    public static long getLong(long address) {
+        return 0L;
+    }
+}
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/module-info.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/module-info.java
new file mode 100644
index 0000000..62b1d4d
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 test {
+}
+
diff --git a/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/test/Main.java b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/test/Main.java
new file mode 100644
index 0000000..cdf8907
--- /dev/null
+++ b/jdk/test/jdk/modules/scenarios/overlappingpackages/src/test/test/Main.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test;
+
+public class Main {
+    public static void main(String[] args) { }
+}
diff --git a/jdk/test/lib/testlibrary/CompilerUtils.java b/jdk/test/lib/testlibrary/CompilerUtils.java
new file mode 100644
index 0000000..91ca918
--- /dev/null
+++ b/jdk/test/lib/testlibrary/CompilerUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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 javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * This class consists exclusively of static utility methods for invoking the
+ * java compiler.
+ */
+
+public final class CompilerUtils {
+    private CompilerUtils() { }
+
+    /**
+     * Compile all the java sources in {@code <source>/**} to
+     * {@code <destination>/**}. The destination directory will be created if
+     * it doesn't exist.
+     *
+     * All warnings/errors emitted by the compiler are output to System.out/err.
+     *
+     * @return true if the compilation is successful
+     *
+     * @throws IOException if there is an I/O error scanning the source tree or
+     *                     creating the destination directory
+     */
+    public static boolean compile(Path source, Path destination, String ... options)
+        throws IOException
+    {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
+
+        List<Path> sources
+            = Files.find(source, Integer.MAX_VALUE,
+                (file, attrs) -> (file.toString().endsWith(".java")))
+                .collect(Collectors.toList());
+
+        Files.createDirectories(destination);
+        jfm.setLocation(StandardLocation.CLASS_PATH, Collections.EMPTY_LIST);
+        jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
+                                 Arrays.asList(destination));
+
+        List<String> opts = Arrays.asList(options);
+        JavaCompiler.CompilationTask task
+            = compiler.getTask(null, jfm, null, opts, null,
+                jfm.getJavaFileObjectsFromPaths(sources));
+
+        return task.call();
+    }
+}
diff --git a/jdk/test/lib/testlibrary/JarUtils.java b/jdk/test/lib/testlibrary/JarUtils.java
new file mode 100644
index 0000000..94905cc
--- /dev/null
+++ b/jdk/test/lib/testlibrary/JarUtils.java
@@ -0,0 +1,179 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class consists exclusively of static utility methods that are useful
+ * for creating and manipulating JAR files.
+ */
+
+public final class JarUtils {
+    private JarUtils() { }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, Path... file)
+        throws IOException
+    {
+        // create the target directory
+        Path parent = jarfile.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+
+        List<Path> entries = new ArrayList<>();
+        for (Path entry : file) {
+            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
+                        (p, attrs) -> attrs.isRegularFile())
+                    .map(e -> dir.relativize(e))
+                    .forEach(entries::add);
+        }
+
+        try (OutputStream out = Files.newOutputStream(jarfile);
+             JarOutputStream jos = new JarOutputStream(out))
+        {
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+            }
+        }
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, String... input)
+        throws IOException
+    {
+        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+        createJarFile(jarfile, dir, paths);
+    }
+
+    /**
+     * Creates a JAR file from the contents of a directory.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
+     */
+    public static void createJarFile(Path jarfile, Path dir) throws IOException {
+        createJarFile(jarfile, dir, Paths.get("."));
+    }
+
+    /**
+     * Update a JAR file.
+     *
+     * Equivalent to {@code jar uf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void updateJarFile(Path jarfile, Path dir, Path... file)
+        throws IOException
+    {
+        List<Path> entries = new ArrayList<>();
+        for (Path entry : file) {
+            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
+                    (p, attrs) -> attrs.isRegularFile())
+                    .map(e -> dir.relativize(e))
+                    .forEach(entries::add);
+        }
+
+        Set<String> names = entries.stream()
+                .map(JarUtils::toJarEntryName)
+                .collect(Collectors.toSet());
+
+        Path tmpfile = Files.createTempFile("jar", "jar");
+
+        try (OutputStream out = Files.newOutputStream(tmpfile);
+             JarOutputStream jos = new JarOutputStream(out))
+        {
+            // copy existing entries from the original JAR file
+            try (JarFile jf = new JarFile(jarfile.toString())) {
+                Enumeration<JarEntry> jentries = jf.entries();
+                while (jentries.hasMoreElements()) {
+                    JarEntry jentry = jentries.nextElement();
+                    if (!names.contains(jentry.getName())) {
+                        jos.putNextEntry(jentry);
+                        jf.getInputStream(jentry).transferTo(jos);
+                    }
+                }
+            }
+
+            // add the new entries
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+            }
+        }
+
+        // replace the original JAR file
+        Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    /**
+     * Update a JAR file.
+     *
+     * Equivalent to {@code jar uf <jarfile> -C <dir> .}
+     */
+    public static void updateJarFile(Path jarfile, Path dir) throws IOException {
+        updateJarFile(jarfile, dir, Paths.get("."));
+    }
+
+
+    /**
+     * Map a file path to the equivalent name in a JAR file
+     */
+    private static String toJarEntryName(Path file) {
+        Path normalized = file.normalize();
+        return normalized.subpath(0, normalized.getNameCount())  // drop root
+                .toString()
+                .replace(File.separatorChar, '/');
+    }
+}
diff --git a/jdk/test/lib/testlibrary/ModuleUtils.java b/jdk/test/lib/testlibrary/ModuleUtils.java
new file mode 100644
index 0000000..c227464
--- /dev/null
+++ b/jdk/test/lib/testlibrary/ModuleUtils.java
@@ -0,0 +1,83 @@
+/*
+ * 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.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Supplier;
+
+
+/**
+ * This class consists exclusively of static utility methods that are useful
+ * for creating tests for modules.
+ */
+
+public final class ModuleUtils {
+    private ModuleUtils() { }
+
+
+    /**
+     * Returns a ModuleFinder that finds modules with the given module
+     * descriptors.
+     */
+    static ModuleFinder finderOf(ModuleDescriptor... descriptors) {
+
+        // Create a ModuleReference for each module
+        Map<String, ModuleReference> namesToReference = new HashMap<>();
+
+        for (ModuleDescriptor descriptor : descriptors) {
+            String name = descriptor.name();
+
+            URI uri = URI.create("module:/" + name);
+
+            Supplier<ModuleReader> supplier = () -> {
+                throw new UnsupportedOperationException();
+            };
+
+            ModuleReference mref = new ModuleReference(descriptor, uri, supplier);
+
+            namesToReference.put(name, mref);
+        }
+
+        return new ModuleFinder() {
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                Objects.requireNonNull(name);
+                return Optional.ofNullable(namesToReference.get(name));
+            }
+            @Override
+            public Set<ModuleReference> findAll() {
+                return new HashSet<>(namesToReference.values());
+            }
+        };
+    }
+
+}
diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java
index 58ef07a..839c322 100644
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java
@@ -26,6 +26,7 @@
 import static jdk.testlibrary.Asserts.*;
 
 import java.io.IOException;
+import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Matcher;
@@ -422,6 +423,28 @@
         return output == null ? exitValue : output.getExitValue();
     }
 
+
+    /**
+     * Print the stdout buffer to the given {@code PrintStream}.
+     *
+     * @return this OutputAnalyzer
+     */
+    public OutputAnalyzer outputTo(PrintStream out) {
+        out.println(getStdout());
+        return this;
+    }
+
+    /**
+     * Print the stderr buffer to the given {@code PrintStream}.
+     *
+     * @return this OutputAnalyzer
+     */
+    public OutputAnalyzer errorTo(PrintStream out) {
+        out.println(getStderr());
+        return this;
+    }
+
+
     /**
      * Get the contents of the output buffer (stdout and stderr) as list of strings.
      * Output will be split by system property 'line.separator'.
diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
index 6842de2..35cffc1 100644
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java
@@ -340,24 +340,31 @@
     }
 
     /**
-     * Executes a test jvm process, waits for it to finish and returns the process output.
-     * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
+     * Executes a test java process, waits for it to finish and returns the process output.
+     * The default options from jtreg, test.vm.opts and test.java.opts, are added.
      * The java from the test.jdk is used to execute the command.
      *
      * The command line will be like:
      * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
      *
-     * The jvm process will have exited before this method returns.
+     * The java process will have exited before this method returns.
      *
      * @param cmds User specifed arguments.
      * @return The output from the process.
      */
-    public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception {
-        ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
+    public static OutputAnalyzer executeTestJava(String... options) throws Exception {
+        ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(options));
         return executeProcess(pb);
     }
 
     /**
+     * @deprecated Use executeTestJava instead
+     */
+    public static OutputAnalyzer executeTestJvm(String... options) throws Exception {
+        return executeTestJava(options);
+    }
+
+    /**
      * Executes a process, waits for it to finish and returns the process output.
      * The process will have exited before this method returns.
      * @param pb The ProcessBuilder to execute.
diff --git a/jdk/test/sun/awt/shell/ShellFolderMemoryLeak.java b/jdk/test/sun/awt/shell/ShellFolderMemoryLeak.java
index fc90596..69b39bf 100644
--- a/jdk/test/sun/awt/shell/ShellFolderMemoryLeak.java
+++ b/jdk/test/sun/awt/shell/ShellFolderMemoryLeak.java
@@ -93,6 +93,7 @@
         String command = javaPath + File.separator + "bin" + File.separator
                 + "java -Xmx256M" + arg1 + " -cp "
                 + classPathDir
+                + " -XaddExports:java.desktop/sun.awt.shell=ALL-UNNAMED"
                 + " ShellFolderMemoryLeak " + arg2;
         process = Runtime.getRuntime().exec(command);
         BufferedReader input = null;
diff --git a/jdk/test/sun/management/StackTraceElementCompositeData/CompatibilityTest.java b/jdk/test/sun/management/StackTraceElementCompositeData/CompatibilityTest.java
new file mode 100644
index 0000000..00789c8
--- /dev/null
+++ b/jdk/test/sun/management/StackTraceElementCompositeData/CompatibilityTest.java
@@ -0,0 +1,72 @@
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import sun.management.StackTraceElementCompositeData;
+
+import org.testng.annotations.*;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug     8139587
+ * @summary Check backward compatibility of StackTraceElementCompositeData
+ * @modules java.management/sun.management
+ * @run testng CompatibilityTest
+ * @author  Jaroslav Bachorik
+ */
+
+public class CompatibilityTest {
+    private static CompositeType compositeTypeV6;
+    private static Map<String, Object> itemsV6;
+    private static CompositeData compositeDataV6;
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        compositeTypeV6 = new CompositeType(
+            StackTraceElement.class.getName(),
+            "StackTraceElement",
+            new String[]{
+                "className", "methodName", "fileName", "nativeMethod", "lineNumber"
+            },
+            new String[]{
+                "className", "methodName", "fileName", "nativeMethod", "lineNumber"
+            },
+            new OpenType[]{
+                SimpleType.STRING,
+                SimpleType.STRING,
+                SimpleType.STRING,
+                SimpleType.BOOLEAN,
+                SimpleType.INTEGER
+            }
+        );
+
+        itemsV6 = new HashMap<>();
+        itemsV6.put("className", "MyClass");
+        itemsV6.put("methodName", "myMethod");
+        itemsV6.put("fileName", "MyClass.java");
+        itemsV6.put("nativeMethod", false);
+        itemsV6.put("lineNumber", 123);
+
+        compositeDataV6 = new CompositeDataSupport(compositeTypeV6, itemsV6);
+    }
+
+    @Test
+    public void testV6Compatibility() throws Exception {
+        StackTraceElement ste = StackTraceElementCompositeData.from(compositeDataV6);
+
+        assertNotNull(ste);
+        assertEquals(ste.getClassName(), "MyClass");
+        assertEquals(ste.getMethodName(), "myMethod");
+        assertEquals(ste.getFileName(), "MyClass.java");
+        assertEquals(ste.isNativeMethod(), false);
+        assertEquals(ste.getLineNumber(), 123);
+
+        assertNull(ste.getModuleName());
+        assertNull(ste.getModuleVersion());
+    }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
index 5e61420..75f3cdb 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
+++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java
@@ -150,6 +150,7 @@
             ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
                 "-cp",
                 TEST_CLASSPATH,
+                "-XaddExports:java.management/sun.management=ALL-UNNAMED",
                 "TestManager",
                 String.valueOf(serverPrc.getPid()),
                 port.get(),
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
index a344249..2dd3555 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java
@@ -131,6 +131,7 @@
             ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
                 "-cp",
                 TEST_CLASSPATH,
+                "-XaddExports:java.management/sun.management=ALL-UNNAMED",
                 "TestManager",
                 String.valueOf(serverPrc.getPid()),
                 port.get(),
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh
index 2e3fac8..5efd6e2 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh
@@ -51,6 +51,9 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+export EXTRAOPTIONS
+
 # Call the common generic test
 #
 # No need to since bug 4267864 is now fixed. 
@@ -58,7 +61,7 @@
 echo -------------------------------------------------------------
 echo Launching test for `basename $0 .sh`
 echo -------------------------------------------------------------
-sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${TESTCLASS}
+sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${EXTRAOPTIONS} ${TESTCLASS}
 result=$?
 restoreFilePermissions `ls ${TESTSRC}/*_test*.in`
 exit $result
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh
index ee68781..16db84c 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh
@@ -49,12 +49,15 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+export EXTRAOPTIONS
+
 # Call the common generic test
 #
 echo -------------------------------------------------------------
 echo Launching test for `basename $0 .sh`
 echo -------------------------------------------------------------
-sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${TESTCLASS} \
+sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${EXTRAOPTIONS} ${TESTCLASS} \
     ${TESTCLASSES}/management_ssltest*.properties
 result=$?
 restoreFilePermissions `ls ${TESTSRC}/*_ssltest*.in`
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh
index a6d1063..86ab964 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh
@@ -48,12 +48,15 @@
 DEBUGOPTIONS=""
 export DEBUGOPTIONS
 
+EXTRAOPTIONS="-XaddExports:java.management/sun.management=ALL-UNNAMED,java.management/sun.management.jmxremote=ALL-UNNAMED"
+export EXTRAOPTIONS
+
 # Call the common generic test
 #
 echo -------------------------------------------------------------
 echo Launching test for `basename $0 .sh`
 echo -------------------------------------------------------------
-sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${TESTCLASS} \
+sh ${TESTSRC}/../RunTest.sh ${DEBUGOPTIONS} ${EXTRAOPTIONS} ${TESTCLASS} \
     ${TESTCLASSES}/management_ssltest*.properties
 result=$?
 restoreFilePermissions `ls ${TESTSRC}/*_ssltest*.in`
diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
index bbdf3c0..e754555 100644
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
@@ -42,6 +42,7 @@
  *          in the related performance counters.
  * @key intermittent
  * @library /lib/testlibrary
+ * @modules java.management/sun.management
  * @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
  * @run testng/othervm -XX:+UsePerfData JMXStatusPerfCountersTest
  */
diff --git a/jdk/test/sun/net/idn/TestStringPrep.java b/jdk/test/sun/net/idn/TestStringPrep.java
index 20b4f5d..2f45955 100644
--- a/jdk/test/sun/net/idn/TestStringPrep.java
+++ b/jdk/test/sun/net/idn/TestStringPrep.java
@@ -231,7 +231,8 @@
     }
 
     public static void TestNamePrepConformance() throws Exception {
-        InputStream stream = StringPrep.class.getResourceAsStream("uidna.spp");
+        InputStream stream = StringPrep.class.getModule()
+                                             .getResourceAsStream("sun/net/idn/uidna.spp");
         StringPrep namePrep = new StringPrep(stream);
         stream.close();
         int i;
diff --git a/jdk/test/sun/net/util/IPAddressUtilTest.java b/jdk/test/sun/net/util/IPAddressUtilTest.java
index 8c35ac7..8e4b6a2 100644
--- a/jdk/test/sun/net/util/IPAddressUtilTest.java
+++ b/jdk/test/sun/net/util/IPAddressUtilTest.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8087190
  * @summary Exercise the sun.net.util.IPAddressUtil class
+ * @modules java.base/sun.net.util
  */
 
 import sun.net.util.*;
diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
index 1b7cf98..c3b45f1 100644
--- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh
@@ -28,6 +28,7 @@
 # @test
 # @bug 4423074
 # @summary Need to rebase all the duplicated classes from Merlin
+# @modules java.base/sun.net.www
 
 HOSTNAME=`uname -n`
 OS=`uname -s`
@@ -50,9 +51,12 @@
     ;;
 esac
 
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \
+EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED"
+
+${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
     ${TESTSRC}${FS}OriginServer.java \
     ${TESTSRC}${FS}ProxyTunnelServer.java \
     ${TESTSRC}${FS}PostThruProxy.java
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} PostThruProxy ${HOSTNAME} ${TESTSRC}
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} \
+    PostThruProxy ${HOSTNAME} ${TESTSRC}
 exit
diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
index fd24c76..79b99f0 100644
--- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh
@@ -28,6 +28,7 @@
 # @test
 # @bug 4423074
 # @summary Need to rebase all the duplicated classes from Merlin
+# @modules java.base/sun.net.www
 
 HOSTNAME=`uname -n`
 OS=`uname -s`
@@ -50,8 +51,11 @@
     ;;
 esac
 
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}${FS}OriginServer.java \
+EXTRAOPTS="-XaddExports:java.base/sun.net.www=ALL-UNNAMED"
+${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} \
+    -d . ${TESTSRC}${FS}OriginServer.java \
     ${TESTSRC}${FS}ProxyTunnelServer.java \
     ${TESTSRC}${FS}PostThruProxyWithAuth.java
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC}
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} \
+    PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC}
 exit
diff --git a/jdk/test/sun/net/www/protocol/jrt/Basic.java b/jdk/test/sun/net/www/protocol/jrt/Basic.java
index 82d15fc..0f0492c 100644
--- a/jdk/test/sun/net/www/protocol/jrt/Basic.java
+++ b/jdk/test/sun/net/www/protocol/jrt/Basic.java
@@ -38,26 +38,6 @@
 
 public class Basic {
 
-    @DataProvider(name = "resources")
-    public Object[][] resources() {
-        Object[][] data = {
-            { "java/lang/Object.class",   "jrt:/java.base/java/lang/Object.class" },
-            { "java/awt/Component.class", "jrt:/java.desktop/java/awt/Component.class" },
-            { "jdk/internal/DoesNotExist", null },
-        };
-        return data;
-    }
-
-    @Test(dataProvider = "resources")
-    public void testResources(String name, String expectedUrlString) throws Exception {
-        URL url = ClassLoader.getSystemResource(name);
-        if (url == null) {
-            assertTrue(expectedUrlString == null);
-        } else {
-            assertEquals(url.toString(), expectedUrlString);
-        }
-    }
-
     @DataProvider(name = "urls")
     public Object[][] urls() {
         Object[][] data = {
diff --git a/jdk/test/sun/net/www/protocol/jrt/OtherResources.java b/jdk/test/sun/net/www/protocol/jrt/OtherResources.java
new file mode 100644
index 0000000..9717d4d
--- /dev/null
+++ b/jdk/test/sun/net/www/protocol/jrt/OtherResources.java
@@ -0,0 +1,47 @@
+/*
+ * 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.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * Access a jrt:/ resource in an observable module that is not in the boot
+ * layer and hence not known to the built-in class loaders.
+ */
+
+public class OtherResources {
+    public static void main(String[] args) throws IOException {
+
+        // check that java.desktop is not in the set of readable modules
+        try {
+            Class.forName("java.awt.Component");
+            throw new RuntimeException("Need to run with -limitmods java.base");
+        } catch (ClassNotFoundException expected) { }
+
+        // access resource in the java.desktop module
+        URL url = new URL("jrt:/java.desktop/java/awt/Component.class");
+        URLConnection uc = url.openConnection();
+        System.out.println(uc.getInputStream());
+    }
+}
diff --git a/jdk/test/sun/net/www/protocol/jrt/WithSecurityManager.java b/jdk/test/sun/net/www/protocol/jrt/WithSecurityManager.java
index 58678d7..97f1105 100644
--- a/jdk/test/sun/net/www/protocol/jrt/WithSecurityManager.java
+++ b/jdk/test/sun/net/www/protocol/jrt/WithSecurityManager.java
@@ -29,6 +29,8 @@
  */
 
 import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -36,8 +38,8 @@
 public class WithSecurityManager {
     public static void main(String[] args) throws Exception {
         String home = System.getProperty("java.home");
-        Path bootmodules = Paths.get(home, "lib", "modules", "bootmodules.jimage");
-        if (Files.notExists(bootmodules)) {
+        Path modules = Paths.get(home, "lib", "modules");
+        if (!Files.isRegularFile(modules)) {
             System.out.println("This runtime is not jimage, test skipped");
             return;
         }
@@ -55,7 +57,13 @@
 
         System.setSecurityManager(new SecurityManager());
 
-        InputStream in = ClassLoader.getSystemResourceAsStream("java/lang/Object.class");
+        InputStream in = null;
+        URL url = new URL("jrt:/java.base/java/lang/Object.class");
+        if (url != null) {
+            try {
+                in = url.openStream();
+            } catch (IOException ignore) { }
+        }
         if (in == null && allow)
             throw new RuntimeException("access expected");
         if (in != null && !allow)
diff --git a/jdk/test/sun/net/www/protocol/jrt/other_resources.sh b/jdk/test/sun/net/www/protocol/jrt/other_resources.sh
new file mode 100644
index 0000000..260891c
--- /dev/null
+++ b/jdk/test/sun/net/www/protocol/jrt/other_resources.sh
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @build OtherResources
+# @run shell other_resources.sh
+# @summary Access a jrt:/ resource in an observable module that is not in
+#  the boot layer and hence not known to the built-in class loaders. This
+#  test is a shell test because the run tag doesn't support -limitmods.
+
+set -e
+
+if [ -z "$TESTJAVA" ]; then
+  if [ $# -lt 1 ]; then exit 1; fi
+  TESTJAVA="$1"; shift
+  COMPILEJAVA="${TESTJAVA}"
+  TESTSRC="`pwd`"
+  TESTCLASSES="`pwd`"
+fi
+
+JAVA="$TESTJAVA/bin/java ${TESTVMOPTS}"
+$JAVA -limitmods java.base -cp $TESTCLASSES OtherResources
+
+exit 0
+
diff --git a/jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh b/jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh
index b633709..b6d0dda 100644
--- a/jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh
+++ b/jdk/test/sun/reflect/Reflection/GetCallerClassTest.sh
@@ -55,14 +55,16 @@
 rm -rf ${BCP}
 mkdir ${BCP}
 
+EXTRAOPTS="-XaddExports:java.base/sun.reflect=ALL-UNNAMED"
+
 # Compile GetCallerClass in bootclasspath
-${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
+${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} ${EXTRAOPTS} \
      -XDignore.symbol.file \
      -d ${BCP} ${TESTSRC}/GetCallerClass.java  || exit 1
 
-${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} \
-     -XDignore.symbol.file -Xbootclasspath/a:${BCP} \
+${COMPILEJAVA}/bin/javac ${TESTTOOLVMOPTS} ${EXTRAOPTS} \
+     -XDignore.symbol.file -cp ${BCP} \
      -d ${TESTCLASSES} ${TESTSRC}/GetCallerClassTest.java  || exit 2
 
-${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbootclasspath/a:${BCP} \
+${TESTJAVA}/bin/java ${TESTVMOPTS} ${EXTRAOPTS} -Xbootclasspath/a:${BCP} \
      -cp ${TESTCLASSES} GetCallerClassTest || exit 3
diff --git a/jdk/test/sun/reflect/constantPool/ConstantPoolTest.java b/jdk/test/sun/reflect/constantPool/ConstantPoolTest.java
index 3ede807..fab27c6 100644
--- a/jdk/test/sun/reflect/constantPool/ConstantPoolTest.java
+++ b/jdk/test/sun/reflect/constantPool/ConstantPoolTest.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 8141615
  * @summary Tests new public methods at sun.reflect.ConstantPool
- * @modules java.base/sun.reflect
+ * @modules java.base/jdk.internal.misc
+ *          java.base/sun.reflect
  * @library /lib/testlibrary
  * @compile ConstantPoolTestDummy.jasm
  * @run main sun.reflect.constantPool.ConstantPoolTest
diff --git a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java
index eab963b..36414cc 100644
--- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java
+++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -66,9 +66,13 @@
 
         // We instantiate a JavaVM that should not produce any console output
         // (neither on standard output, nor on standard err streams).
-        JavaVM vm = new JavaVM(DoRMIStuff.class.getName(),
-            "-Djava.util.logging.config.file=" + loggingPropertiesFile,
-                               "", out, err);
+        JavaVM vm = new JavaVM(
+                DoRMIStuff.class.getName(),
+                "-XaddExports:java.rmi/sun.rmi.registry=ALL-UNNAMED,"
+                + "java.rmi/sun.rmi.server=ALL-UNNAMED,java.rmi/sun.rmi.transport=ALL-UNNAMED,"
+                + "java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
+                + " -Djava.util.logging.config.file="
+                + loggingPropertiesFile, "", out, err);
         vm.execute();
 
         /*
diff --git a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
index 9624500..101f4d7 100644
--- a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
+++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java
@@ -24,6 +24,14 @@
 /*
  * @test
  * @bug 6578647 6829283
+ * @modules java.base/sun.net.spi.nameservice
+ *          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.internal.ccache
+ *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5.internal.ktab
  * @run main/othervm HttpNegotiateServer
  * @summary Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
  * @summary HTTP/Negotiate: Authenticator triggered again when user cancels the first one
diff --git a/jdk/test/sun/security/krb5/config/ConfPlusProp.java b/jdk/test/sun/security/krb5/config/ConfPlusProp.java
index 2376d02..b7dc492 100644
--- a/jdk/test/sun/security/krb5/config/ConfPlusProp.java
+++ b/jdk/test/sun/security/krb5/config/ConfPlusProp.java
@@ -25,6 +25,7 @@
  * @bug 6857795
  * @bug 6858589
  * @bug 6972005
+ * @modules java.security.jgss/sun.security.krb5
  * @compile -XDignore.symbol.file ConfPlusProp.java
  * @run main/othervm ConfPlusProp
  * @summary krb5.conf ignored if system properties on realm and kdc are provided
diff --git a/jdk/test/sun/security/krb5/config/DNS.java b/jdk/test/sun/security/krb5/config/DNS.java
index 7171441..da143e5 100644
--- a/jdk/test/sun/security/krb5/config/DNS.java
+++ b/jdk/test/sun/security/krb5/config/DNS.java
@@ -21,7 +21,14 @@
  * questions.
  */
 
-// See dns.sh.
+/*
+ * @test
+ * @bug 8002344
+ * @summary Krb5LoginModule config class does not return proper KDC list from DNS
+ * @modules java.security.jgss/sun.security.krb5
+ * @build java.naming/javax.naming.spi.NamingManager
+ * @run main/othervm DNS
+ */
 import sun.security.krb5.Config;
 import sun.security.krb5.KrbException;
 
diff --git a/jdk/test/sun/security/krb5/config/dns.sh b/jdk/test/sun/security/krb5/config/dns.sh
deleted file mode 100644
index 698f578..0000000
--- a/jdk/test/sun/security/krb5/config/dns.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (c) 2012, 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 8002344
-# @summary Krb5LoginModule config class does not return proper KDC list from DNS
-#
-
-env
-
-if [ "${TESTJAVA}" = "" ] ; then
-  JAVAC_CMD=`which javac`
-  TESTJAVA=`dirname $JAVAC_CMD`/..
-  COMPILEJAVA="${TESTJAVA}"
-fi
-
-if [ "${TESTSRC}" = "" ] ; then
-   TESTSRC="."
-fi
-
-$COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \
-   ${TESTSRC}/NamingManager.java ${TESTSRC}/DNS.java
-$TESTJAVA/bin/java ${TESTVMOPTS} -Xbootclasspath/p:. DNS
-
diff --git a/jdk/test/sun/security/krb5/config/NamingManager.java b/jdk/test/sun/security/krb5/config/java.naming/javax/naming/spi/NamingManager.java
similarity index 100%
rename from jdk/test/sun/security/krb5/config/NamingManager.java
rename to jdk/test/sun/security/krb5/config/java.naming/javax/naming/spi/NamingManager.java
diff --git a/jdk/test/sun/security/krb5/tools/ktcheck.sh b/jdk/test/sun/security/krb5/tools/ktcheck.sh
index ba279851..48a01a7 100644
--- a/jdk/test/sun/security/krb5/tools/ktcheck.sh
+++ b/jdk/test/sun/security/krb5/tools/ktcheck.sh
@@ -24,6 +24,9 @@
 # @test
 # @bug 6950546
 # @summary "ktab -d name etype" to "ktab -d name [-e etype] [kvno | all | old]"
+# @modules java.security.jgss/sun.security.krb5.internal.ktab
+#          java.security.jgss/sun.security.krb5
+# @compile KtabCheck.java
 # @run shell ktcheck.sh
 #
 
@@ -54,11 +57,12 @@
 KEYTAB=ktab.tmp
 
 rm $KEYTAB
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}KtabCheck.java
 
 EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf"
 KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f"
-CHECK="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRA_OPTIONS} KtabCheck $KEYTAB"
+CHECK="${TESTJAVA}${FS}bin${FS}java -cp ${TESTCLASSES} ${TESTVMOPTS} ${EXTRA_OPTIONS} \
+        -XaddExports:java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED,java.security.jgss/sun.security.krb5=ALL-UNNAMED \
+        KtabCheck $KEYTAB"
 
 echo ${EXTRA_OPTIONS}
 
diff --git a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java
index ac3c2ff..7d3b42d 100644
--- a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java
+++ b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java
@@ -21,8 +21,12 @@
  * questions.
  */
 
-/**
- * @see IsSunMSCAPIAvailable.sh
+/*
+ * @test
+ * @bug 6318171 6931562
+ * @requires os.family == "windows"
+ * @modules jdk.crypto.mscapi/sun.security.mscapi
+ * @run main/othervm IsSunMSCAPIAvailable
  */
 
 import java.security.Provider;
diff --git a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh
deleted file mode 100644
index accf1bf..0000000
--- a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright (c) 2005, 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 6318171 6931562
-# @requires os.family == "windows"
-# @run shell IsSunMSCAPIAvailable.sh
-# @summary Basic test of the Microsoft CryptoAPI provider.
-
-OS=`uname -s`
-case "$OS" in
-    Windows* | CYGWIN* )
-
-    # 'uname -m' does not give us enough information -
-    #  should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk),
-    #  but JTREG does not pass this env variable when executing a shell script.
-    #
-    #  execute test program - rely on it to exit if platform unsupported
-
-	${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}\\IsSunMSCAPIAvailable.java
-	${TESTJAVA}/bin/java ${TESTVMOPTS} IsSunMSCAPIAvailable
-	exit
-	;;
-
-    * )
-        echo "This test is not intended for '$OS' - passing test"
-        exit 0
-        ;;
-esac
-
diff --git a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh
index 0f0fba5..5110a4b 100644
--- a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh
+++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh
@@ -25,7 +25,6 @@
 
 # @test
 # @bug 6888925
-# @modules java.base/sun.security.util
 # @requires os.family == "windows"
 # @run shell PublicKeyInterop.sh
 # @summary SunMSCAPI's Cipher can't use RSA public keys obtained from other
@@ -62,9 +61,11 @@
 	    -noprompt
 
         echo
-	echo "Running the test..."
-        ${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . ${TESTSRC}\\PublicKeyInterop.java
-        ${TESTJAVA}/bin/java ${TESTVMOPTS} PublicKeyInterop
+        echo "Running the test..."
+        ${TESTJAVA}/bin/javac -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+            ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . ${TESTSRC}\\PublicKeyInterop.java
+        ${TESTJAVA}/bin/java -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+            ${TESTVMOPTS} PublicKeyInterop
 
         rc=$?
 
diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh
index 4c2bf16..091f3d9 100644
--- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh
+++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh
@@ -88,9 +88,11 @@
 
         echo
         echo "Running the test..."
-        ${TESTJAVA}${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . \
+        ${TESTJAVA}${FS}bin${FS}javac -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+            ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} -d . \
             ${TESTSRC}${FS}ShortRSAKeyWithinTLS.java
-        ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ShortRSAKeyWithinTLS 7106773.$BITS $BITS \
+        ${TESTJAVA}${FS}bin${FS}java -XaddExports:java.base/sun.security.util=ALL-UNNAMED \
+            ${TESTVMOPTS} ShortRSAKeyWithinTLS 7106773.$BITS $BITS \
             TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
 
         rc=$?
diff --git a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh
index f889417..a99a591 100644
--- a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh
+++ b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -126,7 +126,7 @@
 
 # compile test
 ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
-	-classpath ${TESTSRC}${FS}..${PS}${TESTSRC}${FS}loader.jar \
+	-classpath ${TESTSRC} \
 	-d ${TESTCLASSES} \
 	${TESTSRC}${FS}ClientAuth.java \
 	${TESTSRC}${FS}..${FS}PKCS11Test.java
@@ -134,7 +134,7 @@
 # run test
 echo "Run ClientAuth ..."
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
-	-classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \
+	-classpath ${TESTCLASSES} \
 	-DDIR=${TESTSRC}${FS}ClientAuthData${FS} \
 	-DCUSTOM_DB_DIR=${TESTCLASSES} \
 	-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \
@@ -155,7 +155,7 @@
 # run test with specified TLS protocol and cipher suite
 echo "Run ClientAuth TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
 ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
-	-classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \
+	-classpath ${TESTCLASSES} \
 	-DDIR=${TESTSRC}${FS}ClientAuthData${FS} \
 	-DCUSTOM_DB_DIR=${TESTCLASSES} \
 	-DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ClientAuthData${FS}p11-nss.txt \
diff --git a/jdk/test/sun/security/pkcs11/Provider/Login.policy b/jdk/test/sun/security/pkcs11/Provider/Login.policy
index 7fee2f8..a386103 100644
--- a/jdk/test/sun/security/pkcs11/Provider/Login.policy
+++ b/jdk/test/sun/security/pkcs11/Provider/Login.policy
@@ -1,6 +1,7 @@
 grant {
     permission java.util.PropertyPermission "*", "read, write";
     permission java.lang.RuntimePermission "loadLibrary.*";
+    permission java.lang.RuntimePermission "accessClassInPackage.apple.*";
     permission java.lang.RuntimePermission "accessClassInPackage.sun.*";
     permission java.lang.RuntimePermission "getProtectionDomain";
     permission java.security.SecurityPermission "putProviderProperty.*";
diff --git a/jdk/test/sun/security/provider/PolicyFile/Modules.java b/jdk/test/sun/security/provider/PolicyFile/Modules.java
new file mode 100644
index 0000000..5cd7f3d
--- /dev/null
+++ b/jdk/test/sun/security/provider/PolicyFile/Modules.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8047771
+ * @summary check permissions and principals from various modules
+ * @run main/othervm/java.security.policy==modules.policy Modules
+ */
+
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.security.auth.Subject;
+
+public class Modules {
+
+    private final static Permission[] perms = new Permission[] {
+        // java.base module
+        new java.io.SerializablePermission("enableSubstitution"),
+        new java.lang.reflect.ReflectPermission("suppressAccessChecks"),
+        new java.nio.file.LinkPermission("hard"),
+        new javax.net.ssl.SSLPermission("getSSLSessionContext"),
+        new javax.security.auth.AuthPermission("doAsPrivileged"),
+        new javax.security.auth.PrivateCredentialPermission("* * \"*\"",
+                                                            "read"),
+        // java.base module (@jdk.Exported Permissions)
+        new jdk.net.NetworkPermission("setOption.SO_FLOW_SLA"),
+        // java.desktop module
+        new java.awt.AWTPermission("createRobot"),
+        new javax.sound.sampled.AudioPermission("play"),
+        // java.logging module
+        new java.util.logging.LoggingPermission("control", ""),
+        // java.management module
+        new java.lang.management.ManagementPermission("control"),
+        new javax.management.MBeanPermission("*", "getAttribute"),
+        new javax.management.MBeanServerPermission("createMBeanServer"),
+        new javax.management.MBeanTrustPermission("register"),
+        new javax.management.remote.SubjectDelegationPermission("*"),
+        // java.security.jgss module
+        new javax.security.auth.kerberos.DelegationPermission("\"*\" \"*\""),
+        new javax.security.auth.kerberos.ServicePermission("*", "accept"),
+        // java.sql module
+        new java.sql.SQLPermission("setLog"),
+        // java.xml.bind module
+        new javax.xml.bind.JAXBPermission("setDatatypeConverter"),
+        // java.xml.ws module
+        new javax.xml.ws.WebServicePermission("publishEndpoint"),
+        // java.smartcardio module
+        new javax.smartcardio.CardPermission("*", "*"),
+        // jdk.attach module (@jdk.Exported Permissions)
+        new com.sun.tools.attach.AttachPermission("attachVirtualMachine"),
+        // jdk.jdi module (@jdk.Exported Permissions)
+        new com.sun.jdi.JDIPermission("virtualMachineManager"),
+        // jdk.security.jgss module (@jdk.Exported Permissions)
+        new com.sun.security.jgss.InquireSecContextPermission("*"),
+    };
+
+    private final static Principal[] princs = new Principal[] {
+        // java.base module
+        new javax.security.auth.x500.X500Principal("CN=Duke"),
+        // java.management module
+        new javax.management.remote.JMXPrincipal("Duke"),
+        // java.security.jgss module
+        new javax.security.auth.kerberos.KerberosPrincipal("duke@openjdk.org"),
+        new com.sun.security.auth.UserPrincipal("Duke"),
+        new com.sun.security.auth.NTDomainPrincipal("openjdk.org"),
+        new com.sun.security.auth.NTSid(
+            "S-1-5-21-3623811015-3361044348-30300820-1013"),
+        new com.sun.security.auth.NTUserPrincipal("Duke"),
+        new com.sun.security.auth.UnixNumericUserPrincipal("0"),
+        new com.sun.security.auth.UnixPrincipal("duke"),
+    };
+
+    public static void main(String[] args) throws Exception {
+
+        for (Permission perm : perms) {
+            AccessController.checkPermission(perm);
+        }
+
+        Permission princPerm = new java.util.PropertyPermission("user.home",
+                                                                "read");
+        Set<Principal> princSet = new HashSet<>(Arrays.asList(princs));
+        Subject subject = new Subject(true, princSet, Collections.emptySet(),
+                                      Collections.emptySet());
+        PrivilegedAction<Void> pa = () -> {
+            AccessController.checkPermission(princPerm);
+            return null;
+        };
+        Subject.doAsPrivileged(subject, pa, null);
+    }
+}
diff --git a/jdk/test/sun/security/provider/PolicyFile/modules.policy b/jdk/test/sun/security/provider/PolicyFile/modules.policy
new file mode 100644
index 0000000..4a52fc3
--- /dev/null
+++ b/jdk/test/sun/security/provider/PolicyFile/modules.policy
@@ -0,0 +1,67 @@
+grant {
+    // java.base module
+    permission java.io.SerializablePermission "enableSubstitution";
+    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+    permission java.nio.file.LinkPermission "hard";
+    permission javax.net.ssl.SSLPermission "getSSLSessionContext";
+    permission javax.security.auth.AuthPermission "doAsPrivileged";
+    permission javax.security.auth.PrivateCredentialPermission "* * \"*\"",
+                                                               "read";
+    // java.base module (@jdk.Exported Permissions)
+    permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA";
+    // java.desktop module
+    permission java.awt.AWTPermission "createRobot";
+    permission javax.sound.sampled.AudioPermission "play";
+    // java.logging module
+    permission java.util.logging.LoggingPermission "control", "";
+    // java.management module
+    permission java.lang.management.ManagementPermission "control";
+    permission javax.management.MBeanPermission "*", "getAttribute";
+    permission javax.management.MBeanServerPermission "createMBeanServer";
+    permission javax.management.MBeanTrustPermission "register";
+    permission javax.management.remote.SubjectDelegationPermission "*";
+    // java.security.jgss module
+    permission javax.security.auth.kerberos.DelegationPermission "\"*\" \"*\"";
+    permission javax.security.auth.kerberos.ServicePermission "*", "accept";
+    // java.sql module
+    permission java.sql.SQLPermission "setLog";
+    // javax.xml.bind module
+    permission javax.xml.bind.JAXBPermission "setDatatypeConverter";
+    // javax.xml.ws module
+    permission javax.xml.ws.WebServicePermission "publishEndpoint";
+    // java.smartcardio module
+    permission javax.smartcardio.CardPermission "*", "*";
+    // jdk.attach module (@jdk.Exported Permissions)
+    permission com.sun.tools.attach.AttachPermission "attachVirtualMachine";
+    // jdk.jdi module (@jdk.Exported Permissions)
+    permission com.sun.jdi.JDIPermission "virtualMachineManager";
+    // jdk.security.jgss module (@jdk.Exported Permissions)
+    permission com.sun.security.jgss.InquireSecContextPermission "*"; 
+};
+
+grant
+    // java.base module
+    principal javax.security.auth.x500.X500Principal "CN=Duke",
+    // java.management module
+    principal javax.management.remote.JMXPrincipal "Duke",
+    // java.security.jgss module
+    principal javax.security.auth.kerberos.KerberosPrincipal "duke@openjdk.org",
+    // jdk.security.auth module (@jdk.Exported Principals)
+    principal com.sun.security.auth.UserPrincipal "Duke",
+    principal com.sun.security.auth.NTDomainPrincipal "openjdk.org",
+    principal com.sun.security.auth.NTSid
+        "S-1-5-21-3623811015-3361044348-30300820-1013",
+    principal com.sun.security.auth.NTUserPrincipal "Duke",
+    principal com.sun.security.auth.UnixNumericUserPrincipal "0",
+    principal com.sun.security.auth.UnixPrincipal "duke" {
+    permission java.util.PropertyPermission "user.home", "read";
+};
+
+grant
+    // java.security.jgss module
+    principal javax.security.auth.kerberos.KerberosPrincipal "duke@openjdk.org"
+{
+    // test that ${{self}} expansion works 
+    permission javax.security.auth.kerberos.ServicePermission "${{self}}",
+                                                              "accept";
+};
diff --git a/jdk/test/sun/security/provider/certpath/OCSP/OCSPSingleExtensions.java b/jdk/test/sun/security/provider/certpath/OCSP/OCSPSingleExtensions.java
index f9dde0f..1a29c28 100644
--- a/jdk/test/sun/security/provider/certpath/OCSP/OCSPSingleExtensions.java
+++ b/jdk/test/sun/security/provider/certpath/OCSP/OCSPSingleExtensions.java
@@ -26,16 +26,16 @@
  * @bug 8074064
  * @summary OCSPResponse.SingleResponse objects do not parse singleExtensions
  * @modules java.base/sun.security.x509
- * @run main/othervm sun.security.provider.certpath.OCSPSingleExtensions
+ *          java.base/sun.security.provider.certpath
+ * @run main/othervm OCSPSingleExtensions
  */
 
-package sun.security.provider.certpath;
-
 import java.io.*;
 import java.util.*;
 import java.security.cert.*;
 
 import sun.security.x509.SerialNumber;
+import sun.security.provider.certpath.*;
 
 /*
  * Tester note:
diff --git a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqExtensionTests.java b/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqExtensionTests.java
deleted file mode 100644
index 4d79876..0000000
--- a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqExtensionTests.java
+++ /dev/null
@@ -1,346 +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 sun.security.ssl;
-
-/*
- * @test
- * @bug 8046321
- * @summary OCSP Stapling for TLS (CertStatusReqExtension tests)
- * @build CertStatusReqExtensionTests BogusStatusRequest TestCase TestUtils
- * @run main/othervm sun.security.ssl.CertStatusReqExtensionTests
- */
-
-import java.io.IOException;
-import java.util.*;
-import java.nio.ByteBuffer;
-
-/*
- * Checks that the hash value for a certificate's issuer name is generated
- * correctly. Requires any certificate that is not self-signed.
- *
- * NOTE: this test uses Sun private classes which are subject to change.
- */
-public class CertStatusReqExtensionTests {
-
-    private static final boolean debug = false;
-
-    // Default status_request extension (type = ocsp, OCSPStatusRequest
-    // with no responder IDs or extensions
-    private static final byte[] CSRE_DEF_OSR = {1, 0, 0, 0, 0};
-
-    // A status_request extension using a user-defined type (0xFF) and
-    // an underlying no-Responder ID/no-extension OCSPStatusRequest
-    private static final byte[] CSRE_TYPE_FF = {-1, 0, 0, 0, 0};
-
-    // A CertStatusReqExtension with 5 ResponderIds and 1 Extension
-    private static final byte[] CSRE_REQ_RID_EXTS = {
-           1,    0,  -13,    0,   59,  -95,   57,   48,
-          55,   49,   16,   48,   14,    6,    3,   85,
-           4,   10,   19,    7,   83,  111,  109,  101,
-          73,  110,   99,   49,   16,   48,   14,    6,
-           3,   85,    4,   11,   19,    7,   83,  111,
-         109,  101,   80,   75,   73,   49,   17,   48,
-          15,    6,    3,   85,    4,    3,   19,    8,
-          83,  111,  109,  101,   79,   67,   83,   80,
-           0,   68,  -95,   66,   48,   64,   49,   13,
-          48,   11,    6,    3,   85,    4,   10,   19,
-           4,   79,  104,   77,  121,   49,   14,   48,
-          12,    6,    3,   85,    4,   11,   19,    5,
-          66,  101,   97,  114,  115,   49,   15,   48,
-          13,    6,    3,   85,    4,   11,   19,    6,
-          84,  105,  103,  101,  114,  115,   49,   14,
-          48,   12,    6,    3,   85,    4,    3,   19,
-           5,   76,  105,  111,  110,  115,    0,   58,
-         -95,   56,   48,   54,   49,   16,   48,   14,
-           6,    3,   85,    4,   10,   19,    7,   67,
-         111,  109,  112,   97,  110,  121,   49,   13,
-          48,   11,    6,    3,   85,    4,   11,   19,
-           4,   87,  101,  115,  116,   49,   19,   48,
-          17,    6,    3,   85,    4,    3,   19,   10,
-          82,  101,  115,  112,  111,  110,  100,  101,
-         114,   49,    0,   24,  -94,   22,    4,   20,
-         -67,  -36,  114,  121,   92,  -79,  116,   -1,
-         102, -107,    7,  -21,   18, -113,   64,   76,
-          96,   -7,  -66,  -63,    0,   24,  -94,   22,
-           4,   20,  -51,  -69,  107,  -82,  -39,  -87,
-          45,   25,   41,   28,  -76,  -68,  -11, -110,
-         -94,  -97,   62,   47,   58, -125,    0,   51,
-          48,   49,   48,   47,    6,    9,   43,    6,
-           1,    5,    5,    7,   48,    1,    2,    4,
-          34,    4,   32,  -26,  -81, -120,  -61, -127,
-         -79,    0,  -39,  -54,   49,    3,  -51,  -57,
-         -85,   19, -126,   94,   -2,   21,   26,   98,
-           6,  105,  -35,  -37,  -29,  -73,  101,   53,
-          44,   15,  -19
-    };
-
-    public static void main(String[] args) throws Exception {
-        Map<String, TestCase> testList =
-                new LinkedHashMap<String, TestCase>() {{
-            put("CTOR (default)", testCtorDefault);
-            put("CTOR (int, StatusRequest)", testCtorStatReqs);
-            put("CTOR (HandshakeInStream, length, getReqType, getRequest)",
-                    testCtorInStream);
-        }};
-
-        TestUtils.runTests(testList);
-    }
-
-    public static final TestCase testCtorDefault = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                CertStatusReqExtension csreDef = new CertStatusReqExtension();
-                HandshakeOutStream hsout =
-                        new HandshakeOutStream(null);
-                csreDef.send(hsout);
-                TestUtils.valueCheck(wrapExtData(null), hsout.toByteArray());
-
-                // The length should be 4 (2 bytes for the type, 2 for the
-                // encoding of zero-length
-                if (csreDef.length() != 4) {
-                    throw new RuntimeException("Incorrect length from " +
-                            "default object.  Expected 4, got " +
-                            csreDef.length());
-                }
-
-                // Since there's no data, there are no status_type or request
-                // data fields defined.  Both should return null in this case
-                if (csreDef.getType() != null) {
-                    throw new RuntimeException("Default CSRE returned " +
-                            "non-null status_type");
-                } else if (csreDef.getRequest() != null) {
-                    throw new RuntimeException("Default CSRE returned " +
-                            "non-null request object");
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    public static final TestCase testCtorStatReqs = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                HandshakeOutStream hsout =
-                        new HandshakeOutStream(null);
-                StatusRequest basicStatReq = new OCSPStatusRequest();
-
-                // Create an extension using a default-style OCSPStatusRequest
-                // (no responder IDs, no extensions).
-                CertStatusReqExtension csre1 = new CertStatusReqExtension(
-                        StatusRequestType.OCSP, basicStatReq);
-                csre1.send(hsout);
-                TestUtils.valueCheck(wrapExtData(CSRE_DEF_OSR),
-                        hsout.toByteArray());
-                hsout.reset();
-
-                // Create the extension using a StatusRequestType not already
-                // instantiated as a static StatusRequestType
-                // (e.g. OCSP/OCSP_MULTI)
-                CertStatusReqExtension csre2 =
-                        new CertStatusReqExtension(StatusRequestType.get(-1),
-                                basicStatReq);
-                csre2.send(hsout);
-                TestUtils.valueCheck(wrapExtData(CSRE_TYPE_FF),
-                        hsout.toByteArray());
-
-                // Create the extension using a StatusRequest that
-                // does not match the status_type field
-                // This should throw an IllegalArgumentException
-                try {
-                    CertStatusReqExtension csreBadRequest =
-                            new CertStatusReqExtension(StatusRequestType.OCSP,
-                                    new BogusStatusRequest());
-                    throw new RuntimeException("Constructor accepted a " +
-                            "StatusRequest that is inconsistent with " +
-                            "the status_type");
-                } catch (IllegalArgumentException iae) { }
-
-                // We don't allow a null value for the StatusRequestType
-                // parameter in this constructor.
-                try {
-                    CertStatusReqExtension csreBadRequest =
-                            new CertStatusReqExtension(null, basicStatReq);
-                    throw new RuntimeException("Constructor accepted a " +
-                            "null StatusRequestType");
-                } catch (NullPointerException npe) { }
-
-                // We also don't allow a null value for the StatusRequest
-                // parameter in this constructor.
-                try {
-                    CertStatusReqExtension csreBadRequest =
-                            new CertStatusReqExtension(StatusRequestType.OCSP,
-                                    null);
-                    throw new RuntimeException("Constructor accepted a " +
-                            "null StatusRequest");
-                } catch (NullPointerException npe) { }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor that builds the ob ject using data from
-    // a HandshakeInStream
-    // This also tests the length, getReqType and getRequest methods
-    public static final TestCase testCtorInStream = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            OCSPStatusRequest osr;
-
-            try {
-                // To simulate the extension coming in a ServerHello, the
-                // type and length would already be read by HelloExtensions
-                // and there is no extension data
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(new byte[0]));
-                CertStatusReqExtension csre =
-                        new CertStatusReqExtension(hsis, hsis.available());
-                // Verify length/type/request
-                if (csre.length() != 4) {
-                     throw new RuntimeException("Invalid length: received " +
-                            csre.length() + ", expected 4");
-                } else if (csre.getType() != null) {
-                    throw new RuntimeException("Non-null type from default " +
-                            "extension");
-                } else if (csre.getRequest() != null) {
-                    throw new RuntimeException("Non-null request from default " +
-                            "extension");
-                }
-
-                // Try the an extension with a default OCSPStatusRequest
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(CSRE_DEF_OSR));
-                csre = new CertStatusReqExtension(hsis, hsis.available());
-                if (csre.length() != (CSRE_DEF_OSR.length + 4)) {
-                    throw new RuntimeException("Invalid length: received " +
-                            csre.length() + ", expected " +
-                            CSRE_DEF_OSR.length + 4);
-                } else if (!csre.getType().equals(StatusRequestType.OCSP)) {
-                    throw new RuntimeException("Unknown status_type: " +
-                            String.format("0x%02X", csre.getType().id));
-                } else {
-                    osr = (OCSPStatusRequest)csre.getRequest();
-                    if (!osr.getResponderIds().isEmpty() ||
-                            !osr.getExtensions().isEmpty()) {
-                        throw new RuntimeException("Non-default " +
-                                "OCSPStatusRequest found in extension");
-                    }
-                }
-
-                // Try with a non-default extension
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(CSRE_REQ_RID_EXTS));
-                csre = new CertStatusReqExtension(hsis, hsis.available());
-                if (csre.length() != (CSRE_REQ_RID_EXTS.length + 4)) {
-                    throw new RuntimeException("Invalid length: received " +
-                            csre.length() + ", expected " +
-                            CSRE_REQ_RID_EXTS.length + 4);
-                } else if (!(csre.getType().equals(StatusRequestType.OCSP))) {
-                    throw new RuntimeException("Unknown status_type: " +
-                            String.format("0x%02X", csre.getType().id));
-                } else {
-                    osr = (OCSPStatusRequest)csre.getRequest();
-                    if (osr.getResponderIds().size() != 5 ||
-                            osr.getExtensions().size() != 1) {
-                        throw new RuntimeException("Incorrect number of " +
-                                "ResponderIds or Extensions found in " +
-                                "OCSPStatusRequest");
-                    }
-                }
-
-                // Create a CSRE that asserts status_request and has the
-                // proper length, but really is a bunch of random junk inside
-                // In this case, it will create an UnknownStatusRequest to
-                // handle the unparseable data.
-                byte[] junkData = new byte[48];
-                Random r = new Random(System.currentTimeMillis());
-                r.nextBytes(junkData);
-                junkData[0] = 7;        // Ensure it isn't a valid status_type
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(junkData));
-                csre = new CertStatusReqExtension(hsis, hsis.available());
-                StatusRequest sr = csre.getRequest();
-                if (!(sr instanceof UnknownStatusRequest)) {
-                    throw new RuntimeException("Expected returned status " +
-                            "request to be of type UnknownStatusRequest but " +
-                            "received " + sr.getClass().getName());
-                } else if (csre.length() != (junkData.length + 4)) {
-                    throw new RuntimeException("Invalid length: received " +
-                            csre.length() + ", expected " +
-                            junkData.length + 4);
-                }
-
-                // Set the leading byte to 1 (OCSP type) and run again
-                // It should pass the argument check and fail trying to parse
-                // the underlying StatusRequest.
-                junkData[0] = (byte)StatusRequestType.OCSP.id;
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(junkData));
-                try {
-                    csre = new CertStatusReqExtension(hsis, hsis.available());
-                    throw new RuntimeException("Expected CTOR exception did " +
-                            "not occur");
-                } catch (IOException ioe) { }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Take CSRE extension data and add extension type and length decorations
-    private static byte[] wrapExtData(byte[] extData) {
-        int bufferLen = (extData != null ? extData.length : 0) + 4;
-        ByteBuffer bb = ByteBuffer.allocate(bufferLen);
-        bb.putShort((short)ExtensionType.EXT_STATUS_REQUEST.id);
-        bb.putShort((short)(extData != null ? extData.length: 0));
-        if (extData != null) {
-            bb.put(extData);
-        }
-        return bb.array();
-    }
-}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqItemV2Tests.java b/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqItemV2Tests.java
deleted file mode 100644
index 1238d5e..0000000
--- a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqItemV2Tests.java
+++ /dev/null
@@ -1,463 +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 sun.security.ssl;
-
-/*
- * @test
- * @bug 8046321
- * @summary OCSP Stapling for TLS (CertStatusReqItemv2 tests)
- * @build CertStatusReqItemV2Tests BogusStatusRequest TestCase TestUtils
- * @run main/othervm sun.security.ssl.CertStatusReqItemV2Tests
- */
-
-import java.security.cert.*;
-import java.util.*;
-import java.nio.ByteBuffer;
-import javax.net.ssl.SSLException;
-import javax.security.auth.x500.X500Principal;
-import sun.security.provider.certpath.ResponderId;
-import sun.security.provider.certpath.OCSPNonceExtension;
-
-/*
- * Checks that the hash value for a certificate's issuer name is generated
- * correctly. Requires any certificate that is not self-signed.
- *
- * NOTE: this test uses Sun private classes which are subject to change.
- */
-public class CertStatusReqItemV2Tests {
-
-    private static final boolean debug = false;
-
-    private static final byte[] DEF_CSRIV2_OCSP_MULTI_BYTES = {
-           2,    0,    4,    0,    0,    0,    0
-    };
-
-    private static final byte[] DEF_CSRIV2_OCSP_BYTES = {
-           1,    0,    4,    0,    0,    0,    0
-    };
-
-    // This is a CSRIV2 (ocsp_multi) that has a single
-    // responder ID and no extensions.
-    private static final byte[] CSRIV2_1RID = {
-            2,    0,   32,     0,   28,    0,   26,  -95,
-           24,   48,   22,    49,   20,   48,   18,    6,
-            3,   85,    4,     3,   19,   11,   79,   67,
-           83,   80,   32,    83,  105,  103,  110,  101,
-          114,    0 ,   0
-    };
-
-    // This is a CSRIV2 (ocsp_multi) that has a single
-    // responder ID and no extensions.  The request_length
-    // field is too short in this case.
-    private static final byte[] CSRIV2_LENGTH_TOO_SHORT = {
-            2,    0,   27,     0,   28,    0,   26,  -95,
-           24,   48,   22,    49,   20,   48,   18,    6,
-            3,   85,    4,     3,   19,   11,   79,   67,
-           83,   80,   32,    83,  105,  103,  110,  101,
-          114,    0 ,   0
-    };
-
-    // This is a CSRIV2 (ocsp_multi) that has a single
-    // responder ID and no extensions.  The request_length
-    // field is too long in this case.
-    private static final byte[] CSRIV2_LENGTH_TOO_LONG = {
-            2,    0,   54,     0,   28,    0,   26,  -95,
-           24,   48,   22,    49,   20,   48,   18,    6,
-            3,   85,    4,     3,   19,   11,   79,   67,
-           83,   80,   32,    83,  105,  103,  110,  101,
-          114,    0 ,   0
-    };
-
-    // A CSRIV2 (ocsp) with one Responder ID (byName: CN=OCSP Signer)
-    // and a nonce extension (32 bytes).
-    private static final byte[] CSRIV2_OCSP_1RID_1EXT = {
-            1,    0,   83,    0,   28,    0,   26,  -95,
-           24,   48,   22,   49,   20,   48,   18,    6,
-            3,   85,    4,    3,   19,   11,   79,   67,
-           83,   80,   32,   83,  105,  103,  110,  101,
-          114,    0,   51,   48,   49,   48,   47,    6,
-            9,   43,    6,    1,    5,    5,    7,   48,
-            1,    2,    4,   34,    4,   32,  -34,  -83,
-          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
-          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
-          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
-          -66,  -17,  -34,  -83,  -66,  -17
-    };
-
-    public static void main(String[] args) throws Exception {
-        Map<String, TestCase> testList =
-                new LinkedHashMap<String, TestCase>() {{
-            put("CTOR (Default)", testCtorTypeStatReq);
-            put("CTOR (Byte array)", testCtorByteArray);
-            put("CTOR (invalid lengths)", testCtorInvalidLengths);
-        }};
-
-        TestUtils.runTests(testList);
-    }
-
-    public static final TestCase testCtorTypeStatReq = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                // Attempt to create CSRIv2 objects using null pointers
-                // for either parameter.  In either case NPE should be thrown
-                CertStatusReqItemV2 csriNull;
-                try {
-                    csriNull = new CertStatusReqItemV2(null,
-                            new OCSPStatusRequest());
-                    throw new RuntimeException("Did not catch expected NPE " +
-                            "for null status_type parameter");
-                } catch (NullPointerException npe) { }
-
-                try {
-                    csriNull = new CertStatusReqItemV2(StatusRequestType.OCSP,
-                            null);
-                    throw new RuntimeException("Did not catch expected NPE " +
-                            "for null StatusRequest parameter");
-                } catch (NullPointerException npe) { }
-
-                // Create an "ocsp_multi" type request using a default
-                // (no Responder IDs, no Extensions) OCSPStatusRequest
-                CertStatusReqItemV2 csriMulti =
-                        new CertStatusReqItemV2(StatusRequestType.OCSP_MULTI,
-                                new OCSPStatusRequest());
-                HandshakeOutStream hsout = new HandshakeOutStream(null);
-                csriMulti.send(hsout);
-                TestUtils.valueCheck(DEF_CSRIV2_OCSP_MULTI_BYTES,
-                        hsout.toByteArray());
-                hsout.reset();
-
-                // Create an "ocsp" type request using a default
-                // (no Responder IDs, no Extensions) OCSPStatusRequest
-                CertStatusReqItemV2 csriSingle =
-                        new CertStatusReqItemV2(StatusRequestType.OCSP,
-                                new OCSPStatusRequest(new LinkedList<>(),
-                                        new LinkedList<>()));
-                csriSingle.send(hsout);
-                TestUtils.valueCheck(DEF_CSRIV2_OCSP_BYTES,
-                        hsout.toByteArray());
-
-                // Create the CertStatusRequestItemV2 with a user-defined
-                // StatusRequestType value
-                CertStatusReqItemV2 csriNine =
-                        new CertStatusReqItemV2(StatusRequestType.get(9),
-                                new OCSPStatusRequest(null, null));
-                if (csriNine.getType().id != 9) {
-                    throw new RuntimeException("Expected status_type = 9, " +
-                            "got " + csriNine.getType().id);
-                } else {
-                    StatusRequest sr = csriNine.getRequest();
-                    if (!(sr instanceof OCSPStatusRequest)) {
-                        throw new RuntimeException("Expected " +
-                                "OCSPStatusRequest, got " +
-                                sr.getClass().getName());
-                    }
-                }
-
-                // Create the CertStatusRequestItemV2 with a StatusRequest
-                // that does not match the status_type argument.
-                // We expect IllegalArgumentException in this case.
-                try {
-                    CertStatusReqItemV2 csriBadSR = new CertStatusReqItemV2(
-                            StatusRequestType.OCSP_MULTI,
-                            new BogusStatusRequest());
-                    throw new RuntimeException("Constructor accepted a " +
-                            "StatusRequest that is inconsistent with " +
-                            "the status_type");
-                } catch (IllegalArgumentException iae) {
-                    // The expected result...nothing to do here
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor form that takes the data from a byte array
-    public static final TestCase testCtorByteArray = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                StatusRequestType sType;
-                StatusRequest sReq;
-                ResponderId checkRid =
-                        new ResponderId(new X500Principal("CN=OCSP Signer"));
-                Extension checkExt = new OCSPNonceExtension(32);
-
-                CertStatusReqItemV2 csriv =
-                        new CertStatusReqItemV2(CSRIV2_OCSP_1RID_1EXT);
-                sType = csriv.getType();
-                if (sType != StatusRequestType.OCSP) {
-                    throw new RuntimeException("Unexpected StatusRequestType " +
-                            sType.getClass().getName());
-                }
-
-                sReq = csriv.getRequest();
-                if (sReq instanceof OCSPStatusRequest) {
-                    OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
-                    List<ResponderId> ridList = osr.getResponderIds();
-                    List<Extension> extList = osr.getExtensions();
-
-                    if (ridList.size() != 1 || !ridList.contains(checkRid)) {
-                        throw new RuntimeException("Responder list mismatch");
-                    } else if (extList.size() !=  1 ||
-                            !extList.get(0).getId().equals(checkExt.getId())) {
-                        throw new RuntimeException("Extension list mismatch");
-                    }
-                } else {
-                    throw new RuntimeException("Expected OCSPStatusRequest " +
-                            "from decoded bytes, got " +
-                            sReq.getClass().getName());
-                }
-
-                // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
-                // type will be forcibly set and the outer length field will
-                // be correct.
-                // The constructor should create a StatusRequestType object
-                // and an UnknownStatusRequest object consisting of the
-                // data segment.
-                byte[] junkData = new byte[48];
-                Random r = new Random(System.currentTimeMillis());
-                r.nextBytes(junkData);
-                junkData[0] = 7;        // status_type = 7
-                junkData[1] = 0;
-                junkData[2] = 45;       // request_length = 45
-                csriv = new CertStatusReqItemV2(junkData);
-
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType.id != junkData[0]) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected 7, got " + sType.id);
-                }
-                if (sReq instanceof UnknownStatusRequest) {
-                    // Verify the underlying StatusRequest bytes have been
-                    // preserved correctly.
-                    HandshakeOutStream hsout = new HandshakeOutStream(null);
-                    sReq.send(hsout);
-                    byte[] srDataOut = hsout.toByteArray();
-                    TestUtils.valueCheck(srDataOut, junkData, 0, 3,
-                            srDataOut.length);
-                } else {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected UnknownStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                // Test the parsing of the default OCSP/OCSP_MULTI extensions
-                // and make sure the underlying StatusRequestType and
-                // StatusRequest objects are correct.
-                csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_MULTI_BYTES);
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType != StatusRequestType.OCSP_MULTI) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected OCSP_MULTI (2), got " + sType.id);
-                }
-                if (!(sReq instanceof OCSPStatusRequest)) {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected OCSPStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_BYTES);
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType != StatusRequestType.OCSP) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected OCSP (1), got " + sType.id);
-                }
-                if (!(sReq instanceof OCSPStatusRequest)) {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected OCSPStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    public static final TestCase testCtorInvalidLengths = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                try {
-                    CertStatusReqItemV2 csriTooShort =
-                            new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_SHORT);
-                    throw new RuntimeException("Expected exception not thrown");
-                } catch (SSLException ssle) { }
-
-                try {
-                    CertStatusReqItemV2 csriTooLong =
-                            new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_LONG);
-                    throw new RuntimeException("Expected exception not thrown");
-                } catch (SSLException ssle) { }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor form that takes the data from HandshakeInputStream
-    public static final TestCase testCtorInputStream = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                StatusRequestType sType;
-                StatusRequest sReq;
-                ResponderId checkRid =
-                        new ResponderId(new X500Principal("CN=OCSP Signer"));
-                Extension checkExt = new OCSPNonceExtension(32);
-
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(CSRIV2_OCSP_1RID_1EXT));
-                CertStatusReqItemV2 csriv = new CertStatusReqItemV2(hsis);
-                sType = csriv.getType();
-                if (sType != StatusRequestType.OCSP) {
-                    throw new RuntimeException("Unexpected StatusRequestType " +
-                            sType.getClass().getName());
-                }
-
-                sReq = csriv.getRequest();
-                if (sReq instanceof OCSPStatusRequest) {
-                    OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
-                    List<ResponderId> ridList = osr.getResponderIds();
-                    List<Extension> extList = osr.getExtensions();
-
-                    if (ridList.size() != 1 || !ridList.contains(checkRid)) {
-                        throw new RuntimeException("Responder list mismatch");
-                    } else if (extList.size() !=  1 ||
-                            !extList.get(0).getId().equals(checkExt.getId())) {
-                        throw new RuntimeException("Extension list mismatch");
-                    }
-                } else {
-                    throw new RuntimeException("Expected OCSPStatusRequest " +
-                            "from decoded bytes, got " +
-                            sReq.getClass().getName());
-                }
-
-                // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
-                // type will be forcibly set and the outer length field will
-                // be correct.
-                // The constructor should create a StatusRequestType object
-                // and an UnknownStatusRequest object consisting of the
-                // data segment.
-                byte[] junkData = new byte[48];
-                Random r = new Random(System.currentTimeMillis());
-                r.nextBytes(junkData);
-                junkData[0] = 7;        // status_type = 7
-                junkData[1] = 0;
-                junkData[2] = 45;       // request_length = 45
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(junkData));
-                csriv = new CertStatusReqItemV2(hsis);
-
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType.id != junkData[0]) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected 7, got " + sType.id);
-                }
-                if (sReq instanceof UnknownStatusRequest) {
-                    // Verify the underlying StatusRequest bytes have been
-                    // preserved correctly.
-                    HandshakeOutStream hsout = new HandshakeOutStream(null);
-                    sReq.send(hsout);
-                    byte[] srDataOut = hsout.toByteArray();
-                    TestUtils.valueCheck(srDataOut, junkData, 0, 3,
-                            srDataOut.length);
-                } else {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected UnknownStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                // Test the parsing of the default OCSP/OCSP_MULTI extensions
-                // and make sure the underlying StatusRequestType and
-                // StatusRequest objects are correct.
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(
-                        ByteBuffer.wrap(DEF_CSRIV2_OCSP_MULTI_BYTES));
-                csriv = new CertStatusReqItemV2(hsis);
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType != StatusRequestType.OCSP_MULTI) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected OCSP_MULTI (2), got " + sType.id);
-                }
-                if (!(sReq instanceof OCSPStatusRequest)) {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected OCSPStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(DEF_CSRIV2_OCSP_BYTES));
-                csriv = new CertStatusReqItemV2(hsis);
-                sType = csriv.getType();
-                sReq = csriv.getRequest();
-                if (sType != StatusRequestType.OCSP) {
-                    throw new RuntimeException("StatusRequestType mismatch: " +
-                            "expected OCSP (1), got " + sType.id);
-                }
-                if (!(sReq instanceof OCSPStatusRequest)) {
-                    throw new RuntimeException("StatusRequest mismatch: " +
-                            "expected OCSPStatusRequest, got " +
-                            sReq.getClass().getName());
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqListV2ExtensionTests.java b/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqListV2ExtensionTests.java
deleted file mode 100644
index b8c8013..0000000
--- a/jdk/test/sun/security/ssl/StatusStapling/CertStatusReqListV2ExtensionTests.java
+++ /dev/null
@@ -1,413 +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 sun.security.ssl;
-
-/*
- * @test
- * @bug 8046321
- * @summary OCSP Stapling for TLS (CertStatusReqListV2Extension tests)
- * @build CertStatusReqListV2ExtensionTests TestCase TestUtils
- * @run main/othervm sun.security.ssl.CertStatusReqListV2ExtensionTests
- */
-
-import java.io.IOException;
-import java.util.*;
-import java.nio.ByteBuffer;
-import javax.net.ssl.*;
-
-/*
- * Checks that the hash value for a certificate's issuer name is generated
- * correctly. Requires any certificate that is not self-signed.
- *
- * NOTE: this test uses Sun private classes which are subject to change.
- */
-public class CertStatusReqListV2ExtensionTests {
-
-    private static final boolean debug = false;
-
-    // Default status_request_v2 extension with two items
-    // 1. Type = ocsp_multi, OCSPStatusRequest is default
-    // 2. Type = ocsp, OCSPStatusRequest is default
-    private static final byte[] CSRLV2_DEF = {
-           0,   14,    2,    0,    4,    0,    0,    0,
-           0,    1,    0,    4,    0,    0,    0,    0
-    };
-
-    // A status_request_v2 where the item list length is
-    // longer than the provided data
-    private static final byte[] CSRLV2_LEN_TOO_LONG = {
-           0,   18,    2,    0,    4,    0,    0,    0,
-           0,    1,    0,    4,    0,    0,    0,    0
-    };
-
-    // A status_request_v2 where the item list length is
-    // shorter than the provided data
-    private static final byte[] CSRLV2_LEN_TOO_SHORT = {
-           0,   11,    2,    0,    4,    0,    0,    0,
-           0,    1,    0,    4,    0,    0,    0,    0
-    };
-
-    // A status_request_v2 extension with a zero-length
-    // certificate_status_req_list (not allowed by the spec)
-    private static final byte[] CSRLV2_INVALID_ZEROLEN = {0, 0};
-
-    // A status_request_v2 extension with two items (ocsp_multi and ocsp)
-    // using OCSPStatusRequests with 5 ResponderIds and 1 Extension each.
-    private static final byte[] CSRLV2_TWO_NON_DEF_ITEMS = {
-            2,   90,    2,    1,   42,    0,  -13,    0,
-           59,  -95,   57,   48,   55,   49,   16,   48,
-           14,    6,    3,   85,    4,   10,   19,    7,
-           83,  111,  109,  101,   73,  110,   99,   49,
-           16,   48,   14,    6,    3,   85,    4,   11,
-           19,    7,   83,  111,  109,  101,   80,   75,
-           73,   49,   17,   48,   15,    6,    3,   85,
-            4,    3,   19,    8,   83,  111,  109,  101,
-           79,   67,   83,   80,    0,   68,  -95,   66,
-           48,   64,   49,   13,   48,   11,    6,    3,
-           85,    4,   10,   19,    4,   79,  104,   77,
-          121,   49,   14,   48,   12,    6,    3,   85,
-            4,   11,   19,    5,   66,  101,   97,  114,
-          115,   49,   15,   48,   13,    6,    3,   85,
-            4,   11,   19,    6,   84,  105,  103,  101,
-          114,  115,   49,   14,   48,   12,    6,    3,
-           85,    4,    3,   19,    5,   76,  105,  111,
-          110,  115,    0,   58,  -95,   56,   48,   54,
-           49,   16,   48,   14,    6,    3,   85,    4,
-           10,   19,    7,   67,  111,  109,  112,   97,
-          110,  121,   49,   13,   48,   11,    6,    3,
-           85,    4,   11,   19,    4,   87,  101,  115,
-          116,   49,   19,   48,   17,    6,    3,   85,
-            4,    3,   19,   10,   82,  101,  115,  112,
-          111,  110,  100,  101,  114,   49,    0,   24,
-          -94,   22,    4,   20,  -67,  -36,  114,  121,
-           92,  -79,  116,   -1,  102, -107,    7,  -21,
-           18, -113,   64,   76,   96,   -7,  -66,  -63,
-            0,   24,  -94,   22,    4,   20,  -51,  -69,
-          107,  -82,  -39,  -87,   45,   25,   41,   28,
-          -76,  -68,  -11, -110,  -94,  -97,   62,   47,
-           58, -125,    0,   51,   48,   49,   48,   47,
-            6,    9,   43,    6,    1,    5,    5,    7,
-           48,    1,    2,    4,   34,    4,   32,  -26,
-          -81, -120,  -61, -127,  -79,    0,  -39,  -54,
-           49,    3,  -51,  -57,  -85,   19, -126,   94,
-           -2,   21,   26,   98,    6,  105,  -35,  -37,
-          -29,  -73,  101,   53,   44,   15,  -19,    1,
-            1,   42,    0,  -13,    0,   59,  -95,   57,
-           48,   55,   49,   16,   48,   14,    6,    3,
-           85,    4,   10,   19,    7,   83,  111,  109,
-          101,   73,  110,   99,   49,   16,   48,   14,
-            6,    3,   85,    4,   11,   19,    7,   83,
-          111,  109,  101,   80,   75,   73,   49,   17,
-           48,   15,    6,    3,   85,    4,    3,   19,
-            8,   83,  111,  109,  101,   79,   67,   83,
-           80,    0,   68,  -95,   66,   48,   64,   49,
-           13,   48,   11,    6,    3,   85,    4,   10,
-           19,    4,   79,  104,   77,  121,   49,   14,
-           48,   12,    6,    3,   85,    4,   11,   19,
-            5,   66,  101,   97,  114,  115,   49,   15,
-           48,   13,    6,    3,   85,    4,   11,   19,
-            6,   84,  105,  103,  101,  114,  115,   49,
-           14,   48,   12,    6,    3,   85,    4,    3,
-           19,    5,   76,  105,  111,  110,  115,    0,
-           58,  -95,   56,   48,   54,   49,   16,   48,
-           14,    6,    3,   85,    4,   10,   19,    7,
-           67,  111,  109,  112,   97,  110,  121,   49,
-           13,   48,   11,    6,    3,   85,    4,   11,
-           19,    4,   87,  101,  115,  116,   49,   19,
-           48,   17,    6,    3,   85,    4,    3,   19,
-           10,   82,  101,  115,  112,  111,  110,  100,
-          101,  114,   49,    0,   24,  -94,   22,    4,
-           20,  -67,  -36,  114,  121,   92,  -79,  116,
-           -1,  102, -107,    7,  -21,   18, -113,   64,
-           76,   96,   -7,  -66,  -63,    0,   24,  -94,
-           22,    4,   20,  -51,  -69,  107,  -82,  -39,
-          -87,   45,   25,   41,   28,  -76,  -68,  -11,
-         -110,  -94,  -97,   62,   47,   58, -125,    0,
-           51,   48,   49,   48,   47,    6,    9,   43,
-            6,    1,    5,    5,    7,   48,    1,    2,
-            4,   34,    4,   32,  -26,  -81, -120,  -61,
-         -127,  -79,    0,  -39,  -54,   49,    3,  -51,
-          -57,  -85,   19, -126,   94,   -2,   21,   26,
-           98,    6,  105,  -35,  -37,  -29,  -73,  101,
-           53,   44,   15,  -19
-    };
-
-    public static void main(String[] args) throws Exception {
-        Map<String, TestCase> testList =
-                new LinkedHashMap<String, TestCase>() {{
-            put("CTOR (default)", testCtorDefault);
-            put("CTOR (List<CertStatusReqItemV2)", testCtorItemList);
-            put("CTOR (HandshakeInStream, getRequestList",
-                    testCtorInStream);
-        }};
-
-        TestUtils.runTests(testList);
-    }
-
-    public static final TestCase testCtorDefault = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                CertStatusReqListV2Extension csrlV2 =
-                        new CertStatusReqListV2Extension();
-                HandshakeOutStream hsout = new HandshakeOutStream(null);
-                csrlV2.send(hsout);
-                TestUtils.valueCheck(wrapExtData(new byte[0]),
-                        hsout.toByteArray());
-
-                // The length should be 4 (2 bytes for the type, 2 for the
-                // encoding of zero-length
-                if (csrlV2.length() != 4) {
-                    throw new RuntimeException("Incorrect length from " +
-                            "default object.  Expected 4, got " +
-                            csrlV2.length());
-                }
-
-                // Since there's no data, there are no status_type or request
-                // data fields defined.  An empty, unmodifiable list should be
-                // returned when obtained from the extension.
-                List<CertStatusReqItemV2> itemList = csrlV2.getRequestItems();
-                if (!itemList.isEmpty()) {
-                    throw new RuntimeException("Default CSRLV2 returned " +
-                            "non-empty request list");
-                } else {
-                    try {
-                        itemList.add(new CertStatusReqItemV2(
-                                StatusRequestType.OCSP_MULTI,
-                                new OCSPStatusRequest()));
-                        throw new RuntimeException("Returned itemList is " +
-                                "modifiable!");
-                    } catch (UnsupportedOperationException uoe) { }
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    public static final TestCase testCtorItemList = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            OCSPStatusRequest osr = new OCSPStatusRequest();
-            List<CertStatusReqItemV2> noItems = Collections.emptyList();
-            List<CertStatusReqItemV2> defList =
-                    new ArrayList<CertStatusReqItemV2>() {{
-                add(new CertStatusReqItemV2(StatusRequestType.OCSP_MULTI, osr));
-                add(new CertStatusReqItemV2(StatusRequestType.OCSP, osr));
-            }};
-            List<CertStatusReqItemV2> unknownTypesList =
-                    new ArrayList<CertStatusReqItemV2>() {{
-                add(new CertStatusReqItemV2(StatusRequestType.get(8),
-                        new UnknownStatusRequest(new byte[0])));
-                add(new CertStatusReqItemV2(StatusRequestType.get(12),
-                        new UnknownStatusRequest(new byte[5])));
-            }};
-
-            try {
-                HandshakeOutStream hsout = new HandshakeOutStream(null);
-                StatusRequest basicStatReq = new OCSPStatusRequest();
-
-                // Create an extension using a default-style OCSPStatusRequest
-                // (no responder IDs, no extensions).
-                CertStatusReqListV2Extension csrlv2 =
-                        new CertStatusReqListV2Extension(defList);
-                csrlv2.send(hsout);
-                TestUtils.valueCheck(wrapExtData(CSRLV2_DEF),
-                        hsout.toByteArray());
-                hsout.reset();
-
-                // Create the extension using a StatusRequestType not already
-                // instantiated as a static StatusRequestType
-                // (e.g. OCSP/OCSP_MULTI)
-                csrlv2 = new CertStatusReqListV2Extension(unknownTypesList);
-                List<CertStatusReqItemV2> itemList = csrlv2.getRequestItems();
-                if (itemList.size() != unknownTypesList.size()) {
-                    throw new RuntimeException("Custom CSRLV2 returned " +
-                            "an incorrect number of items: expected " +
-                            unknownTypesList.size() + ", got " +
-                            itemList.size());
-                } else {
-                    // Verify that the list is unmodifiable
-                    try {
-                        itemList.add(new CertStatusReqItemV2(
-                                StatusRequestType.OCSP_MULTI,
-                                new OCSPStatusRequest()));
-                        throw new RuntimeException("Returned itemList is " +
-                                "modifiable!");
-                    } catch (UnsupportedOperationException uoe) { }
-                }
-
-                // Pass a null value for the item list.  This should throw
-                // an exception
-                try {
-                    CertStatusReqListV2Extension csrlv2Null =
-                            new CertStatusReqListV2Extension(null);
-                    throw new RuntimeException("Constructor accepted a " +
-                            "null request list");
-                } catch (NullPointerException npe) { }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor that builds the ob ject using data from
-    // a HandshakeInStream
-    // This also tests the length, getReqType and getRequest methods
-    public static final TestCase testCtorInStream = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            OCSPStatusRequest osr;
-            CertStatusReqListV2Extension csrlv2;
-
-            try {
-                // To simulate the extension coming in a ServerHello, the
-                // type and length would already be read by HelloExtensions
-                // and there is no extension data
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(new byte[0]));
-                csrlv2 = new CertStatusReqListV2Extension(hsis,
-                        hsis.available());
-
-                // Verify length/request list
-                if (csrlv2.length() != 4) {
-                     throw new RuntimeException("Invalid length: received " +
-                            csrlv2.length() + ", expected 4");
-                } else {
-                    List<CertStatusReqItemV2> itemList =
-                            csrlv2.getRequestItems();
-                    if (!itemList.isEmpty()) {
-                        throw new RuntimeException("Default CSRLV2 returned " +
-                                "non-empty request list");
-                    } else {
-                        try {
-                            itemList.add(new CertStatusReqItemV2(
-                                    StatusRequestType.OCSP_MULTI,
-                                    new OCSPStatusRequest()));
-                            throw new RuntimeException("Returned itemList is " +
-                                    "modifiable!");
-                        } catch (UnsupportedOperationException uoe) { }
-                    }
-                }
-
-                // Try the an extension with our basic client-generated
-                // status_request_v2 (2 items, ocsp_multi and ocsp, each with
-                // a default OCSPStatusRequest
-                hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_DEF));
-                csrlv2 = new CertStatusReqListV2Extension(hsis,
-                        hsis.available());
-                if (csrlv2.length() != (CSRLV2_DEF.length + 4)) {
-                    throw new RuntimeException("Invalid length: received " +
-                            csrlv2.length() + ", expected " +
-                            CSRLV2_DEF.length + 4);
-                } else {
-                    List<CertStatusReqItemV2> itemList =
-                            csrlv2.getRequestItems();
-                    if (itemList.size() != 2) {
-                        throw new RuntimeException("Unexpected number of " +
-                                "items request list, expected 2, got " +
-                                itemList.size());
-                    } else {
-                        try {
-                            itemList.add(new CertStatusReqItemV2(
-                                    StatusRequestType.OCSP_MULTI,
-                                    new OCSPStatusRequest()));
-                            throw new RuntimeException("Returned itemList is " +
-                                    "modifiable!");
-                        } catch (UnsupportedOperationException uoe) { }
-                    }
-                }
-
-                // Try incoming data with an illegal zero-length
-                // certificate_status_req_list
-                try {
-                    hsis = new HandshakeInStream();
-                    hsis.incomingRecord(
-                            ByteBuffer.wrap(CSRLV2_INVALID_ZEROLEN));
-                    csrlv2 = new CertStatusReqListV2Extension(hsis,
-                            hsis.available());
-                    throw new RuntimeException("Unxpected successful " +
-                            "object construction");
-                } catch (SSLException ssle) { }
-
-                // Try extensions where the certificate_status_req_list length
-                // is either too long or too short
-                try {
-                    hsis = new HandshakeInStream();
-                    hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_LEN_TOO_LONG));
-                    csrlv2 = new CertStatusReqListV2Extension(hsis,
-                            hsis.available());
-                    throw new RuntimeException("Unxpected successful " +
-                            "object construction");
-                } catch (SSLException ssle) { }
-
-                try {
-                    hsis = new HandshakeInStream();
-                    hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_LEN_TOO_SHORT));
-                    csrlv2 = new CertStatusReqListV2Extension(hsis,
-                            hsis.available());
-                    throw new RuntimeException("Unxpected successful " +
-                            "object construction");
-                } catch (SSLException ssle) { }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Take CSRE extension data and add extension type and length decorations
-    private static byte[] wrapExtData(byte[] extData) {
-        int bufferLen = extData.length + 4;
-        ByteBuffer bb = ByteBuffer.allocate(bufferLen);
-
-        bb.putShort((short)ExtensionType.EXT_STATUS_REQUEST_V2.id);
-        bb.putShort((short)extData.length);
-        if (extData.length != 0) {
-            bb.put(extData);
-        }
-        return bb.array();
-    }
-}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/OCSPStatusRequestTests.java b/jdk/test/sun/security/ssl/StatusStapling/OCSPStatusRequestTests.java
deleted file mode 100644
index eb61067..0000000
--- a/jdk/test/sun/security/ssl/StatusStapling/OCSPStatusRequestTests.java
+++ /dev/null
@@ -1,340 +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 sun.security.ssl;
-
-/*
- * @test
- * @bug 8046321
- * @summary OCSP Stapling for TLS (OCSPStatusRequestTests tests)
- * @build OCSPStatusRequestTests TestCase TestUtils
- * @run main/othervm sun.security.ssl.OCSPStatusRequestTests
- */
-
-import java.security.cert.*;
-import java.util.*;
-import java.nio.ByteBuffer;
-import javax.security.auth.x500.X500Principal;
-import sun.security.provider.certpath.ResponderId;
-import sun.security.provider.certpath.OCSPNonceExtension;
-
-/*
- * Checks that the hash value for a certificate's issuer name is generated
- * correctly. Requires any certificate that is not self-signed.
- *
- * NOTE: this test uses Sun private classes which are subject to change.
- */
-public class OCSPStatusRequestTests {
-
-    private static final boolean debug = false;
-
-    // The default (no Responder IDs or Extensions)
-    private static final byte[] DEF_OCSPREQ_BYTES = { 0, 0, 0, 0 };
-
-    // OCSP Extension with one Responder ID (byName: CN=OCSP Signer) and
-    // a nonce extension (32 bytes).
-    private static final byte[] OCSPREQ_1RID_1EXT = {
-            0,   28,    0,   26,  -95,   24,   48,   22,
-           49,   20,   48,   18,    6,    3,   85,    4,
-            3,   19,   11,   79,   67,   83,   80,   32,
-           83,  105,  103,  110,  101,  114,    0,   51,
-           48,   49,   48,   47,    6,    9,   43,    6,
-            1,    5,    5,    7,   48,    1,    2,    4,
-           34,    4,   32,  -34,  -83,  -66,  -17,  -34,
-          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
-          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
-          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
-          -83,  -66,  -17
-    };
-
-    public static void main(String[] args) throws Exception {
-        Map<String, TestCase> testList =
-                new LinkedHashMap<String, TestCase>() {{
-            put("CTOR (default)", testCtorDefault);
-            put("CTOR (Responder Id and Extension)", testCtorRidsExts);
-            put("CTOR (HandshakeInStream)", testCtorInStream);
-            put("CTOR (byte array)", testCtorByteArray);
-            put("Length tests", testLength);
-            put("Equals tests", testEquals);
-        }};
-
-        TestUtils.runTests(testList);
-    }
-
-    // Test the default constructor and its encoding
-    public static final TestCase testCtorDefault = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                // Create a OCSPStatusRequest with a single ResponderId
-                // and Extension
-                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
-                HandshakeOutStream hsout = new HandshakeOutStream(null);
-                osrDefault.send(hsout);
-                System.out.println("Encoded Result:");
-                TestUtils.dumpBytes(hsout.toByteArray());
-
-                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor form that allows the user to specify zero
-    // or more ResponderId objects and/or Extensions
-    public static final TestCase testCtorRidsExts = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                List<ResponderId> ridList = new LinkedList<ResponderId>() {{
-                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
-                }};
-                List<Extension> extList = new LinkedList<Extension>() {{
-                    add(new OCSPNonceExtension(32));
-                }};
-
-                // Default-style OCSPStatusRequest using both empty Lists and
-                // null inputs
-                OCSPStatusRequest osrDef1 =
-                        new OCSPStatusRequest(new LinkedList<ResponderId>(),
-                                null);
-                OCSPStatusRequest osrDef2 =
-                        new OCSPStatusRequest(null,
-                                new LinkedList<Extension>());
-                HandshakeOutStream hsout = new HandshakeOutStream(null);
-                osrDef1.send(hsout);
-                System.out.println("Encoded Result:");
-                TestUtils.dumpBytes(hsout.toByteArray());
-                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
-
-                hsout.reset();
-                osrDef2.send(hsout);
-                System.out.println("Encoded Result:");
-                TestUtils.dumpBytes(hsout.toByteArray());
-                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
-
-                hsout.reset();
-                OCSPStatusRequest osrWithItems =
-                        new OCSPStatusRequest(ridList, extList);
-                osrWithItems.send(hsout);
-                System.out.println("Encoded Result:");
-                byte[] encodedData = hsout.toByteArray();
-                TestUtils.dumpBytes(encodedData);
-                // Check everything except the last 32 bytes (nonce data)
-                TestUtils.valueCheck(OCSPREQ_1RID_1EXT, encodedData, 0, 0,
-                        encodedData.length - 32);
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor that builds the ob ject using data from
-    // a HandshakeInStream
-    public static final TestCase testCtorInStream = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                ResponderId checkRid =
-                        new ResponderId(new X500Principal("CN=OCSP Signer"));
-                Extension checkExt = new OCSPNonceExtension(32);
-
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
-                OCSPStatusRequest osr = new OCSPStatusRequest(hsis);
-
-                List<ResponderId> ridList = osr.getResponderIds();
-                List<Extension> extList = osr.getExtensions();
-
-                if (ridList.size() != 1 || !ridList.contains(checkRid)) {
-                    throw new RuntimeException("Responder list mismatch");
-                } else if (extList.size() !=  1 ||
-                        !extList.get(0).getId().equals(checkExt.getId())) {
-                    throw new RuntimeException("Extension list mismatch");
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the constructor form that takes the data from a byte array
-    public static final TestCase testCtorByteArray = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                ResponderId checkRid =
-                        new ResponderId(new X500Principal("CN=OCSP Signer"));
-                Extension checkExt = new OCSPNonceExtension(32);
-
-                OCSPStatusRequest osr =
-                        new OCSPStatusRequest(OCSPREQ_1RID_1EXT);
-
-                List<ResponderId> ridList = osr.getResponderIds();
-                List<Extension> extList = osr.getExtensions();
-
-                if (ridList.size() != 1 || !ridList.contains(checkRid)) {
-                    throw new RuntimeException("Responder list mismatch");
-                } else if (extList.size() !=  1 ||
-                        !extList.get(0).getId().equals(checkExt.getId())) {
-                    throw new RuntimeException("Extension list mismatch");
-                }
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the length functions for both default and non-default
-    // OCSPStatusRequest objects
-    public static final TestCase testLength = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
-                OCSPStatusRequest osr = new OCSPStatusRequest(hsis);
-                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
-
-                if (osrDefault.length() != DEF_OCSPREQ_BYTES.length) {
-                    throw new RuntimeException("Invalid length for default: " +
-                            "Expected" + DEF_OCSPREQ_BYTES.length +
-                            ", received " + osrDefault.length());
-                } else if (osr.length() != OCSPREQ_1RID_1EXT.length) {
-                    throw new RuntimeException("Invalid length for default: " +
-                            "Expected" + OCSPREQ_1RID_1EXT.length +
-                            ", received " + osr.length());
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test the equals method with default and non-default objects
-    public static final TestCase testEquals = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            try {
-                // Make two different lists with the same ResponderId values
-                // and also make a extension list
-                List<ResponderId> ridList1 = new LinkedList<ResponderId>() {{
-                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
-                }};
-                List<ResponderId> ridList2 = new LinkedList<ResponderId>() {{
-                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
-                }};
-                List<Extension> extList = new LinkedList<Extension>() {{
-                    add(new OCSPNonceExtension(32));
-                }};
-
-                // We expect two default OCSP objects to be equal
-                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
-                if (!osrDefault.equals(new OCSPStatusRequest())) {
-                    throw new RuntimeException("Default OCSPStatusRequest" +
-                            " equality test failed");
-                }
-
-                // null test (expect false return)
-                if (osrDefault.equals(null)) {
-                    throw new RuntimeException("OCSPStatusRequest matched" +
-                            " unexpectedly");
-                }
-
-                // Self-reference test
-                OCSPStatusRequest osrSelfRef = osrDefault;
-                if (!osrDefault.equals(osrSelfRef)) {
-                    throw new RuntimeException("Default OCSPStatusRequest" +
-                            " equality test failed");
-                }
-
-                // Two OCSPStatusRequests with matching ResponderIds should
-                // be considered equal
-                OCSPStatusRequest osrByList1 =
-                        new OCSPStatusRequest(ridList1, null);
-                OCSPStatusRequest osrByList2 = new OCSPStatusRequest(ridList2,
-                        Collections.emptyList());
-                if (!osrByList1.equals(osrByList2)) {
-                    throw new RuntimeException("Single Responder ID " +
-                            "OCSPStatusRequest equality test failed");
-                }
-
-                // We expect OCSPStatusRequests with different nonces to be
-                // considered unequal.
-                HandshakeInStream hsis = new HandshakeInStream();
-                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
-                OCSPStatusRequest osrStream = new OCSPStatusRequest(hsis);
-                OCSPStatusRequest osrRidExt = new OCSPStatusRequest(ridList1,
-                        extList);
-                if (osrStream.equals(osrRidExt)) {
-                    throw new RuntimeException("OCSPStatusRequest matched" +
-                            " unexpectedly");
-                }
-
-                pass = Boolean.TRUE;
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/StatusResponseManagerTests.java b/jdk/test/sun/security/ssl/StatusStapling/StatusResponseManagerTests.java
deleted file mode 100644
index 198657e..0000000
--- a/jdk/test/sun/security/ssl/StatusStapling/StatusResponseManagerTests.java
+++ /dev/null
@@ -1,455 +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 sun.security.ssl;
-
-/*
- * @test
- * @bug 8046321
- * @summary OCSP Stapling for TLS (StatusResponseManager tests)
- * @library ../../../../java/security/testlibrary
- * @build CertificateBuilder SimpleOCSPServer
- * @build StatusResponseManagerTests TestCase TestUtils
- * @run main/othervm -Djavax.net.debug=ssl:respmgr
- *      sun.security.ssl.StatusResponseManagerTests
- */
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.cert.*;
-import java.util.*;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.PublicKey;
-import java.util.concurrent.TimeUnit;
-
-import sun.security.testlibrary.SimpleOCSPServer;
-import sun.security.testlibrary.CertificateBuilder;
-
-/*
- * Checks that the hash value for a certificate's issuer name is generated
- * correctly. Requires any certificate that is not self-signed.
- *
- * NOTE: this test uses Sun private classes which are subject to change.
- */
-public class StatusResponseManagerTests {
-
-    private static final boolean debug = true;
-    private static final boolean ocspDebug = false;
-
-    // PKI components we will need for this test
-    static String passwd = "passphrase";
-    static String ROOT_ALIAS = "root";
-    static String INT_ALIAS = "intermediate";
-    static String SSL_ALIAS = "ssl";
-    static KeyStore rootKeystore;           // Root CA Keystore
-    static KeyStore intKeystore;            // Intermediate CA Keystore
-    static KeyStore serverKeystore;         // SSL Server Keystore
-    static KeyStore trustStore;             // SSL Client trust store
-    static X509Certificate rootCert;
-    static X509Certificate intCert;
-    static X509Certificate sslCert;
-    static SimpleOCSPServer rootOcsp;       // Root CA OCSP Responder
-    static int rootOcspPort;                // Port number for root OCSP
-    static SimpleOCSPServer intOcsp;        // Intermediate CA OCSP Responder
-    static int intOcspPort;                 // Port number for intermed. OCSP
-
-    static X509Certificate[] chain;
-
-    public static void main(String[] args) throws Exception {
-        Map<String, TestCase> testList =
-                new LinkedHashMap<String, TestCase>() {{
-            put("Basic OCSP fetch test", testOcspFetch);
-            put("Clear StatusResponseManager cache", testClearSRM);
-            put("Basic OCSP_MULTI fetch test", testOcspMultiFetch);
-            put("Test Cache Expiration", testCacheExpiry);
-        }};
-
-        // Create the CAs and OCSP responders
-        createPKI();
-
-        // Grab the certificates and make a chain we can reuse for tests
-        sslCert = (X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);
-        intCert = (X509Certificate)intKeystore.getCertificate(INT_ALIAS);
-        rootCert = (X509Certificate)rootKeystore.getCertificate(ROOT_ALIAS);
-        chain = new X509Certificate[3];
-        chain[0] = sslCert;
-        chain[1] = intCert;
-        chain[2] = rootCert;
-
-        TestUtils.runTests(testList);
-
-        intOcsp.stop();
-        rootOcsp.stop();
-    }
-
-    // Test a simple RFC 6066 server-side fetch
-    public static final TestCase testOcspFetch = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            StatusResponseManager srm = new StatusResponseManager();
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            StatusRequest oReq = new OCSPStatusRequest();
-
-            try {
-                // Get OCSP responses for non-root certs in the chain
-                Map<X509Certificate, byte[]> responseMap = srm.get(
-                        StatusRequestType.OCSP, oReq, chain, 5000,
-                        TimeUnit.MILLISECONDS);
-
-                // There should be one entry in the returned map and
-                // one entry in the cache when the operation is complete.
-                if (responseMap.size() != 1) {
-                    message = "Incorrect number of responses: expected 1, got "
-                            + responseMap.size();
-                } else if (!responseMap.containsKey(sslCert)) {
-                    message = "Response map key is incorrect, expected " +
-                            sslCert.getSubjectX500Principal().toString();
-                } else if (srm.size() != 1) {
-                    message = "Incorrect number of cache entries: " +
-                            "expected 1, got " + srm.size();
-                } else {
-                    pass = Boolean.TRUE;
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test clearing the StatusResponseManager cache.
-    public static final TestCase testClearSRM = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            StatusResponseManager srm = new StatusResponseManager();
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            StatusRequest oReq = new OCSPStatusRequest();
-
-            try {
-                // Get OCSP responses for non-root certs in the chain
-                srm.get(StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
-                        TimeUnit.MILLISECONDS);
-
-                // There should be two entries in the returned map and
-                // two entries in the cache when the operation is complete.
-                if (srm.size() != 2) {
-                    message = "Incorrect number of responses: expected 2, got "
-                            + srm.size();
-                } else {
-                    // Next, clear the SRM, then check the size again
-                    srm.clear();
-                    if (srm.size() != 0) {
-                        message = "Incorrect number of responses: expected 0," +
-                                " got " + srm.size();
-                    } else {
-                        pass = Boolean.TRUE;
-                    }
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test a simple RFC 6961 server-side fetch
-    public static final TestCase testOcspMultiFetch = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            StatusResponseManager srm = new StatusResponseManager();
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            StatusRequest oReq = new OCSPStatusRequest();
-
-            try {
-                // Get OCSP responses for non-root certs in the chain
-                Map<X509Certificate, byte[]> responseMap = srm.get(
-                        StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
-                        TimeUnit.MILLISECONDS);
-
-                // There should be two entries in the returned map and
-                // two entries in the cache when the operation is complete.
-                if (responseMap.size() != 2) {
-                    message = "Incorrect number of responses: expected 2, got "
-                            + responseMap.size();
-                } else if (!responseMap.containsKey(sslCert) ||
-                        !responseMap.containsKey(intCert)) {
-                    message = "Response map keys are incorrect, expected " +
-                            sslCert.getSubjectX500Principal().toString() +
-                            " and " +
-                            intCert.getSubjectX500Principal().toString();
-                } else if (srm.size() != 2) {
-                    message = "Incorrect number of cache entries: " +
-                            "expected 2, got " + srm.size();
-                } else {
-                    pass = Boolean.TRUE;
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    // Test cache expiration
-    public static final TestCase testCacheExpiry = new TestCase() {
-        @Override
-        public Map.Entry<Boolean, String> runTest() {
-            // For this test, we will set the cache expiry to 5 seconds
-            System.setProperty("jdk.tls.stapling.cacheLifetime", "5");
-            StatusResponseManager srm = new StatusResponseManager();
-            Boolean pass = Boolean.FALSE;
-            String message = null;
-            StatusRequest oReq = new OCSPStatusRequest();
-
-            try {
-                // Get OCSP responses for non-root certs in the chain
-                srm.get(StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
-                        TimeUnit.MILLISECONDS);
-
-                // There should be two entries in the returned map and
-                // two entries in the cache when the operation is complete.
-                if (srm.size() != 2) {
-                    message = "Incorrect number of responses: expected 2, got "
-                            + srm.size();
-                } else {
-                    // Next, wait for more than 5 seconds so the responses
-                    // in the SRM will expire.
-                    Thread.sleep(7000);
-                    if (srm.size() != 0) {
-                        message = "Incorrect number of responses: expected 0," +
-                                " got " + srm.size();
-                    } else {
-                        pass = Boolean.TRUE;
-                    }
-                }
-            } catch (Exception e) {
-                e.printStackTrace(System.out);
-                message = e.getClass().getName();
-            }
-
-            // Set the cache lifetime back to the default
-            System.setProperty("jdk.tls.stapling.cacheLifetime", "");
-            return new AbstractMap.SimpleEntry<>(pass, message);
-        }
-    };
-
-    /**
-     * Creates the PKI components necessary for this test, including
-     * Root CA, Intermediate CA and SSL server certificates, the keystores
-     * for each entity, a client trust store, and starts the OCSP responders.
-     */
-    private static void createPKI() throws Exception {
-        CertificateBuilder cbld = new CertificateBuilder();
-        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
-        keyGen.initialize(2048);
-        KeyStore.Builder keyStoreBuilder =
-                KeyStore.Builder.newInstance("PKCS12", null,
-                        new KeyStore.PasswordProtection(passwd.toCharArray()));
-
-        // Generate Root, IntCA, EE keys
-        KeyPair rootCaKP = keyGen.genKeyPair();
-        log("Generated Root CA KeyPair");
-        KeyPair intCaKP = keyGen.genKeyPair();
-        log("Generated Intermediate CA KeyPair");
-        KeyPair sslKP = keyGen.genKeyPair();
-        log("Generated SSL Cert KeyPair");
-
-        // Set up the Root CA Cert
-        cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany");
-        cbld.setPublicKey(rootCaKP.getPublic());
-        cbld.setSerialNumber(new BigInteger("1"));
-        // Make a 3 year validity starting from 60 days ago
-        long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
-        long end = start + TimeUnit.DAYS.toMillis(1085);
-        cbld.setValidity(new Date(start), new Date(end));
-        addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic());
-        addCommonCAExts(cbld);
-        // Make our Root CA Cert!
-        X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(),
-                "SHA256withRSA");
-        log("Root CA Created:\n" + certInfo(rootCert));
-
-        // Now build a keystore and add the keys and cert
-        rootKeystore = keyStoreBuilder.getKeyStore();
-        Certificate[] rootChain = {rootCert};
-        rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),
-                passwd.toCharArray(), rootChain);
-
-        // Now fire up the OCSP responder
-        rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);
-        rootOcsp.enableLog(ocspDebug);
-        rootOcsp.setNextUpdateInterval(3600);
-        rootOcsp.start();
-        Thread.sleep(1000);         // Give the server a second to start up
-        rootOcspPort = rootOcsp.getPort();
-        String rootRespURI = "http://localhost:" + rootOcspPort;
-        log("Root OCSP Responder URI is " + rootRespURI);
-
-        // Now that we have the root keystore and OCSP responder we can
-        // create our intermediate CA.
-        cbld.reset();
-        cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany");
-        cbld.setPublicKey(intCaKP.getPublic());
-        cbld.setSerialNumber(new BigInteger("100"));
-        // Make a 2 year validity starting from 30 days ago
-        start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30);
-        end = start + TimeUnit.DAYS.toMillis(730);
-        cbld.setValidity(new Date(start), new Date(end));
-        addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic());
-        addCommonCAExts(cbld);
-        cbld.addAIAExt(Collections.singletonList(rootRespURI));
-        // Make our Intermediate CA Cert!
-        X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(),
-                "SHA256withRSA");
-        log("Intermediate CA Created:\n" + certInfo(intCaCert));
-
-        // Provide intermediate CA cert revocation info to the Root CA
-        // OCSP responder.
-        Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
-            new HashMap<>();
-        revInfo.put(intCaCert.getSerialNumber(),
-                new SimpleOCSPServer.CertStatusInfo(
-                        SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
-        rootOcsp.updateStatusDb(revInfo);
-
-        // Now build a keystore and add the keys, chain and root cert as a TA
-        intKeystore = keyStoreBuilder.getKeyStore();
-        Certificate[] intChain = {intCaCert, rootCert};
-        intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(),
-                passwd.toCharArray(), intChain);
-        intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
-
-        // Now fire up the Intermediate CA OCSP responder
-        intOcsp = new SimpleOCSPServer(intKeystore, passwd,
-                INT_ALIAS, null);
-        intOcsp.enableLog(ocspDebug);
-        intOcsp.setNextUpdateInterval(3600);
-        intOcsp.start();
-        Thread.sleep(1000);
-        intOcspPort = intOcsp.getPort();
-        String intCaRespURI = "http://localhost:" + intOcspPort;
-        log("Intermediate CA OCSP Responder URI is " + intCaRespURI);
-
-        // Last but not least, let's make our SSLCert and add it to its own
-        // Keystore
-        cbld.reset();
-        cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany");
-        cbld.setPublicKey(sslKP.getPublic());
-        cbld.setSerialNumber(new BigInteger("4096"));
-        // Make a 1 year validity starting from 7 days ago
-        start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7);
-        end = start + TimeUnit.DAYS.toMillis(365);
-        cbld.setValidity(new Date(start), new Date(end));
-
-        // Add extensions
-        addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic());
-        boolean[] kuBits = {true, false, true, false, false, false,
-            false, false, false};
-        cbld.addKeyUsageExt(kuBits);
-        List<String> ekuOids = new ArrayList<>();
-        ekuOids.add("1.3.6.1.5.5.7.3.1");
-        ekuOids.add("1.3.6.1.5.5.7.3.2");
-        cbld.addExtendedKeyUsageExt(ekuOids);
-        cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost"));
-        cbld.addAIAExt(Collections.singletonList(intCaRespURI));
-        // Make our SSL Server Cert!
-        X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(),
-                "SHA256withRSA");
-        log("SSL Certificate Created:\n" + certInfo(sslCert));
-
-        // Provide SSL server cert revocation info to the Intermeidate CA
-        // OCSP responder.
-        revInfo = new HashMap<>();
-        revInfo.put(sslCert.getSerialNumber(),
-                new SimpleOCSPServer.CertStatusInfo(
-                        SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
-        intOcsp.updateStatusDb(revInfo);
-
-        // Now build a keystore and add the keys, chain and root cert as a TA
-        serverKeystore = keyStoreBuilder.getKeyStore();
-        Certificate[] sslChain = {sslCert, intCaCert, rootCert};
-        serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(),
-                passwd.toCharArray(), sslChain);
-        serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
-
-        // And finally a Trust Store for the client
-        trustStore = keyStoreBuilder.getKeyStore();
-        trustStore.setCertificateEntry(ROOT_ALIAS, rootCert);
-    }
-
-    private static void addCommonExts(CertificateBuilder cbld,
-            PublicKey subjKey, PublicKey authKey) throws IOException {
-        cbld.addSubjectKeyIdExt(subjKey);
-        cbld.addAuthorityKeyIdExt(authKey);
-    }
-
-    private static void addCommonCAExts(CertificateBuilder cbld)
-            throws IOException {
-        cbld.addBasicConstraintsExt(true, true, -1);
-        // Set key usage bits for digitalSignature, keyCertSign and cRLSign
-        boolean[] kuBitSettings = {true, false, false, false, false, true,
-            true, false, false};
-        cbld.addKeyUsageExt(kuBitSettings);
-    }
-
-    /**
-     * Helper routine that dumps only a few cert fields rather than
-     * the whole toString() output.
-     *
-     * @param cert An X509Certificate to be displayed
-     *
-     * @return The {@link String} output of the issuer, subject and
-     * serial number
-     */
-    private static String certInfo(X509Certificate cert) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Issuer: ").append(cert.getIssuerX500Principal()).
-                append("\n");
-        sb.append("Subject: ").append(cert.getSubjectX500Principal()).
-                append("\n");
-        sb.append("Serial: ").append(cert.getSerialNumber()).append("\n");
-        return sb.toString();
-    }
-
-    /**
-     * Log a message on stdout
-     *
-     * @param message The message to log
-     */
-    private static void log(String message) {
-        if (debug) {
-            System.out.println(message);
-        }
-    }
-}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/TEST.properties b/jdk/test/sun/security/ssl/StatusStapling/TEST.properties
index 72f8b4c..41268dd 100644
--- a/jdk/test/sun/security/ssl/StatusStapling/TEST.properties
+++ b/jdk/test/sun/security/ssl/StatusStapling/TEST.properties
@@ -1 +1,6 @@
+modules = \
+    java.base/sun.security.provider.certpath \
+    java.base/sun.security.util \
+    java.base/sun.security.x509 \
+    java.base/sun.security.ssl
 bootclasspath.dirs=.
diff --git a/jdk/test/sun/security/ssl/StatusStapling/TestRun.java b/jdk/test/sun/security/ssl/StatusStapling/TestRun.java
new file mode 100644
index 0000000..ce6e6f1
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/TestRun.java
@@ -0,0 +1,36 @@
+/*
+ * 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 8046321
+ * @library ../../../../java/security/testlibrary
+ * @build CertificateBuilder SimpleOCSPServer
+ * @run main/othervm java.base/sun.security.ssl.CertStatusReqExtensionTests
+ * @run main/othervm java.base/sun.security.ssl.CertStatusReqItemV2Tests
+ * @run main/othervm java.base/sun.security.ssl.CertStatusReqListV2ExtensionTests
+ * @run main/othervm java.base/sun.security.ssl.OCSPStatusRequestTests
+ * @run main/othervm -Djavax.net.debug=ssl:respmgr java.base/sun.security.ssl.StatusResponseManagerTests
+ * @summary OCSP Stapling for TLS
+ */
+
diff --git a/jdk/test/sun/security/ssl/StatusStapling/BogusStatusRequest.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/BogusStatusRequest.java
similarity index 100%
rename from jdk/test/sun/security/ssl/StatusStapling/BogusStatusRequest.java
rename to jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/BogusStatusRequest.java
diff --git a/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqExtensionTests.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqExtensionTests.java
new file mode 100644
index 0000000..da7030e
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqExtensionTests.java
@@ -0,0 +1,338 @@
+/*
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.util.*;
+import java.nio.ByteBuffer;
+
+/*
+ * Checks that the hash value for a certificate's issuer name is generated
+ * correctly. Requires any certificate that is not self-signed.
+ *
+ * NOTE: this test uses Sun private classes which are subject to change.
+ */
+public class CertStatusReqExtensionTests {
+
+    private static final boolean debug = false;
+
+    // Default status_request extension (type = ocsp, OCSPStatusRequest
+    // with no responder IDs or extensions
+    private static final byte[] CSRE_DEF_OSR = {1, 0, 0, 0, 0};
+
+    // A status_request extension using a user-defined type (0xFF) and
+    // an underlying no-Responder ID/no-extension OCSPStatusRequest
+    private static final byte[] CSRE_TYPE_FF = {-1, 0, 0, 0, 0};
+
+    // A CertStatusReqExtension with 5 ResponderIds and 1 Extension
+    private static final byte[] CSRE_REQ_RID_EXTS = {
+           1,    0,  -13,    0,   59,  -95,   57,   48,
+          55,   49,   16,   48,   14,    6,    3,   85,
+           4,   10,   19,    7,   83,  111,  109,  101,
+          73,  110,   99,   49,   16,   48,   14,    6,
+           3,   85,    4,   11,   19,    7,   83,  111,
+         109,  101,   80,   75,   73,   49,   17,   48,
+          15,    6,    3,   85,    4,    3,   19,    8,
+          83,  111,  109,  101,   79,   67,   83,   80,
+           0,   68,  -95,   66,   48,   64,   49,   13,
+          48,   11,    6,    3,   85,    4,   10,   19,
+           4,   79,  104,   77,  121,   49,   14,   48,
+          12,    6,    3,   85,    4,   11,   19,    5,
+          66,  101,   97,  114,  115,   49,   15,   48,
+          13,    6,    3,   85,    4,   11,   19,    6,
+          84,  105,  103,  101,  114,  115,   49,   14,
+          48,   12,    6,    3,   85,    4,    3,   19,
+           5,   76,  105,  111,  110,  115,    0,   58,
+         -95,   56,   48,   54,   49,   16,   48,   14,
+           6,    3,   85,    4,   10,   19,    7,   67,
+         111,  109,  112,   97,  110,  121,   49,   13,
+          48,   11,    6,    3,   85,    4,   11,   19,
+           4,   87,  101,  115,  116,   49,   19,   48,
+          17,    6,    3,   85,    4,    3,   19,   10,
+          82,  101,  115,  112,  111,  110,  100,  101,
+         114,   49,    0,   24,  -94,   22,    4,   20,
+         -67,  -36,  114,  121,   92,  -79,  116,   -1,
+         102, -107,    7,  -21,   18, -113,   64,   76,
+          96,   -7,  -66,  -63,    0,   24,  -94,   22,
+           4,   20,  -51,  -69,  107,  -82,  -39,  -87,
+          45,   25,   41,   28,  -76,  -68,  -11, -110,
+         -94,  -97,   62,   47,   58, -125,    0,   51,
+          48,   49,   48,   47,    6,    9,   43,    6,
+           1,    5,    5,    7,   48,    1,    2,    4,
+          34,    4,   32,  -26,  -81, -120,  -61, -127,
+         -79,    0,  -39,  -54,   49,    3,  -51,  -57,
+         -85,   19, -126,   94,   -2,   21,   26,   98,
+           6,  105,  -35,  -37,  -29,  -73,  101,   53,
+          44,   15,  -19
+    };
+
+    public static void main(String[] args) throws Exception {
+        Map<String, TestCase> testList =
+                new LinkedHashMap<String, TestCase>() {{
+            put("CTOR (default)", testCtorDefault);
+            put("CTOR (int, StatusRequest)", testCtorStatReqs);
+            put("CTOR (HandshakeInStream, length, getReqType, getRequest)",
+                    testCtorInStream);
+        }};
+
+        TestUtils.runTests(testList);
+    }
+
+    public static final TestCase testCtorDefault = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                CertStatusReqExtension csreDef = new CertStatusReqExtension();
+                HandshakeOutStream hsout =
+                        new HandshakeOutStream(null);
+                csreDef.send(hsout);
+                TestUtils.valueCheck(wrapExtData(null), hsout.toByteArray());
+
+                // The length should be 4 (2 bytes for the type, 2 for the
+                // encoding of zero-length
+                if (csreDef.length() != 4) {
+                    throw new RuntimeException("Incorrect length from " +
+                            "default object.  Expected 4, got " +
+                            csreDef.length());
+                }
+
+                // Since there's no data, there are no status_type or request
+                // data fields defined.  Both should return null in this case
+                if (csreDef.getType() != null) {
+                    throw new RuntimeException("Default CSRE returned " +
+                            "non-null status_type");
+                } else if (csreDef.getRequest() != null) {
+                    throw new RuntimeException("Default CSRE returned " +
+                            "non-null request object");
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    public static final TestCase testCtorStatReqs = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                HandshakeOutStream hsout =
+                        new HandshakeOutStream(null);
+                StatusRequest basicStatReq = new OCSPStatusRequest();
+
+                // Create an extension using a default-style OCSPStatusRequest
+                // (no responder IDs, no extensions).
+                CertStatusReqExtension csre1 = new CertStatusReqExtension(
+                        StatusRequestType.OCSP, basicStatReq);
+                csre1.send(hsout);
+                TestUtils.valueCheck(wrapExtData(CSRE_DEF_OSR),
+                        hsout.toByteArray());
+                hsout.reset();
+
+                // Create the extension using a StatusRequestType not already
+                // instantiated as a static StatusRequestType
+                // (e.g. OCSP/OCSP_MULTI)
+                CertStatusReqExtension csre2 =
+                        new CertStatusReqExtension(StatusRequestType.get(-1),
+                                basicStatReq);
+                csre2.send(hsout);
+                TestUtils.valueCheck(wrapExtData(CSRE_TYPE_FF),
+                        hsout.toByteArray());
+
+                // Create the extension using a StatusRequest that
+                // does not match the status_type field
+                // This should throw an IllegalArgumentException
+                try {
+                    CertStatusReqExtension csreBadRequest =
+                            new CertStatusReqExtension(StatusRequestType.OCSP,
+                                    new BogusStatusRequest());
+                    throw new RuntimeException("Constructor accepted a " +
+                            "StatusRequest that is inconsistent with " +
+                            "the status_type");
+                } catch (IllegalArgumentException iae) { }
+
+                // We don't allow a null value for the StatusRequestType
+                // parameter in this constructor.
+                try {
+                    CertStatusReqExtension csreBadRequest =
+                            new CertStatusReqExtension(null, basicStatReq);
+                    throw new RuntimeException("Constructor accepted a " +
+                            "null StatusRequestType");
+                } catch (NullPointerException npe) { }
+
+                // We also don't allow a null value for the StatusRequest
+                // parameter in this constructor.
+                try {
+                    CertStatusReqExtension csreBadRequest =
+                            new CertStatusReqExtension(StatusRequestType.OCSP,
+                                    null);
+                    throw new RuntimeException("Constructor accepted a " +
+                            "null StatusRequest");
+                } catch (NullPointerException npe) { }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor that builds the ob ject using data from
+    // a HandshakeInStream
+    // This also tests the length, getReqType and getRequest methods
+    public static final TestCase testCtorInStream = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            OCSPStatusRequest osr;
+
+            try {
+                // To simulate the extension coming in a ServerHello, the
+                // type and length would already be read by HelloExtensions
+                // and there is no extension data
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(new byte[0]));
+                CertStatusReqExtension csre =
+                        new CertStatusReqExtension(hsis, hsis.available());
+                // Verify length/type/request
+                if (csre.length() != 4) {
+                     throw new RuntimeException("Invalid length: received " +
+                            csre.length() + ", expected 4");
+                } else if (csre.getType() != null) {
+                    throw new RuntimeException("Non-null type from default " +
+                            "extension");
+                } else if (csre.getRequest() != null) {
+                    throw new RuntimeException("Non-null request from default " +
+                            "extension");
+                }
+
+                // Try the an extension with a default OCSPStatusRequest
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(CSRE_DEF_OSR));
+                csre = new CertStatusReqExtension(hsis, hsis.available());
+                if (csre.length() != (CSRE_DEF_OSR.length + 4)) {
+                    throw new RuntimeException("Invalid length: received " +
+                            csre.length() + ", expected " +
+                            CSRE_DEF_OSR.length + 4);
+                } else if (!csre.getType().equals(StatusRequestType.OCSP)) {
+                    throw new RuntimeException("Unknown status_type: " +
+                            String.format("0x%02X", csre.getType().id));
+                } else {
+                    osr = (OCSPStatusRequest)csre.getRequest();
+                    if (!osr.getResponderIds().isEmpty() ||
+                            !osr.getExtensions().isEmpty()) {
+                        throw new RuntimeException("Non-default " +
+                                "OCSPStatusRequest found in extension");
+                    }
+                }
+
+                // Try with a non-default extension
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(CSRE_REQ_RID_EXTS));
+                csre = new CertStatusReqExtension(hsis, hsis.available());
+                if (csre.length() != (CSRE_REQ_RID_EXTS.length + 4)) {
+                    throw new RuntimeException("Invalid length: received " +
+                            csre.length() + ", expected " +
+                            CSRE_REQ_RID_EXTS.length + 4);
+                } else if (!(csre.getType().equals(StatusRequestType.OCSP))) {
+                    throw new RuntimeException("Unknown status_type: " +
+                            String.format("0x%02X", csre.getType().id));
+                } else {
+                    osr = (OCSPStatusRequest)csre.getRequest();
+                    if (osr.getResponderIds().size() != 5 ||
+                            osr.getExtensions().size() != 1) {
+                        throw new RuntimeException("Incorrect number of " +
+                                "ResponderIds or Extensions found in " +
+                                "OCSPStatusRequest");
+                    }
+                }
+
+                // Create a CSRE that asserts status_request and has the
+                // proper length, but really is a bunch of random junk inside
+                // In this case, it will create an UnknownStatusRequest to
+                // handle the unparseable data.
+                byte[] junkData = new byte[48];
+                Random r = new Random(System.currentTimeMillis());
+                r.nextBytes(junkData);
+                junkData[0] = 7;        // Ensure it isn't a valid status_type
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(junkData));
+                csre = new CertStatusReqExtension(hsis, hsis.available());
+                StatusRequest sr = csre.getRequest();
+                if (!(sr instanceof UnknownStatusRequest)) {
+                    throw new RuntimeException("Expected returned status " +
+                            "request to be of type UnknownStatusRequest but " +
+                            "received " + sr.getClass().getName());
+                } else if (csre.length() != (junkData.length + 4)) {
+                    throw new RuntimeException("Invalid length: received " +
+                            csre.length() + ", expected " +
+                            junkData.length + 4);
+                }
+
+                // Set the leading byte to 1 (OCSP type) and run again
+                // It should pass the argument check and fail trying to parse
+                // the underlying StatusRequest.
+                junkData[0] = (byte)StatusRequestType.OCSP.id;
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(junkData));
+                try {
+                    csre = new CertStatusReqExtension(hsis, hsis.available());
+                    throw new RuntimeException("Expected CTOR exception did " +
+                            "not occur");
+                } catch (IOException ioe) { }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Take CSRE extension data and add extension type and length decorations
+    private static byte[] wrapExtData(byte[] extData) {
+        int bufferLen = (extData != null ? extData.length : 0) + 4;
+        ByteBuffer bb = ByteBuffer.allocate(bufferLen);
+        bb.putShort((short)ExtensionType.EXT_STATUS_REQUEST.id);
+        bb.putShort((short)(extData != null ? extData.length: 0));
+        if (extData != null) {
+            bb.put(extData);
+        }
+        return bb.array();
+    }
+}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqItemV2Tests.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqItemV2Tests.java
new file mode 100644
index 0000000..0ff275b
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqItemV2Tests.java
@@ -0,0 +1,455 @@
+/*
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.security.cert.*;
+import java.util.*;
+import java.nio.ByteBuffer;
+import javax.net.ssl.SSLException;
+import javax.security.auth.x500.X500Principal;
+import sun.security.provider.certpath.ResponderId;
+import sun.security.provider.certpath.OCSPNonceExtension;
+
+/*
+ * Checks that the hash value for a certificate's issuer name is generated
+ * correctly. Requires any certificate that is not self-signed.
+ *
+ * NOTE: this test uses Sun private classes which are subject to change.
+ */
+public class CertStatusReqItemV2Tests {
+
+    private static final boolean debug = false;
+
+    private static final byte[] DEF_CSRIV2_OCSP_MULTI_BYTES = {
+           2,    0,    4,    0,    0,    0,    0
+    };
+
+    private static final byte[] DEF_CSRIV2_OCSP_BYTES = {
+           1,    0,    4,    0,    0,    0,    0
+    };
+
+    // This is a CSRIV2 (ocsp_multi) that has a single
+    // responder ID and no extensions.
+    private static final byte[] CSRIV2_1RID = {
+            2,    0,   32,     0,   28,    0,   26,  -95,
+           24,   48,   22,    49,   20,   48,   18,    6,
+            3,   85,    4,     3,   19,   11,   79,   67,
+           83,   80,   32,    83,  105,  103,  110,  101,
+          114,    0 ,   0
+    };
+
+    // This is a CSRIV2 (ocsp_multi) that has a single
+    // responder ID and no extensions.  The request_length
+    // field is too short in this case.
+    private static final byte[] CSRIV2_LENGTH_TOO_SHORT = {
+            2,    0,   27,     0,   28,    0,   26,  -95,
+           24,   48,   22,    49,   20,   48,   18,    6,
+            3,   85,    4,     3,   19,   11,   79,   67,
+           83,   80,   32,    83,  105,  103,  110,  101,
+          114,    0 ,   0
+    };
+
+    // This is a CSRIV2 (ocsp_multi) that has a single
+    // responder ID and no extensions.  The request_length
+    // field is too long in this case.
+    private static final byte[] CSRIV2_LENGTH_TOO_LONG = {
+            2,    0,   54,     0,   28,    0,   26,  -95,
+           24,   48,   22,    49,   20,   48,   18,    6,
+            3,   85,    4,     3,   19,   11,   79,   67,
+           83,   80,   32,    83,  105,  103,  110,  101,
+          114,    0 ,   0
+    };
+
+    // A CSRIV2 (ocsp) with one Responder ID (byName: CN=OCSP Signer)
+    // and a nonce extension (32 bytes).
+    private static final byte[] CSRIV2_OCSP_1RID_1EXT = {
+            1,    0,   83,    0,   28,    0,   26,  -95,
+           24,   48,   22,   49,   20,   48,   18,    6,
+            3,   85,    4,    3,   19,   11,   79,   67,
+           83,   80,   32,   83,  105,  103,  110,  101,
+          114,    0,   51,   48,   49,   48,   47,    6,
+            9,   43,    6,    1,    5,    5,    7,   48,
+            1,    2,    4,   34,    4,   32,  -34,  -83,
+          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
+          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
+          -66,  -17,  -34,  -83,  -66,  -17,  -34,  -83,
+          -66,  -17,  -34,  -83,  -66,  -17
+    };
+
+    public static void main(String[] args) throws Exception {
+        Map<String, TestCase> testList =
+                new LinkedHashMap<String, TestCase>() {{
+            put("CTOR (Default)", testCtorTypeStatReq);
+            put("CTOR (Byte array)", testCtorByteArray);
+            put("CTOR (invalid lengths)", testCtorInvalidLengths);
+        }};
+
+        TestUtils.runTests(testList);
+    }
+
+    public static final TestCase testCtorTypeStatReq = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                // Attempt to create CSRIv2 objects using null pointers
+                // for either parameter.  In either case NPE should be thrown
+                CertStatusReqItemV2 csriNull;
+                try {
+                    csriNull = new CertStatusReqItemV2(null,
+                            new OCSPStatusRequest());
+                    throw new RuntimeException("Did not catch expected NPE " +
+                            "for null status_type parameter");
+                } catch (NullPointerException npe) { }
+
+                try {
+                    csriNull = new CertStatusReqItemV2(StatusRequestType.OCSP,
+                            null);
+                    throw new RuntimeException("Did not catch expected NPE " +
+                            "for null StatusRequest parameter");
+                } catch (NullPointerException npe) { }
+
+                // Create an "ocsp_multi" type request using a default
+                // (no Responder IDs, no Extensions) OCSPStatusRequest
+                CertStatusReqItemV2 csriMulti =
+                        new CertStatusReqItemV2(StatusRequestType.OCSP_MULTI,
+                                new OCSPStatusRequest());
+                HandshakeOutStream hsout = new HandshakeOutStream(null);
+                csriMulti.send(hsout);
+                TestUtils.valueCheck(DEF_CSRIV2_OCSP_MULTI_BYTES,
+                        hsout.toByteArray());
+                hsout.reset();
+
+                // Create an "ocsp" type request using a default
+                // (no Responder IDs, no Extensions) OCSPStatusRequest
+                CertStatusReqItemV2 csriSingle =
+                        new CertStatusReqItemV2(StatusRequestType.OCSP,
+                                new OCSPStatusRequest(new LinkedList<>(),
+                                        new LinkedList<>()));
+                csriSingle.send(hsout);
+                TestUtils.valueCheck(DEF_CSRIV2_OCSP_BYTES,
+                        hsout.toByteArray());
+
+                // Create the CertStatusRequestItemV2 with a user-defined
+                // StatusRequestType value
+                CertStatusReqItemV2 csriNine =
+                        new CertStatusReqItemV2(StatusRequestType.get(9),
+                                new OCSPStatusRequest(null, null));
+                if (csriNine.getType().id != 9) {
+                    throw new RuntimeException("Expected status_type = 9, " +
+                            "got " + csriNine.getType().id);
+                } else {
+                    StatusRequest sr = csriNine.getRequest();
+                    if (!(sr instanceof OCSPStatusRequest)) {
+                        throw new RuntimeException("Expected " +
+                                "OCSPStatusRequest, got " +
+                                sr.getClass().getName());
+                    }
+                }
+
+                // Create the CertStatusRequestItemV2 with a StatusRequest
+                // that does not match the status_type argument.
+                // We expect IllegalArgumentException in this case.
+                try {
+                    CertStatusReqItemV2 csriBadSR = new CertStatusReqItemV2(
+                            StatusRequestType.OCSP_MULTI,
+                            new BogusStatusRequest());
+                    throw new RuntimeException("Constructor accepted a " +
+                            "StatusRequest that is inconsistent with " +
+                            "the status_type");
+                } catch (IllegalArgumentException iae) {
+                    // The expected result...nothing to do here
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor form that takes the data from a byte array
+    public static final TestCase testCtorByteArray = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                StatusRequestType sType;
+                StatusRequest sReq;
+                ResponderId checkRid =
+                        new ResponderId(new X500Principal("CN=OCSP Signer"));
+                Extension checkExt = new OCSPNonceExtension(32);
+
+                CertStatusReqItemV2 csriv =
+                        new CertStatusReqItemV2(CSRIV2_OCSP_1RID_1EXT);
+                sType = csriv.getType();
+                if (sType != StatusRequestType.OCSP) {
+                    throw new RuntimeException("Unexpected StatusRequestType " +
+                            sType.getClass().getName());
+                }
+
+                sReq = csriv.getRequest();
+                if (sReq instanceof OCSPStatusRequest) {
+                    OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
+                    List<ResponderId> ridList = osr.getResponderIds();
+                    List<Extension> extList = osr.getExtensions();
+
+                    if (ridList.size() != 1 || !ridList.contains(checkRid)) {
+                        throw new RuntimeException("Responder list mismatch");
+                    } else if (extList.size() !=  1 ||
+                            !extList.get(0).getId().equals(checkExt.getId())) {
+                        throw new RuntimeException("Extension list mismatch");
+                    }
+                } else {
+                    throw new RuntimeException("Expected OCSPStatusRequest " +
+                            "from decoded bytes, got " +
+                            sReq.getClass().getName());
+                }
+
+                // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
+                // type will be forcibly set and the outer length field will
+                // be correct.
+                // The constructor should create a StatusRequestType object
+                // and an UnknownStatusRequest object consisting of the
+                // data segment.
+                byte[] junkData = new byte[48];
+                Random r = new Random(System.currentTimeMillis());
+                r.nextBytes(junkData);
+                junkData[0] = 7;        // status_type = 7
+                junkData[1] = 0;
+                junkData[2] = 45;       // request_length = 45
+                csriv = new CertStatusReqItemV2(junkData);
+
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType.id != junkData[0]) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected 7, got " + sType.id);
+                }
+                if (sReq instanceof UnknownStatusRequest) {
+                    // Verify the underlying StatusRequest bytes have been
+                    // preserved correctly.
+                    HandshakeOutStream hsout = new HandshakeOutStream(null);
+                    sReq.send(hsout);
+                    byte[] srDataOut = hsout.toByteArray();
+                    TestUtils.valueCheck(srDataOut, junkData, 0, 3,
+                            srDataOut.length);
+                } else {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected UnknownStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                // Test the parsing of the default OCSP/OCSP_MULTI extensions
+                // and make sure the underlying StatusRequestType and
+                // StatusRequest objects are correct.
+                csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_MULTI_BYTES);
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType != StatusRequestType.OCSP_MULTI) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected OCSP_MULTI (2), got " + sType.id);
+                }
+                if (!(sReq instanceof OCSPStatusRequest)) {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected OCSPStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                csriv = new CertStatusReqItemV2(DEF_CSRIV2_OCSP_BYTES);
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType != StatusRequestType.OCSP) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected OCSP (1), got " + sType.id);
+                }
+                if (!(sReq instanceof OCSPStatusRequest)) {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected OCSPStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    public static final TestCase testCtorInvalidLengths = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                try {
+                    CertStatusReqItemV2 csriTooShort =
+                            new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_SHORT);
+                    throw new RuntimeException("Expected exception not thrown");
+                } catch (SSLException ssle) { }
+
+                try {
+                    CertStatusReqItemV2 csriTooLong =
+                            new CertStatusReqItemV2(CSRIV2_LENGTH_TOO_LONG);
+                    throw new RuntimeException("Expected exception not thrown");
+                } catch (SSLException ssle) { }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor form that takes the data from HandshakeInputStream
+    public static final TestCase testCtorInputStream = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                StatusRequestType sType;
+                StatusRequest sReq;
+                ResponderId checkRid =
+                        new ResponderId(new X500Principal("CN=OCSP Signer"));
+                Extension checkExt = new OCSPNonceExtension(32);
+
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(CSRIV2_OCSP_1RID_1EXT));
+                CertStatusReqItemV2 csriv = new CertStatusReqItemV2(hsis);
+                sType = csriv.getType();
+                if (sType != StatusRequestType.OCSP) {
+                    throw new RuntimeException("Unexpected StatusRequestType " +
+                            sType.getClass().getName());
+                }
+
+                sReq = csriv.getRequest();
+                if (sReq instanceof OCSPStatusRequest) {
+                    OCSPStatusRequest osr = (OCSPStatusRequest)sReq;
+                    List<ResponderId> ridList = osr.getResponderIds();
+                    List<Extension> extList = osr.getExtensions();
+
+                    if (ridList.size() != 1 || !ridList.contains(checkRid)) {
+                        throw new RuntimeException("Responder list mismatch");
+                    } else if (extList.size() !=  1 ||
+                            !extList.get(0).getId().equals(checkExt.getId())) {
+                        throw new RuntimeException("Extension list mismatch");
+                    }
+                } else {
+                    throw new RuntimeException("Expected OCSPStatusRequest " +
+                            "from decoded bytes, got " +
+                            sReq.getClass().getName());
+                }
+
+                // Create a CSRIV2 out of random data.  A non-OCSP/OCSP_MULTI
+                // type will be forcibly set and the outer length field will
+                // be correct.
+                // The constructor should create a StatusRequestType object
+                // and an UnknownStatusRequest object consisting of the
+                // data segment.
+                byte[] junkData = new byte[48];
+                Random r = new Random(System.currentTimeMillis());
+                r.nextBytes(junkData);
+                junkData[0] = 7;        // status_type = 7
+                junkData[1] = 0;
+                junkData[2] = 45;       // request_length = 45
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(junkData));
+                csriv = new CertStatusReqItemV2(hsis);
+
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType.id != junkData[0]) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected 7, got " + sType.id);
+                }
+                if (sReq instanceof UnknownStatusRequest) {
+                    // Verify the underlying StatusRequest bytes have been
+                    // preserved correctly.
+                    HandshakeOutStream hsout = new HandshakeOutStream(null);
+                    sReq.send(hsout);
+                    byte[] srDataOut = hsout.toByteArray();
+                    TestUtils.valueCheck(srDataOut, junkData, 0, 3,
+                            srDataOut.length);
+                } else {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected UnknownStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                // Test the parsing of the default OCSP/OCSP_MULTI extensions
+                // and make sure the underlying StatusRequestType and
+                // StatusRequest objects are correct.
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(
+                        ByteBuffer.wrap(DEF_CSRIV2_OCSP_MULTI_BYTES));
+                csriv = new CertStatusReqItemV2(hsis);
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType != StatusRequestType.OCSP_MULTI) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected OCSP_MULTI (2), got " + sType.id);
+                }
+                if (!(sReq instanceof OCSPStatusRequest)) {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected OCSPStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(DEF_CSRIV2_OCSP_BYTES));
+                csriv = new CertStatusReqItemV2(hsis);
+                sType = csriv.getType();
+                sReq = csriv.getRequest();
+                if (sType != StatusRequestType.OCSP) {
+                    throw new RuntimeException("StatusRequestType mismatch: " +
+                            "expected OCSP (1), got " + sType.id);
+                }
+                if (!(sReq instanceof OCSPStatusRequest)) {
+                    throw new RuntimeException("StatusRequest mismatch: " +
+                            "expected OCSPStatusRequest, got " +
+                            sReq.getClass().getName());
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqListV2ExtensionTests.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqListV2ExtensionTests.java
new file mode 100644
index 0000000..5884ee3
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/CertStatusReqListV2ExtensionTests.java
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.util.*;
+import java.nio.ByteBuffer;
+import javax.net.ssl.*;
+
+/*
+ * Checks that the hash value for a certificate's issuer name is generated
+ * correctly. Requires any certificate that is not self-signed.
+ *
+ * NOTE: this test uses Sun private classes which are subject to change.
+ */
+public class CertStatusReqListV2ExtensionTests {
+
+    private static final boolean debug = false;
+
+    // Default status_request_v2 extension with two items
+    // 1. Type = ocsp_multi, OCSPStatusRequest is default
+    // 2. Type = ocsp, OCSPStatusRequest is default
+    private static final byte[] CSRLV2_DEF = {
+           0,   14,    2,    0,    4,    0,    0,    0,
+           0,    1,    0,    4,    0,    0,    0,    0
+    };
+
+    // A status_request_v2 where the item list length is
+    // longer than the provided data
+    private static final byte[] CSRLV2_LEN_TOO_LONG = {
+           0,   18,    2,    0,    4,    0,    0,    0,
+           0,    1,    0,    4,    0,    0,    0,    0
+    };
+
+    // A status_request_v2 where the item list length is
+    // shorter than the provided data
+    private static final byte[] CSRLV2_LEN_TOO_SHORT = {
+           0,   11,    2,    0,    4,    0,    0,    0,
+           0,    1,    0,    4,    0,    0,    0,    0
+    };
+
+    // A status_request_v2 extension with a zero-length
+    // certificate_status_req_list (not allowed by the spec)
+    private static final byte[] CSRLV2_INVALID_ZEROLEN = {0, 0};
+
+    // A status_request_v2 extension with two items (ocsp_multi and ocsp)
+    // using OCSPStatusRequests with 5 ResponderIds and 1 Extension each.
+    private static final byte[] CSRLV2_TWO_NON_DEF_ITEMS = {
+            2,   90,    2,    1,   42,    0,  -13,    0,
+           59,  -95,   57,   48,   55,   49,   16,   48,
+           14,    6,    3,   85,    4,   10,   19,    7,
+           83,  111,  109,  101,   73,  110,   99,   49,
+           16,   48,   14,    6,    3,   85,    4,   11,
+           19,    7,   83,  111,  109,  101,   80,   75,
+           73,   49,   17,   48,   15,    6,    3,   85,
+            4,    3,   19,    8,   83,  111,  109,  101,
+           79,   67,   83,   80,    0,   68,  -95,   66,
+           48,   64,   49,   13,   48,   11,    6,    3,
+           85,    4,   10,   19,    4,   79,  104,   77,
+          121,   49,   14,   48,   12,    6,    3,   85,
+            4,   11,   19,    5,   66,  101,   97,  114,
+          115,   49,   15,   48,   13,    6,    3,   85,
+            4,   11,   19,    6,   84,  105,  103,  101,
+          114,  115,   49,   14,   48,   12,    6,    3,
+           85,    4,    3,   19,    5,   76,  105,  111,
+          110,  115,    0,   58,  -95,   56,   48,   54,
+           49,   16,   48,   14,    6,    3,   85,    4,
+           10,   19,    7,   67,  111,  109,  112,   97,
+          110,  121,   49,   13,   48,   11,    6,    3,
+           85,    4,   11,   19,    4,   87,  101,  115,
+          116,   49,   19,   48,   17,    6,    3,   85,
+            4,    3,   19,   10,   82,  101,  115,  112,
+          111,  110,  100,  101,  114,   49,    0,   24,
+          -94,   22,    4,   20,  -67,  -36,  114,  121,
+           92,  -79,  116,   -1,  102, -107,    7,  -21,
+           18, -113,   64,   76,   96,   -7,  -66,  -63,
+            0,   24,  -94,   22,    4,   20,  -51,  -69,
+          107,  -82,  -39,  -87,   45,   25,   41,   28,
+          -76,  -68,  -11, -110,  -94,  -97,   62,   47,
+           58, -125,    0,   51,   48,   49,   48,   47,
+            6,    9,   43,    6,    1,    5,    5,    7,
+           48,    1,    2,    4,   34,    4,   32,  -26,
+          -81, -120,  -61, -127,  -79,    0,  -39,  -54,
+           49,    3,  -51,  -57,  -85,   19, -126,   94,
+           -2,   21,   26,   98,    6,  105,  -35,  -37,
+          -29,  -73,  101,   53,   44,   15,  -19,    1,
+            1,   42,    0,  -13,    0,   59,  -95,   57,
+           48,   55,   49,   16,   48,   14,    6,    3,
+           85,    4,   10,   19,    7,   83,  111,  109,
+          101,   73,  110,   99,   49,   16,   48,   14,
+            6,    3,   85,    4,   11,   19,    7,   83,
+          111,  109,  101,   80,   75,   73,   49,   17,
+           48,   15,    6,    3,   85,    4,    3,   19,
+            8,   83,  111,  109,  101,   79,   67,   83,
+           80,    0,   68,  -95,   66,   48,   64,   49,
+           13,   48,   11,    6,    3,   85,    4,   10,
+           19,    4,   79,  104,   77,  121,   49,   14,
+           48,   12,    6,    3,   85,    4,   11,   19,
+            5,   66,  101,   97,  114,  115,   49,   15,
+           48,   13,    6,    3,   85,    4,   11,   19,
+            6,   84,  105,  103,  101,  114,  115,   49,
+           14,   48,   12,    6,    3,   85,    4,    3,
+           19,    5,   76,  105,  111,  110,  115,    0,
+           58,  -95,   56,   48,   54,   49,   16,   48,
+           14,    6,    3,   85,    4,   10,   19,    7,
+           67,  111,  109,  112,   97,  110,  121,   49,
+           13,   48,   11,    6,    3,   85,    4,   11,
+           19,    4,   87,  101,  115,  116,   49,   19,
+           48,   17,    6,    3,   85,    4,    3,   19,
+           10,   82,  101,  115,  112,  111,  110,  100,
+          101,  114,   49,    0,   24,  -94,   22,    4,
+           20,  -67,  -36,  114,  121,   92,  -79,  116,
+           -1,  102, -107,    7,  -21,   18, -113,   64,
+           76,   96,   -7,  -66,  -63,    0,   24,  -94,
+           22,    4,   20,  -51,  -69,  107,  -82,  -39,
+          -87,   45,   25,   41,   28,  -76,  -68,  -11,
+         -110,  -94,  -97,   62,   47,   58, -125,    0,
+           51,   48,   49,   48,   47,    6,    9,   43,
+            6,    1,    5,    5,    7,   48,    1,    2,
+            4,   34,    4,   32,  -26,  -81, -120,  -61,
+         -127,  -79,    0,  -39,  -54,   49,    3,  -51,
+          -57,  -85,   19, -126,   94,   -2,   21,   26,
+           98,    6,  105,  -35,  -37,  -29,  -73,  101,
+           53,   44,   15,  -19
+    };
+
+    public static void main(String[] args) throws Exception {
+        Map<String, TestCase> testList =
+                new LinkedHashMap<String, TestCase>() {{
+            put("CTOR (default)", testCtorDefault);
+            put("CTOR (List<CertStatusReqItemV2)", testCtorItemList);
+            put("CTOR (HandshakeInStream, getRequestList",
+                    testCtorInStream);
+        }};
+
+        TestUtils.runTests(testList);
+    }
+
+    public static final TestCase testCtorDefault = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                CertStatusReqListV2Extension csrlV2 =
+                        new CertStatusReqListV2Extension();
+                HandshakeOutStream hsout = new HandshakeOutStream(null);
+                csrlV2.send(hsout);
+                TestUtils.valueCheck(wrapExtData(new byte[0]),
+                        hsout.toByteArray());
+
+                // The length should be 4 (2 bytes for the type, 2 for the
+                // encoding of zero-length
+                if (csrlV2.length() != 4) {
+                    throw new RuntimeException("Incorrect length from " +
+                            "default object.  Expected 4, got " +
+                            csrlV2.length());
+                }
+
+                // Since there's no data, there are no status_type or request
+                // data fields defined.  An empty, unmodifiable list should be
+                // returned when obtained from the extension.
+                List<CertStatusReqItemV2> itemList = csrlV2.getRequestItems();
+                if (!itemList.isEmpty()) {
+                    throw new RuntimeException("Default CSRLV2 returned " +
+                            "non-empty request list");
+                } else {
+                    try {
+                        itemList.add(new CertStatusReqItemV2(
+                                StatusRequestType.OCSP_MULTI,
+                                new OCSPStatusRequest()));
+                        throw new RuntimeException("Returned itemList is " +
+                                "modifiable!");
+                    } catch (UnsupportedOperationException uoe) { }
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    public static final TestCase testCtorItemList = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            OCSPStatusRequest osr = new OCSPStatusRequest();
+            List<CertStatusReqItemV2> noItems = Collections.emptyList();
+            List<CertStatusReqItemV2> defList =
+                    new ArrayList<CertStatusReqItemV2>() {{
+                add(new CertStatusReqItemV2(StatusRequestType.OCSP_MULTI, osr));
+                add(new CertStatusReqItemV2(StatusRequestType.OCSP, osr));
+            }};
+            List<CertStatusReqItemV2> unknownTypesList =
+                    new ArrayList<CertStatusReqItemV2>() {{
+                add(new CertStatusReqItemV2(StatusRequestType.get(8),
+                        new UnknownStatusRequest(new byte[0])));
+                add(new CertStatusReqItemV2(StatusRequestType.get(12),
+                        new UnknownStatusRequest(new byte[5])));
+            }};
+
+            try {
+                HandshakeOutStream hsout = new HandshakeOutStream(null);
+                StatusRequest basicStatReq = new OCSPStatusRequest();
+
+                // Create an extension using a default-style OCSPStatusRequest
+                // (no responder IDs, no extensions).
+                CertStatusReqListV2Extension csrlv2 =
+                        new CertStatusReqListV2Extension(defList);
+                csrlv2.send(hsout);
+                TestUtils.valueCheck(wrapExtData(CSRLV2_DEF),
+                        hsout.toByteArray());
+                hsout.reset();
+
+                // Create the extension using a StatusRequestType not already
+                // instantiated as a static StatusRequestType
+                // (e.g. OCSP/OCSP_MULTI)
+                csrlv2 = new CertStatusReqListV2Extension(unknownTypesList);
+                List<CertStatusReqItemV2> itemList = csrlv2.getRequestItems();
+                if (itemList.size() != unknownTypesList.size()) {
+                    throw new RuntimeException("Custom CSRLV2 returned " +
+                            "an incorrect number of items: expected " +
+                            unknownTypesList.size() + ", got " +
+                            itemList.size());
+                } else {
+                    // Verify that the list is unmodifiable
+                    try {
+                        itemList.add(new CertStatusReqItemV2(
+                                StatusRequestType.OCSP_MULTI,
+                                new OCSPStatusRequest()));
+                        throw new RuntimeException("Returned itemList is " +
+                                "modifiable!");
+                    } catch (UnsupportedOperationException uoe) { }
+                }
+
+                // Pass a null value for the item list.  This should throw
+                // an exception
+                try {
+                    CertStatusReqListV2Extension csrlv2Null =
+                            new CertStatusReqListV2Extension(null);
+                    throw new RuntimeException("Constructor accepted a " +
+                            "null request list");
+                } catch (NullPointerException npe) { }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor that builds the ob ject using data from
+    // a HandshakeInStream
+    // This also tests the length, getReqType and getRequest methods
+    public static final TestCase testCtorInStream = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            OCSPStatusRequest osr;
+            CertStatusReqListV2Extension csrlv2;
+
+            try {
+                // To simulate the extension coming in a ServerHello, the
+                // type and length would already be read by HelloExtensions
+                // and there is no extension data
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(new byte[0]));
+                csrlv2 = new CertStatusReqListV2Extension(hsis,
+                        hsis.available());
+
+                // Verify length/request list
+                if (csrlv2.length() != 4) {
+                     throw new RuntimeException("Invalid length: received " +
+                            csrlv2.length() + ", expected 4");
+                } else {
+                    List<CertStatusReqItemV2> itemList =
+                            csrlv2.getRequestItems();
+                    if (!itemList.isEmpty()) {
+                        throw new RuntimeException("Default CSRLV2 returned " +
+                                "non-empty request list");
+                    } else {
+                        try {
+                            itemList.add(new CertStatusReqItemV2(
+                                    StatusRequestType.OCSP_MULTI,
+                                    new OCSPStatusRequest()));
+                            throw new RuntimeException("Returned itemList is " +
+                                    "modifiable!");
+                        } catch (UnsupportedOperationException uoe) { }
+                    }
+                }
+
+                // Try the an extension with our basic client-generated
+                // status_request_v2 (2 items, ocsp_multi and ocsp, each with
+                // a default OCSPStatusRequest
+                hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_DEF));
+                csrlv2 = new CertStatusReqListV2Extension(hsis,
+                        hsis.available());
+                if (csrlv2.length() != (CSRLV2_DEF.length + 4)) {
+                    throw new RuntimeException("Invalid length: received " +
+                            csrlv2.length() + ", expected " +
+                            CSRLV2_DEF.length + 4);
+                } else {
+                    List<CertStatusReqItemV2> itemList =
+                            csrlv2.getRequestItems();
+                    if (itemList.size() != 2) {
+                        throw new RuntimeException("Unexpected number of " +
+                                "items request list, expected 2, got " +
+                                itemList.size());
+                    } else {
+                        try {
+                            itemList.add(new CertStatusReqItemV2(
+                                    StatusRequestType.OCSP_MULTI,
+                                    new OCSPStatusRequest()));
+                            throw new RuntimeException("Returned itemList is " +
+                                    "modifiable!");
+                        } catch (UnsupportedOperationException uoe) { }
+                    }
+                }
+
+                // Try incoming data with an illegal zero-length
+                // certificate_status_req_list
+                try {
+                    hsis = new HandshakeInStream();
+                    hsis.incomingRecord(
+                            ByteBuffer.wrap(CSRLV2_INVALID_ZEROLEN));
+                    csrlv2 = new CertStatusReqListV2Extension(hsis,
+                            hsis.available());
+                    throw new RuntimeException("Unxpected successful " +
+                            "object construction");
+                } catch (SSLException ssle) { }
+
+                // Try extensions where the certificate_status_req_list length
+                // is either too long or too short
+                try {
+                    hsis = new HandshakeInStream();
+                    hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_LEN_TOO_LONG));
+                    csrlv2 = new CertStatusReqListV2Extension(hsis,
+                            hsis.available());
+                    throw new RuntimeException("Unxpected successful " +
+                            "object construction");
+                } catch (SSLException ssle) { }
+
+                try {
+                    hsis = new HandshakeInStream();
+                    hsis.incomingRecord(ByteBuffer.wrap(CSRLV2_LEN_TOO_SHORT));
+                    csrlv2 = new CertStatusReqListV2Extension(hsis,
+                            hsis.available());
+                    throw new RuntimeException("Unxpected successful " +
+                            "object construction");
+                } catch (SSLException ssle) { }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Take CSRE extension data and add extension type and length decorations
+    private static byte[] wrapExtData(byte[] extData) {
+        int bufferLen = extData.length + 4;
+        ByteBuffer bb = ByteBuffer.allocate(bufferLen);
+
+        bb.putShort((short)ExtensionType.EXT_STATUS_REQUEST_V2.id);
+        bb.putShort((short)extData.length);
+        if (extData.length != 0) {
+            bb.put(extData);
+        }
+        return bb.array();
+    }
+}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/OCSPStatusRequestTests.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/OCSPStatusRequestTests.java
new file mode 100644
index 0000000..85de96d
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/OCSPStatusRequestTests.java
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.security.cert.*;
+import java.util.*;
+import java.nio.ByteBuffer;
+import javax.security.auth.x500.X500Principal;
+import sun.security.provider.certpath.ResponderId;
+import sun.security.provider.certpath.OCSPNonceExtension;
+
+/*
+ * Checks that the hash value for a certificate's issuer name is generated
+ * correctly. Requires any certificate that is not self-signed.
+ *
+ * NOTE: this test uses Sun private classes which are subject to change.
+ */
+public class OCSPStatusRequestTests {
+
+    private static final boolean debug = false;
+
+    // The default (no Responder IDs or Extensions)
+    private static final byte[] DEF_OCSPREQ_BYTES = { 0, 0, 0, 0 };
+
+    // OCSP Extension with one Responder ID (byName: CN=OCSP Signer) and
+    // a nonce extension (32 bytes).
+    private static final byte[] OCSPREQ_1RID_1EXT = {
+            0,   28,    0,   26,  -95,   24,   48,   22,
+           49,   20,   48,   18,    6,    3,   85,    4,
+            3,   19,   11,   79,   67,   83,   80,   32,
+           83,  105,  103,  110,  101,  114,    0,   51,
+           48,   49,   48,   47,    6,    9,   43,    6,
+            1,    5,    5,    7,   48,    1,    2,    4,
+           34,    4,   32,  -34,  -83,  -66,  -17,  -34,
+          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
+          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
+          -83,  -66,  -17,  -34,  -83,  -66,  -17,  -34,
+          -83,  -66,  -17
+    };
+
+    public static void main(String[] args) throws Exception {
+        Map<String, TestCase> testList =
+                new LinkedHashMap<String, TestCase>() {{
+            put("CTOR (default)", testCtorDefault);
+            put("CTOR (Responder Id and Extension)", testCtorRidsExts);
+            put("CTOR (HandshakeInStream)", testCtorInStream);
+            put("CTOR (byte array)", testCtorByteArray);
+            put("Length tests", testLength);
+            put("Equals tests", testEquals);
+        }};
+
+        TestUtils.runTests(testList);
+    }
+
+    // Test the default constructor and its encoding
+    public static final TestCase testCtorDefault = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                // Create a OCSPStatusRequest with a single ResponderId
+                // and Extension
+                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
+                HandshakeOutStream hsout = new HandshakeOutStream(null);
+                osrDefault.send(hsout);
+                System.out.println("Encoded Result:");
+                TestUtils.dumpBytes(hsout.toByteArray());
+
+                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor form that allows the user to specify zero
+    // or more ResponderId objects and/or Extensions
+    public static final TestCase testCtorRidsExts = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                List<ResponderId> ridList = new LinkedList<ResponderId>() {{
+                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
+                }};
+                List<Extension> extList = new LinkedList<Extension>() {{
+                    add(new OCSPNonceExtension(32));
+                }};
+
+                // Default-style OCSPStatusRequest using both empty Lists and
+                // null inputs
+                OCSPStatusRequest osrDef1 =
+                        new OCSPStatusRequest(new LinkedList<ResponderId>(),
+                                null);
+                OCSPStatusRequest osrDef2 =
+                        new OCSPStatusRequest(null,
+                                new LinkedList<Extension>());
+                HandshakeOutStream hsout = new HandshakeOutStream(null);
+                osrDef1.send(hsout);
+                System.out.println("Encoded Result:");
+                TestUtils.dumpBytes(hsout.toByteArray());
+                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
+
+                hsout.reset();
+                osrDef2.send(hsout);
+                System.out.println("Encoded Result:");
+                TestUtils.dumpBytes(hsout.toByteArray());
+                TestUtils.valueCheck(DEF_OCSPREQ_BYTES, hsout.toByteArray());
+
+                hsout.reset();
+                OCSPStatusRequest osrWithItems =
+                        new OCSPStatusRequest(ridList, extList);
+                osrWithItems.send(hsout);
+                System.out.println("Encoded Result:");
+                byte[] encodedData = hsout.toByteArray();
+                TestUtils.dumpBytes(encodedData);
+                // Check everything except the last 32 bytes (nonce data)
+                TestUtils.valueCheck(OCSPREQ_1RID_1EXT, encodedData, 0, 0,
+                        encodedData.length - 32);
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor that builds the ob ject using data from
+    // a HandshakeInStream
+    public static final TestCase testCtorInStream = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                ResponderId checkRid =
+                        new ResponderId(new X500Principal("CN=OCSP Signer"));
+                Extension checkExt = new OCSPNonceExtension(32);
+
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
+                OCSPStatusRequest osr = new OCSPStatusRequest(hsis);
+
+                List<ResponderId> ridList = osr.getResponderIds();
+                List<Extension> extList = osr.getExtensions();
+
+                if (ridList.size() != 1 || !ridList.contains(checkRid)) {
+                    throw new RuntimeException("Responder list mismatch");
+                } else if (extList.size() !=  1 ||
+                        !extList.get(0).getId().equals(checkExt.getId())) {
+                    throw new RuntimeException("Extension list mismatch");
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the constructor form that takes the data from a byte array
+    public static final TestCase testCtorByteArray = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                ResponderId checkRid =
+                        new ResponderId(new X500Principal("CN=OCSP Signer"));
+                Extension checkExt = new OCSPNonceExtension(32);
+
+                OCSPStatusRequest osr =
+                        new OCSPStatusRequest(OCSPREQ_1RID_1EXT);
+
+                List<ResponderId> ridList = osr.getResponderIds();
+                List<Extension> extList = osr.getExtensions();
+
+                if (ridList.size() != 1 || !ridList.contains(checkRid)) {
+                    throw new RuntimeException("Responder list mismatch");
+                } else if (extList.size() !=  1 ||
+                        !extList.get(0).getId().equals(checkExt.getId())) {
+                    throw new RuntimeException("Extension list mismatch");
+                }
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the length functions for both default and non-default
+    // OCSPStatusRequest objects
+    public static final TestCase testLength = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
+                OCSPStatusRequest osr = new OCSPStatusRequest(hsis);
+                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
+
+                if (osrDefault.length() != DEF_OCSPREQ_BYTES.length) {
+                    throw new RuntimeException("Invalid length for default: " +
+                            "Expected" + DEF_OCSPREQ_BYTES.length +
+                            ", received " + osrDefault.length());
+                } else if (osr.length() != OCSPREQ_1RID_1EXT.length) {
+                    throw new RuntimeException("Invalid length for default: " +
+                            "Expected" + OCSPREQ_1RID_1EXT.length +
+                            ", received " + osr.length());
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test the equals method with default and non-default objects
+    public static final TestCase testEquals = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            try {
+                // Make two different lists with the same ResponderId values
+                // and also make a extension list
+                List<ResponderId> ridList1 = new LinkedList<ResponderId>() {{
+                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
+                }};
+                List<ResponderId> ridList2 = new LinkedList<ResponderId>() {{
+                    add(new ResponderId(new X500Principal("CN=OCSP Signer")));
+                }};
+                List<Extension> extList = new LinkedList<Extension>() {{
+                    add(new OCSPNonceExtension(32));
+                }};
+
+                // We expect two default OCSP objects to be equal
+                OCSPStatusRequest osrDefault = new OCSPStatusRequest();
+                if (!osrDefault.equals(new OCSPStatusRequest())) {
+                    throw new RuntimeException("Default OCSPStatusRequest" +
+                            " equality test failed");
+                }
+
+                // null test (expect false return)
+                if (osrDefault.equals(null)) {
+                    throw new RuntimeException("OCSPStatusRequest matched" +
+                            " unexpectedly");
+                }
+
+                // Self-reference test
+                OCSPStatusRequest osrSelfRef = osrDefault;
+                if (!osrDefault.equals(osrSelfRef)) {
+                    throw new RuntimeException("Default OCSPStatusRequest" +
+                            " equality test failed");
+                }
+
+                // Two OCSPStatusRequests with matching ResponderIds should
+                // be considered equal
+                OCSPStatusRequest osrByList1 =
+                        new OCSPStatusRequest(ridList1, null);
+                OCSPStatusRequest osrByList2 = new OCSPStatusRequest(ridList2,
+                        Collections.emptyList());
+                if (!osrByList1.equals(osrByList2)) {
+                    throw new RuntimeException("Single Responder ID " +
+                            "OCSPStatusRequest equality test failed");
+                }
+
+                // We expect OCSPStatusRequests with different nonces to be
+                // considered unequal.
+                HandshakeInStream hsis = new HandshakeInStream();
+                hsis.incomingRecord(ByteBuffer.wrap(OCSPREQ_1RID_1EXT));
+                OCSPStatusRequest osrStream = new OCSPStatusRequest(hsis);
+                OCSPStatusRequest osrRidExt = new OCSPStatusRequest(ridList1,
+                        extList);
+                if (osrStream.equals(osrRidExt)) {
+                    throw new RuntimeException("OCSPStatusRequest matched" +
+                            " unexpectedly");
+                }
+
+                pass = Boolean.TRUE;
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/StatusResponseManagerTests.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/StatusResponseManagerTests.java
new file mode 100644
index 0000000..7e0202e
--- /dev/null
+++ b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/StatusResponseManagerTests.java
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.*;
+import java.util.*;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PublicKey;
+import java.util.concurrent.TimeUnit;
+
+import sun.security.testlibrary.SimpleOCSPServer;
+import sun.security.testlibrary.CertificateBuilder;
+
+/*
+ * Checks that the hash value for a certificate's issuer name is generated
+ * correctly. Requires any certificate that is not self-signed.
+ *
+ * NOTE: this test uses Sun private classes which are subject to change.
+ */
+public class StatusResponseManagerTests {
+
+    private static final boolean debug = true;
+    private static final boolean ocspDebug = false;
+
+    // PKI components we will need for this test
+    static String passwd = "passphrase";
+    static String ROOT_ALIAS = "root";
+    static String INT_ALIAS = "intermediate";
+    static String SSL_ALIAS = "ssl";
+    static KeyStore rootKeystore;           // Root CA Keystore
+    static KeyStore intKeystore;            // Intermediate CA Keystore
+    static KeyStore serverKeystore;         // SSL Server Keystore
+    static KeyStore trustStore;             // SSL Client trust store
+    static X509Certificate rootCert;
+    static X509Certificate intCert;
+    static X509Certificate sslCert;
+    static SimpleOCSPServer rootOcsp;       // Root CA OCSP Responder
+    static int rootOcspPort;                // Port number for root OCSP
+    static SimpleOCSPServer intOcsp;        // Intermediate CA OCSP Responder
+    static int intOcspPort;                 // Port number for intermed. OCSP
+
+    static X509Certificate[] chain;
+
+    public static void main(String[] args) throws Exception {
+        Map<String, TestCase> testList =
+                new LinkedHashMap<String, TestCase>() {{
+            put("Basic OCSP fetch test", testOcspFetch);
+            put("Clear StatusResponseManager cache", testClearSRM);
+            put("Basic OCSP_MULTI fetch test", testOcspMultiFetch);
+            put("Test Cache Expiration", testCacheExpiry);
+        }};
+
+        // Create the CAs and OCSP responders
+        createPKI();
+
+        // Grab the certificates and make a chain we can reuse for tests
+        sslCert = (X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);
+        intCert = (X509Certificate)intKeystore.getCertificate(INT_ALIAS);
+        rootCert = (X509Certificate)rootKeystore.getCertificate(ROOT_ALIAS);
+        chain = new X509Certificate[3];
+        chain[0] = sslCert;
+        chain[1] = intCert;
+        chain[2] = rootCert;
+
+        TestUtils.runTests(testList);
+
+        intOcsp.stop();
+        rootOcsp.stop();
+    }
+
+    // Test a simple RFC 6066 server-side fetch
+    public static final TestCase testOcspFetch = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            StatusResponseManager srm = new StatusResponseManager();
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            StatusRequest oReq = new OCSPStatusRequest();
+
+            try {
+                // Get OCSP responses for non-root certs in the chain
+                Map<X509Certificate, byte[]> responseMap = srm.get(
+                        StatusRequestType.OCSP, oReq, chain, 5000,
+                        TimeUnit.MILLISECONDS);
+
+                // There should be one entry in the returned map and
+                // one entry in the cache when the operation is complete.
+                if (responseMap.size() != 1) {
+                    message = "Incorrect number of responses: expected 1, got "
+                            + responseMap.size();
+                } else if (!responseMap.containsKey(sslCert)) {
+                    message = "Response map key is incorrect, expected " +
+                            sslCert.getSubjectX500Principal().toString();
+                } else if (srm.size() != 1) {
+                    message = "Incorrect number of cache entries: " +
+                            "expected 1, got " + srm.size();
+                } else {
+                    pass = Boolean.TRUE;
+                }
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test clearing the StatusResponseManager cache.
+    public static final TestCase testClearSRM = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            StatusResponseManager srm = new StatusResponseManager();
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            StatusRequest oReq = new OCSPStatusRequest();
+
+            try {
+                // Get OCSP responses for non-root certs in the chain
+                srm.get(StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
+                        TimeUnit.MILLISECONDS);
+
+                // There should be two entries in the returned map and
+                // two entries in the cache when the operation is complete.
+                if (srm.size() != 2) {
+                    message = "Incorrect number of responses: expected 2, got "
+                            + srm.size();
+                } else {
+                    // Next, clear the SRM, then check the size again
+                    srm.clear();
+                    if (srm.size() != 0) {
+                        message = "Incorrect number of responses: expected 0," +
+                                " got " + srm.size();
+                    } else {
+                        pass = Boolean.TRUE;
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test a simple RFC 6961 server-side fetch
+    public static final TestCase testOcspMultiFetch = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            StatusResponseManager srm = new StatusResponseManager();
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            StatusRequest oReq = new OCSPStatusRequest();
+
+            try {
+                // Get OCSP responses for non-root certs in the chain
+                Map<X509Certificate, byte[]> responseMap = srm.get(
+                        StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
+                        TimeUnit.MILLISECONDS);
+
+                // There should be two entries in the returned map and
+                // two entries in the cache when the operation is complete.
+                if (responseMap.size() != 2) {
+                    message = "Incorrect number of responses: expected 2, got "
+                            + responseMap.size();
+                } else if (!responseMap.containsKey(sslCert) ||
+                        !responseMap.containsKey(intCert)) {
+                    message = "Response map keys are incorrect, expected " +
+                            sslCert.getSubjectX500Principal().toString() +
+                            " and " +
+                            intCert.getSubjectX500Principal().toString();
+                } else if (srm.size() != 2) {
+                    message = "Incorrect number of cache entries: " +
+                            "expected 2, got " + srm.size();
+                } else {
+                    pass = Boolean.TRUE;
+                }
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    // Test cache expiration
+    public static final TestCase testCacheExpiry = new TestCase() {
+        @Override
+        public Map.Entry<Boolean, String> runTest() {
+            // For this test, we will set the cache expiry to 5 seconds
+            System.setProperty("jdk.tls.stapling.cacheLifetime", "5");
+            StatusResponseManager srm = new StatusResponseManager();
+            Boolean pass = Boolean.FALSE;
+            String message = null;
+            StatusRequest oReq = new OCSPStatusRequest();
+
+            try {
+                // Get OCSP responses for non-root certs in the chain
+                srm.get(StatusRequestType.OCSP_MULTI, oReq, chain, 5000,
+                        TimeUnit.MILLISECONDS);
+
+                // There should be two entries in the returned map and
+                // two entries in the cache when the operation is complete.
+                if (srm.size() != 2) {
+                    message = "Incorrect number of responses: expected 2, got "
+                            + srm.size();
+                } else {
+                    // Next, wait for more than 5 seconds so the responses
+                    // in the SRM will expire.
+                    Thread.sleep(7000);
+                    if (srm.size() != 0) {
+                        message = "Incorrect number of responses: expected 0," +
+                                " got " + srm.size();
+                    } else {
+                        pass = Boolean.TRUE;
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace(System.out);
+                message = e.getClass().getName();
+            }
+
+            // Set the cache lifetime back to the default
+            System.setProperty("jdk.tls.stapling.cacheLifetime", "");
+            return new AbstractMap.SimpleEntry<>(pass, message);
+        }
+    };
+
+    /**
+     * Creates the PKI components necessary for this test, including
+     * Root CA, Intermediate CA and SSL server certificates, the keystores
+     * for each entity, a client trust store, and starts the OCSP responders.
+     */
+    private static void createPKI() throws Exception {
+        CertificateBuilder cbld = new CertificateBuilder();
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(2048);
+        KeyStore.Builder keyStoreBuilder =
+                KeyStore.Builder.newInstance("PKCS12", null,
+                        new KeyStore.PasswordProtection(passwd.toCharArray()));
+
+        // Generate Root, IntCA, EE keys
+        KeyPair rootCaKP = keyGen.genKeyPair();
+        log("Generated Root CA KeyPair");
+        KeyPair intCaKP = keyGen.genKeyPair();
+        log("Generated Intermediate CA KeyPair");
+        KeyPair sslKP = keyGen.genKeyPair();
+        log("Generated SSL Cert KeyPair");
+
+        // Set up the Root CA Cert
+        cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany");
+        cbld.setPublicKey(rootCaKP.getPublic());
+        cbld.setSerialNumber(new BigInteger("1"));
+        // Make a 3 year validity starting from 60 days ago
+        long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60);
+        long end = start + TimeUnit.DAYS.toMillis(1085);
+        cbld.setValidity(new Date(start), new Date(end));
+        addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic());
+        addCommonCAExts(cbld);
+        // Make our Root CA Cert!
+        X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(),
+                "SHA256withRSA");
+        log("Root CA Created:\n" + certInfo(rootCert));
+
+        // Now build a keystore and add the keys and cert
+        rootKeystore = keyStoreBuilder.getKeyStore();
+        Certificate[] rootChain = {rootCert};
+        rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(),
+                passwd.toCharArray(), rootChain);
+
+        // Now fire up the OCSP responder
+        rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null);
+        rootOcsp.enableLog(ocspDebug);
+        rootOcsp.setNextUpdateInterval(3600);
+        rootOcsp.start();
+        Thread.sleep(1000);         // Give the server a second to start up
+        rootOcspPort = rootOcsp.getPort();
+        String rootRespURI = "http://localhost:" + rootOcspPort;
+        log("Root OCSP Responder URI is " + rootRespURI);
+
+        // Now that we have the root keystore and OCSP responder we can
+        // create our intermediate CA.
+        cbld.reset();
+        cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany");
+        cbld.setPublicKey(intCaKP.getPublic());
+        cbld.setSerialNumber(new BigInteger("100"));
+        // Make a 2 year validity starting from 30 days ago
+        start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30);
+        end = start + TimeUnit.DAYS.toMillis(730);
+        cbld.setValidity(new Date(start), new Date(end));
+        addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic());
+        addCommonCAExts(cbld);
+        cbld.addAIAExt(Collections.singletonList(rootRespURI));
+        // Make our Intermediate CA Cert!
+        X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(),
+                "SHA256withRSA");
+        log("Intermediate CA Created:\n" + certInfo(intCaCert));
+
+        // Provide intermediate CA cert revocation info to the Root CA
+        // OCSP responder.
+        Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
+            new HashMap<>();
+        revInfo.put(intCaCert.getSerialNumber(),
+                new SimpleOCSPServer.CertStatusInfo(
+                        SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
+        rootOcsp.updateStatusDb(revInfo);
+
+        // Now build a keystore and add the keys, chain and root cert as a TA
+        intKeystore = keyStoreBuilder.getKeyStore();
+        Certificate[] intChain = {intCaCert, rootCert};
+        intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(),
+                passwd.toCharArray(), intChain);
+        intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
+
+        // Now fire up the Intermediate CA OCSP responder
+        intOcsp = new SimpleOCSPServer(intKeystore, passwd,
+                INT_ALIAS, null);
+        intOcsp.enableLog(ocspDebug);
+        intOcsp.setNextUpdateInterval(3600);
+        intOcsp.start();
+        Thread.sleep(1000);
+        intOcspPort = intOcsp.getPort();
+        String intCaRespURI = "http://localhost:" + intOcspPort;
+        log("Intermediate CA OCSP Responder URI is " + intCaRespURI);
+
+        // Last but not least, let's make our SSLCert and add it to its own
+        // Keystore
+        cbld.reset();
+        cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany");
+        cbld.setPublicKey(sslKP.getPublic());
+        cbld.setSerialNumber(new BigInteger("4096"));
+        // Make a 1 year validity starting from 7 days ago
+        start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7);
+        end = start + TimeUnit.DAYS.toMillis(365);
+        cbld.setValidity(new Date(start), new Date(end));
+
+        // Add extensions
+        addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic());
+        boolean[] kuBits = {true, false, true, false, false, false,
+            false, false, false};
+        cbld.addKeyUsageExt(kuBits);
+        List<String> ekuOids = new ArrayList<>();
+        ekuOids.add("1.3.6.1.5.5.7.3.1");
+        ekuOids.add("1.3.6.1.5.5.7.3.2");
+        cbld.addExtendedKeyUsageExt(ekuOids);
+        cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost"));
+        cbld.addAIAExt(Collections.singletonList(intCaRespURI));
+        // Make our SSL Server Cert!
+        X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(),
+                "SHA256withRSA");
+        log("SSL Certificate Created:\n" + certInfo(sslCert));
+
+        // Provide SSL server cert revocation info to the Intermeidate CA
+        // OCSP responder.
+        revInfo = new HashMap<>();
+        revInfo.put(sslCert.getSerialNumber(),
+                new SimpleOCSPServer.CertStatusInfo(
+                        SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD));
+        intOcsp.updateStatusDb(revInfo);
+
+        // Now build a keystore and add the keys, chain and root cert as a TA
+        serverKeystore = keyStoreBuilder.getKeyStore();
+        Certificate[] sslChain = {sslCert, intCaCert, rootCert};
+        serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(),
+                passwd.toCharArray(), sslChain);
+        serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert);
+
+        // And finally a Trust Store for the client
+        trustStore = keyStoreBuilder.getKeyStore();
+        trustStore.setCertificateEntry(ROOT_ALIAS, rootCert);
+    }
+
+    private static void addCommonExts(CertificateBuilder cbld,
+            PublicKey subjKey, PublicKey authKey) throws IOException {
+        cbld.addSubjectKeyIdExt(subjKey);
+        cbld.addAuthorityKeyIdExt(authKey);
+    }
+
+    private static void addCommonCAExts(CertificateBuilder cbld)
+            throws IOException {
+        cbld.addBasicConstraintsExt(true, true, -1);
+        // Set key usage bits for digitalSignature, keyCertSign and cRLSign
+        boolean[] kuBitSettings = {true, false, false, false, false, true,
+            true, false, false};
+        cbld.addKeyUsageExt(kuBitSettings);
+    }
+
+    /**
+     * Helper routine that dumps only a few cert fields rather than
+     * the whole toString() output.
+     *
+     * @param cert An X509Certificate to be displayed
+     *
+     * @return The {@link String} output of the issuer, subject and
+     * serial number
+     */
+    private static String certInfo(X509Certificate cert) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Issuer: ").append(cert.getIssuerX500Principal()).
+                append("\n");
+        sb.append("Subject: ").append(cert.getSubjectX500Principal()).
+                append("\n");
+        sb.append("Serial: ").append(cert.getSerialNumber()).append("\n");
+        return sb.toString();
+    }
+
+    /**
+     * Log a message on stdout
+     *
+     * @param message The message to log
+     */
+    private static void log(String message) {
+        if (debug) {
+            System.out.println(message);
+        }
+    }
+}
diff --git a/jdk/test/sun/security/ssl/StatusStapling/TestCase.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/TestCase.java
similarity index 100%
rename from jdk/test/sun/security/ssl/StatusStapling/TestCase.java
rename to jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/TestCase.java
diff --git a/jdk/test/sun/security/ssl/StatusStapling/TestUtils.java b/jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/TestUtils.java
similarity index 100%
rename from jdk/test/sun/security/ssl/StatusStapling/TestUtils.java
rename to jdk/test/sun/security/ssl/StatusStapling/java.base/sun/security/ssl/TestUtils.java
diff --git a/jdk/test/sun/security/tools/jarsigner/ts.sh b/jdk/test/sun/security/tools/jarsigner/ts.sh
index 6dabe06..9b7bd89 100644
--- a/jdk/test/sun/security/tools/jarsigner/ts.sh
+++ b/jdk/test/sun/security/tools/jarsigner/ts.sh
@@ -24,6 +24,11 @@
 # @test
 # @bug 6543842 6543440 6939248 8009636 8024302
 # @summary checking response of timestamp
+# @modules java.base/sun.misc
+#          java.base/sun.security.pkcs
+#          java.base/sun.security.timestamp
+#          java.base/sun.security.x509
+#          java.base/sun.security.util
 #
 # @run shell/timeout=600 ts.sh
 
@@ -90,6 +95,7 @@
         $KT -alias ca -gencert -ext eku:critical=cs | \
         $KT -alias tsbad3 -importcert
 
-$JAVAC -d . ${TESTSRC}/TimestampCheck.java
-$JAVA ${TESTVMOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck
+EXTRAOPTS="-XaddExports:java.base/sun.misc=ALL-UNNAMED,java.base/sun.security.pkcs=ALL-UNNAMED,java.base/sun.security.timestamp=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED"
+$JAVAC ${EXTRAOPTS} -d . ${TESTSRC}/TimestampCheck.java
+$JAVA ${TESTVMOPTS} ${EXTRAOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck
 
diff --git a/jdk/test/sun/security/tools/keytool/autotest.sh b/jdk/test/sun/security/tools/keytool/autotest.sh
index 655c886..d798f7a 100644
--- a/jdk/test/sun/security/tools/keytool/autotest.sh
+++ b/jdk/test/sun/security/tools/keytool/autotest.sh
@@ -100,7 +100,9 @@
 
 echo "Using NSS lib at $LIBNAME"
 
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . -XDignore.symbol.file \
+EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED"
+
+${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
         ${TESTSRC}${FS}KeyToolTest.java || exit 10
 
 NSS=${TESTSRC}${FS}..${FS}..${FS}pkcs11${FS}nss
@@ -113,7 +115,7 @@
 chmod u+w key3.db
 chmod u+w cert8.db
 
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dnss \
+echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dnss \
    -Dnss.lib=${LIBNAME} \
    KeyToolTest
 status=$?
diff --git a/jdk/test/sun/security/tools/keytool/standard.sh b/jdk/test/sun/security/tools/keytool/standard.sh
index 03484aa..f84bd19 100644
--- a/jdk/test/sun/security/tools/keytool/standard.sh
+++ b/jdk/test/sun/security/tools/keytool/standard.sh
@@ -57,9 +57,11 @@
     ;;
 esac
 
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
+EXTRAOPTS="-XaddExports:java.base/sun.security.tools.keytool=ALL-UNNAMED,java.base/sun.security.util=ALL-UNNAMED,java.base/sun.security.x509=ALL-UNNAMED"
 
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dfile KeyToolTest
+${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
+
+echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dfile KeyToolTest
 status=$?
 
 exit $status
diff --git a/jdk/test/sun/security/util/Oid/OidEquals.java b/jdk/test/sun/security/util/Oid/OidEquals.java
index 1682fc3..554455b 100644
--- a/jdk/test/sun/security/util/Oid/OidEquals.java
+++ b/jdk/test/sun/security/util/Oid/OidEquals.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8022444
  * @summary Test ObjectIdentifier.equals(Object obj)
+ * @modules java.base/sun.security.util
  */
 
 import sun.security.util.ObjectIdentifier;
diff --git a/jdk/test/sun/security/validator/certreplace.sh b/jdk/test/sun/security/validator/certreplace.sh
index 6609231..e32d638 100644
--- a/jdk/test/sun/security/validator/certreplace.sh
+++ b/jdk/test/sun/security/validator/certreplace.sh
@@ -25,6 +25,7 @@
 # @bug 6948803
 # @summary CertPath validation regression caused by SHA1 replacement root
 #  and MD2 disable feature
+# @modules java.base/sun.security.validator
 #
 
 if [ "${TESTSRC}" = "" ] ; then
@@ -82,5 +83,6 @@
 
 # 5. Build and run test
 
-$JAVAC ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}${FS}CertReplace.java
-$JAVA ${TESTVMOPTS} CertReplace certreplace.jks certreplace.certs
+EXTRAOPTS="-XaddExports:java.base/sun.security.validator=ALL-UNNAMED"
+$JAVAC ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . ${TESTSRC}${FS}CertReplace.java
+$JAVA ${TESTVMOPTS} ${EXTRAOPTS} CertReplace certreplace.jks certreplace.certs
diff --git a/jdk/test/sun/security/validator/samedn.sh b/jdk/test/sun/security/validator/samedn.sh
index ebf0660..acfa49e 100644
--- a/jdk/test/sun/security/validator/samedn.sh
+++ b/jdk/test/sun/security/validator/samedn.sh
@@ -25,6 +25,7 @@
 # @bug 6958869
 # @summary regression: PKIXValidator fails when multiple trust anchors
 # have same dn
+# @modules java.base/sun.security.validator
 #
 
 if [ "${TESTSRC}" = "" ] ; then
@@ -78,6 +79,7 @@
 # 5. Build and run test. Make sure the CA certs are ignored for validity check.
 # Check both, one of them might be dropped out of map in old codes.
 
-$JAVAC ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . ${TESTSRC}${FS}CertReplace.java
-$JAVA ${TESTVMOPTS} CertReplace samedn.jks samedn1.certs || exit 1
-$JAVA ${TESTVMOPTS} CertReplace samedn.jks samedn2.certs || exit 2
+EXTRAOPTS="-XaddExports:java.base/sun.security.validator=ALL-UNNAMED"
+$JAVAC ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . ${TESTSRC}${FS}CertReplace.java
+$JAVA ${TESTVMOPTS} ${EXTRAOPTS} CertReplace samedn.jks samedn1.certs || exit 1
+$JAVA ${TESTVMOPTS} ${EXTRAOPTS} CertReplace samedn.jks samedn2.certs || exit 2
diff --git a/jdk/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java b/jdk/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java
index f629aef..1cccda6 100644
--- a/jdk/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java
+++ b/jdk/test/sun/security/x509/URICertStore/ExtensionsWithLDAP.java
@@ -51,6 +51,7 @@
  * @test
  * @bug 8134708
  * @summary Check if LDAP resources from CRLDP and AIA extensions can be loaded
+ * @modules java.base/sun.net.spi.nameservice
  * @run main/othervm ExtensionsWithLDAP
  */
 public class ExtensionsWithLDAP {
diff --git a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
index e10212a..046a7ed 100644
--- a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
+++ b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
@@ -32,6 +32,7 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -68,7 +69,8 @@
         // Ensure that all Message fields have a corresponding key/value
         // in the resource bundle and that mnemonics can be looked
         // up where applicable.
-        ResourceBundle rb = ResourceBundle.getBundle(RESOURCE_BUNDLE);
+        Module module = sun.tools.jconsole.Messages.class.getModule();
+        ResourceBundle rb = ResourceBundle.getBundle(RESOURCE_BUNDLE, module);
         for (Field field : Messages.class.getFields()) {
             if (isResourceKeyField(field)) {
                 String resourceKey = field.getName();
diff --git a/jdk/test/sun/tools/jhsdb/SAGetoptTest.java b/jdk/test/sun/tools/jhsdb/SAGetoptTest.java
index 60ff9ff..72f50b8 100644
--- a/jdk/test/sun/tools/jhsdb/SAGetoptTest.java
+++ b/jdk/test/sun/tools/jhsdb/SAGetoptTest.java
@@ -25,6 +25,7 @@
  /*
  * @test
  * @summary unit test for SAGetopt function
+ * @modules jdk.hotspot.agent/sun.jvm.hotspot
  * @compile -XDignore.symbol.file SAGetoptTest.java
  * @run main SAGetoptTest
  */
diff --git a/jdk/test/sun/util/resources/TimeZone/Bug4640234.java b/jdk/test/sun/util/resources/TimeZone/Bug4640234.java
index a8766ea..5726bed 100644
--- a/jdk/test/sun/util/resources/TimeZone/Bug4640234.java
+++ b/jdk/test/sun/util/resources/TimeZone/Bug4640234.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -29,6 +29,7 @@
  *          ISO country codes.
  *          The test program also displays which timezone, country and
  *          language names are not translated
+ * @modules java.base/sun.util.resources
  */
 
 
@@ -49,6 +50,7 @@
 import java.util.ResourceBundle;
 import java.util.TimeZone;
 
+import sun.util.resources.LocaleData;
 
 public class Bug4640234  {
     static SimpleDateFormat sdfEn = new SimpleDateFormat("zzzz", Locale.US);
@@ -84,8 +86,8 @@
             String[] countries = locEn.getISOCountries();
             String[] languages = locEn.getISOLanguages();
 
-            ResourceBundle resEn = ResourceBundle.getBundle(
-                    "sun.util.resources.LocaleNames", locEn);
+            ResourceBundle resEn = LocaleData.getBundle("sun.util.resources.LocaleNames",
+                                                        locEn);
             Map<String, String> countryMapEn = getList(resEn, true);
             Map<String, String> languageMapEn = getList(resEn, false);
 
@@ -94,8 +96,8 @@
             Map<String, String> languageMap;
 
             for (Locale locale : locales2Test) {
-                resLoc = ResourceBundle.getBundle(
-                    "sun.util.resources.LocaleNames", locale);
+                resLoc = LocaleData.getBundle("sun.util.resources.LocaleNames",
+                                              locale);
 
                 sdfLoc = new SimpleDateFormat("zzzz", locale);
                 sdfLocShort = new SimpleDateFormat("z", locale);
@@ -257,18 +259,20 @@
 
         if (nameEn == null) {
             // We should not get here but test is a MUST have
-            return new String[] {"", MessageFormat.format(notFoundMessage,
-                new String[] {"English", ISOCode})};
+            return new String[] {"",
+                                 MessageFormat.format(notFoundMessage, "English", ISOCode)};
         }
 
         if (nameLoc == null) {
-            return new String[] {"", MessageFormat.format(notFoundMessage,
-                new String[] {locale.getDisplayName(), ISOCode})};
+            return new String[] {"",
+                                 MessageFormat.format(notFoundMessage,
+                                                      locale.getDisplayName(), ISOCode)};
         }
 
         if (nameEn.equals(nameLoc)) {
             return new String[] {MessageFormat.format(notLocalizedMessage,
-                new String[] {locale.getDisplayName(), ISOCode}), ""};
+                                                      locale.getDisplayName(), ISOCode),
+                                 ""};
         }
 
         return new String[] {"", ""};
diff --git a/jdk/test/tools/jar/compat/CLICompatibility.java b/jdk/test/tools/jar/compat/CLICompatibility.java
new file mode 100644
index 0000000..a69c082
--- /dev/null
+++ b/jdk/test/tools/jar/compat/CLICompatibility.java
@@ -0,0 +1,633 @@
+/*
+ * 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.io.*;
+import java.lang.reflect.Method;
+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.List;
+import java.util.function.Consumer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.FileUtils;
+import jdk.testlibrary.JDKToolFinder;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static java.lang.String.format;
+import static java.lang.System.out;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils jdk.testlibrary.JDKToolFinder
+ * @run testng CLICompatibility
+ * @summary Basic test for compatibility of CLI options
+ */
+
+public class CLICompatibility {
+    static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
+    static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    final boolean legacyOnly;  // for running on older JDK's ( test validation )
+
+    // Resources we know to exist, that can be used for creating jar files.
+    static final String RES1 = "CLICompatibility.class";
+    static final String RES2 = "CLICompatibility$Result.class";
+
+    @BeforeTest
+    public void setupResourcesForJar() throws Exception {
+        // Copy the files that we are going to use for creating/updating test
+        // jar files, so that they can be referred to without '-C dir'
+        Files.copy(TEST_CLASSES.resolve(RES1), USER_DIR.resolve(RES1));
+        Files.copy(TEST_CLASSES.resolve(RES2), USER_DIR.resolve(RES2));
+    }
+
+    static final IOConsumer<InputStream> ASSERT_CONTAINS_RES1 = in -> {
+        try (JarInputStream jin = new JarInputStream(in)) {
+            assertTrue(jarContains(jin, RES1), "Failed to find " + RES1);
+        }
+    };
+    static final IOConsumer<InputStream> ASSERT_CONTAINS_RES2 = in -> {
+        try (JarInputStream jin = new JarInputStream(in)) {
+            assertTrue(jarContains(jin, RES2), "Failed to find " + RES2);
+        }
+    };
+    static final IOConsumer<InputStream> ASSERT_CONTAINS_MAINFEST = in -> {
+        try (JarInputStream jin = new JarInputStream(in)) {
+            assertTrue(jin.getManifest() != null, "No META-INF/MANIFEST.MF");
+        }
+    };
+    static final IOConsumer<InputStream> ASSERT_DOES_NOT_CONTAIN_MAINFEST = in -> {
+        try (JarInputStream jin = new JarInputStream(in)) {
+            assertTrue(jin.getManifest() == null, "Found unexpected META-INF/MANIFEST.MF");
+        }
+    };
+
+    static final FailCheckerWithMessage FAIL_TOO_MANY_MAIN_OPS =
+        new FailCheckerWithMessage("You must specify one of -ctxui options",
+        /* legacy */ "{ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files");
+
+    // Create
+
+    @Test
+    public void createBadArgs() {
+        final FailCheckerWithMessage FAIL_CREATE_NO_ARGS = new FailCheckerWithMessage(
+                "'c' flag requires manifest or input files to be specified!");
+
+        jar("c")
+            .assertFailure()
+            .resultChecker(FAIL_CREATE_NO_ARGS);
+
+        jar("-c")
+            .assertFailure()
+            .resultChecker(FAIL_CREATE_NO_ARGS);
+
+        if (!legacyOnly)
+            jar("--create")
+                .assertFailure()
+                .resultChecker(FAIL_CREATE_NO_ARGS);
+
+        jar("ct")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        jar("-ct")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        if (!legacyOnly)
+            jar("--create --list")
+                .assertFailure()
+                .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+    }
+
+    @Test
+    public void createWriteToFile() throws IOException {
+        Path path = Paths.get("createJarFile.jar");  // for creating
+        String jn = path.toString();
+        for (String opts : new String[]{"cf " + jn, "-cf " + jn, "--create --file=" + jn}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jar(opts, RES1)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(Files.newInputStream(path));
+                    ASSERT_CONTAINS_MAINFEST.accept(Files.newInputStream(path));
+                });
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    @Test
+    public void createWriteToStdout() throws IOException {
+        for (String opts : new String[]{"c", "-c", "--create"}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jar(opts, RES1)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(r.stdoutAsStream());
+                    ASSERT_CONTAINS_MAINFEST.accept(r.stdoutAsStream());
+                });
+        }
+    }
+
+    @Test
+    public void createWriteToStdoutNoManifest() throws IOException {
+        for (String opts : new String[]{"cM", "-cM", "--create --no-manifest"} ){
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jar(opts, RES1)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(r.stdoutAsStream());
+                    ASSERT_DOES_NOT_CONTAIN_MAINFEST.accept(r.stdoutAsStream());
+                });
+        }
+    }
+
+    // Update
+
+    @Test
+    public void updateBadArgs() {
+        final FailCheckerWithMessage FAIL_UPDATE_NO_ARGS = new FailCheckerWithMessage(
+                "'u' flag requires manifest, 'e' flag or input files to be specified!");
+
+        jar("u")
+            .assertFailure()
+            .resultChecker(FAIL_UPDATE_NO_ARGS);
+
+        jar("-u")
+            .assertFailure()
+            .resultChecker(FAIL_UPDATE_NO_ARGS);
+
+        if (!legacyOnly)
+            jar("--update")
+                .assertFailure()
+                .resultChecker(FAIL_UPDATE_NO_ARGS);
+
+        jar("ut")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        jar("-ut")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        if (!legacyOnly)
+            jar("--update --list")
+                .assertFailure()
+                .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+    }
+
+    @Test
+    public void updateReadFileWriteFile() throws IOException {
+        Path path = Paths.get("updateReadWriteStdout.jar");  // for updating
+        String jn = path.toString();
+
+        for (String opts : new String[]{"uf " + jn, "-uf " + jn, "--update --file=" + jn}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            createJar(path, RES1);
+            jar(opts, RES2)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(Files.newInputStream(path));
+                    ASSERT_CONTAINS_RES2.accept(Files.newInputStream(path));
+                    ASSERT_CONTAINS_MAINFEST.accept(Files.newInputStream(path));
+                });
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    @Test
+    public void updateReadStdinWriteStdout() throws IOException {
+        Path path = Paths.get("updateReadStdinWriteStdout.jar");
+
+        for (String opts : new String[]{"u", "-u", "--update"}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            createJar(path, RES1);
+            jarWithStdin(path.toFile(), opts, RES2)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(r.stdoutAsStream());
+                    ASSERT_CONTAINS_RES2.accept(r.stdoutAsStream());
+                    ASSERT_CONTAINS_MAINFEST.accept(r.stdoutAsStream());
+                });
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    @Test
+    public void updateReadStdinWriteStdoutNoManifest() throws IOException {
+        Path path = Paths.get("updateReadStdinWriteStdoutNoManifest.jar");
+
+        for (String opts : new String[]{"uM", "-uM", "--update --no-manifest"} ){
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            createJar(path, RES1);
+            jarWithStdin(path.toFile(), opts, RES2)
+                .assertSuccess()
+                .resultChecker(r -> {
+                    ASSERT_CONTAINS_RES1.accept(r.stdoutAsStream());
+                    ASSERT_CONTAINS_RES2.accept(r.stdoutAsStream());
+                    ASSERT_DOES_NOT_CONTAIN_MAINFEST.accept(r.stdoutAsStream());
+                });
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    // List
+
+    @Test
+    public void listBadArgs() {
+        jar("te")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        jar("-te")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        if (!legacyOnly)
+            jar("--list --extract")
+                .assertFailure()
+                .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+    }
+
+    @Test
+    public void listReadFromFileWriteToStdout() throws IOException {
+        Path path = Paths.get("listReadFromFileWriteToStdout.jar");  // for listing
+        createJar(path, RES1);
+        String jn = path.toString();
+
+        for (String opts : new String[]{"tf " + jn, "-tf " + jn, "--list --file " + jn}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jar(opts)
+                .assertSuccess()
+                .resultChecker(r ->
+                    assertTrue(r.output.contains("META-INF/MANIFEST.MF") && r.output.contains(RES1),
+                               "Failed, got [" + r.output + "]")
+                );
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    @Test
+    public void listReadFromStdinWriteToStdout() throws IOException {
+        Path path = Paths.get("listReadFromStdinWriteToStdout.jar");
+        createJar(path, RES1);
+
+        for (String opts : new String[]{"t", "-t", "--list"} ){
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jarWithStdin(path.toFile(), opts)
+                .assertSuccess()
+                .resultChecker(r ->
+                    assertTrue(r.output.contains("META-INF/MANIFEST.MF") && r.output.contains(RES1),
+                               "Failed, got [" + r.output + "]")
+                );
+        }
+        FileUtils.deleteFileIfExistsWithRetry(path);
+    }
+
+    // Extract
+
+    @Test
+    public void extractBadArgs() {
+        jar("xi")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        jar("-xi")
+            .assertFailure()
+            .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+
+        if (!legacyOnly)
+            jar("--extract --generate-index")
+                .assertFailure()
+                .resultChecker(FAIL_TOO_MANY_MAIN_OPS);
+    }
+
+    @Test
+    public void extractReadFromStdin() throws IOException {
+        Path path = Paths.get("extract");
+        Path jarPath = path.resolve("extractReadFromStdin.jar"); // for extracting
+        createJar(jarPath, RES1);
+
+        for (String opts : new String[]{"x" ,"-x", "--extract"}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jarWithStdinAndWorkingDir(jarPath.toFile(), path.toFile(), opts)
+                .assertSuccess()
+                .resultChecker(r ->
+                    assertTrue(Files.exists(path.resolve(RES1)),
+                               "Expected to find:" + path.resolve(RES1))
+                );
+            FileUtils.deleteFileIfExistsWithRetry(path.resolve(RES1));
+        }
+        FileUtils.deleteFileTreeWithRetry(path);
+    }
+
+    @Test
+    public void extractReadFromFile() throws IOException {
+        Path path = Paths.get("extract");
+        String jn = "extractReadFromFile.jar";
+        Path jarPath = path.resolve(jn);
+        createJar(jarPath, RES1);
+
+        for (String opts : new String[]{"xf "+jn ,"-xf "+jn, "--extract --file "+jn}) {
+            if (legacyOnly && opts.startsWith("--"))
+                continue;
+
+            jarWithStdinAndWorkingDir(null, path.toFile(), opts)
+                .assertSuccess()
+                .resultChecker(r ->
+                    assertTrue(Files.exists(path.resolve(RES1)),
+                               "Expected to find:" + path.resolve(RES1))
+                );
+            FileUtils.deleteFileIfExistsWithRetry(path.resolve(RES1));
+        }
+        FileUtils.deleteFileTreeWithRetry(path);
+    }
+
+    // Basic help
+
+    @Test
+    public void helpBadOptionalArg() {
+        if (legacyOnly)
+            return;
+
+        jar("--help:")
+            .assertFailure();
+
+        jar("--help:blah")
+            .assertFailure();
+    }
+
+    @Test
+    public void help() {
+        if (legacyOnly)
+            return;
+
+        jar("-h")
+            .assertSuccess()
+            .resultChecker(r ->
+                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [-C dir] files"),
+                           "Failed, got [" + r.output + "]")
+            );
+
+        jar("--help")
+            .assertSuccess()
+            .resultChecker(r ->
+                assertTrue(r.output.startsWith("Usage: jar [OPTION...] [-C dir] files"),
+                           "Failed, got [" + r.output + "]")
+            );
+
+        jar("--help:compat")
+            .assertSuccess()
+            .resultChecker(r ->
+                assertTrue(r.output.startsWith("Compatibility Interface:"),
+                           "Failed, got [" + r.output + "]")
+            );
+    }
+
+    // -- Infrastructure
+
+    static boolean jarContains(JarInputStream jis, String entryName)
+        throws IOException
+    {
+        JarEntry e;
+        boolean found = false;
+        while((e = jis.getNextJarEntry()) != null) {
+            if (e.getName().equals(entryName))
+                return true;
+        }
+        return false;
+    }
+
+    /* Creates a simple jar with entries of size 0, good enough for testing */
+    static void createJar(Path path, String... entries) throws IOException {
+        FileUtils.deleteFileIfExistsWithRetry(path);
+        Path parent = path.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+        try (OutputStream out = Files.newOutputStream(path);
+             JarOutputStream jos = new JarOutputStream(out)) {
+            JarEntry je = new JarEntry("META-INF/MANIFEST.MF");
+            jos.putNextEntry(je);
+            jos.closeEntry();
+
+            for (String entry : entries) {
+                je = new JarEntry(entry);
+                jos.putNextEntry(je);
+                jos.closeEntry();
+            }
+        }
+    }
+
+    static class FailCheckerWithMessage implements Consumer<Result> {
+        final String[] messages;
+        FailCheckerWithMessage(String... m) {
+            messages = m;
+        }
+        @Override
+        public void accept(Result r) {
+            //out.printf("%s%n", r.output);
+            boolean found = false;
+            for (String m : messages) {
+                if (r.output.contains(m)) {
+                    found = true;
+                    break;
+                }
+            }
+            assertTrue(found,
+                       "Excepted out to contain one of: " + Arrays.asList(messages)
+                           + " but got: " + r.output);
+        }
+    }
+
+    static Result jar(String... args) {
+        return jarWithStdinAndWorkingDir(null, null, args);
+    }
+
+    static Result jarWithStdin(File stdinSource, String... args) {
+        return jarWithStdinAndWorkingDir(stdinSource, null, args);
+    }
+
+    static Result jarWithStdinAndWorkingDir(File stdinFrom,
+                                            File workingDir,
+                                            String... args) {
+        String jar = getJDKTool("jar");
+        List<String> commands = new ArrayList<>();
+        commands.add(jar);
+        Stream.of(args).map(s -> s.split(" "))
+                       .flatMap(Arrays::stream)
+                       .forEach(x -> commands.add(x));
+        ProcessBuilder p = new ProcessBuilder(commands);
+        if (stdinFrom != null)
+            p.redirectInput(stdinFrom);
+        if (workingDir != null)
+            p.directory(workingDir);
+        return run(p);
+    }
+
+    static Result run(ProcessBuilder pb) {
+        Process p;
+        byte[] stdout, stderr;
+        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 {
+            stdout = readAllBytes(p.getInputStream());
+            stderr = readAllBytes(p.getErrorStream());
+
+            output = toString(stdout, stderr);
+        } 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(), stdout, stderr, output);
+    }
+
+    static final Path JAVA_HOME = Paths.get(System.getProperty("java.home"));
+
+    static String getJDKTool(String name) {
+        try {
+            return JDKToolFinder.getJDKTool(name);
+        } catch (Exception x) {
+            Path j = JAVA_HOME.resolve("bin").resolve(name);
+            if (Files.exists(j))
+                return j.toString();
+            j = JAVA_HOME.resolve("..").resolve("bin").resolve(name);
+            if (Files.exists(j))
+                return j.toString();
+            throw new RuntimeException(x);
+        }
+    }
+
+    static String toString(byte[] ba1, byte[] ba2) {
+        return (new String(ba1, UTF_8)).concat(new String(ba2, UTF_8));
+    }
+
+    static class Result {
+        final int exitValue;
+        final byte[] stdout;
+        final byte[] stderr;
+        final String output;
+
+        private Result(int exitValue, byte[] stdout, byte[] stderr, String output) {
+            this.exitValue = exitValue;
+            this.stdout = stdout;
+            this.stderr = stderr;
+            this.output = output;
+        }
+
+        InputStream stdoutAsStream() { return new ByteArrayInputStream(stdout); }
+
+        Result assertSuccess() { assertTrue(exitValue == 0, output); return this; }
+        Result assertFailure() { assertTrue(exitValue != 0, output); return this; }
+
+        Result resultChecker(IOConsumer<Result> r) {
+            try {  r.accept(this); return this; }
+            catch (IOException x) { throw new UncheckedIOException(x); }
+        }
+
+        Result resultChecker(FailCheckerWithMessage c) { c.accept(this); return this; }
+    }
+
+    interface IOConsumer<T> { void accept(T t) throws IOException ;  }
+
+    // readAllBytes implementation so the test can be run pre 1.9 ( legacyOnly )
+    static byte[] readAllBytes(InputStream is) throws IOException {
+        byte[] buf = new byte[8192];
+        int capacity = buf.length;
+        int nread = 0;
+        int n;
+        for (;;) {
+            // read to EOF which may read more or less than initial buffer size
+            while ((n = is.read(buf, nread, capacity - nread)) > 0)
+                nread += n;
+
+            // if the last call to read returned -1, then we're done
+            if (n < 0)
+                break;
+
+            // need to allocate a larger buffer
+            capacity = capacity << 1;
+
+            buf = Arrays.copyOf(buf, capacity);
+        }
+        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
+    }
+
+    // Standalone entry point for running with, possibly older, JDKs.
+    public static void main(String[] args) throws Throwable {
+        boolean legacyOnly = false;
+        if (args.length != 0 && args[0].equals("legacyOnly"))
+            legacyOnly = true;
+
+        CLICompatibility test = new CLICompatibility(legacyOnly);
+        for (Method m : CLICompatibility.class.getDeclaredMethods()) {
+            if (m.getAnnotation(Test.class) != null) {
+                System.out.println("Invoking " + m.getName());
+                m.invoke(test);
+            }
+        }
+    }
+    CLICompatibility(boolean legacyOnly) { this.legacyOnly = legacyOnly; }
+    CLICompatibility() { this.legacyOnly = false; }
+}
diff --git a/jdk/test/tools/jar/modularJar/Basic.java b/jdk/test/tools/jar/modularJar/Basic.java
new file mode 100644
index 0000000..40829ec
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/Basic.java
@@ -0,0 +1,797 @@
+/*
+ * 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.*;
+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.attribute.BasicFileAttributes;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import jdk.testlibrary.FileUtils;
+import jdk.testlibrary.JDKToolFinder;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static java.lang.String.format;
+import static java.lang.System.out;
+
+/*
+ * @test
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils jdk.testlibrary.JDKToolFinder
+ * @compile Basic.java
+ * @run testng Basic
+ * @summary Basic test for Modular jars
+ */
+
+public class Basic {
+    static final Path TEST_SRC = Paths.get(System.getProperty("test.src", "."));
+    static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
+    static final Path MODULE_CLASSES = TEST_CLASSES.resolve("build");
+
+    // Details based on the checked in module source
+    static TestModuleData FOO = new TestModuleData("foo",
+                                                   "1.123",
+                                                   "jdk.test.foo.Foo",
+                                                   "Hello World!!!", null,
+                                                   "jdk.test.foo.internal");
+    static TestModuleData BAR = new TestModuleData("bar",
+                                                   "4.5.6.7",
+                                                   "jdk.test.bar.Bar",
+                                                   "Hello from Bar!", null,
+                                                   "jdk.test.bar",
+                                                   "jdk.test.bar.internal");
+
+    static class TestModuleData {
+        final String moduleName;
+        final String mainClass;
+        final String version;
+        final String message;
+        final String hashes;
+        final Set<String> conceals;
+        TestModuleData(String mn, String v, String mc, String m, String h, String... pkgs) {
+            moduleName = mn; mainClass = mc; version = v; message = m; hashes = h;
+            conceals = new HashSet<>();
+            Stream.of(pkgs).forEach(conceals::add);
+        }
+        TestModuleData(String mn, String v, String mc, String m, String h, Set<String> pkgs) {
+            moduleName = mn; mainClass = mc; version = v; message = m; hashes = h;
+            conceals = pkgs;
+        }
+        static TestModuleData from(String s) {
+            try {
+                BufferedReader reader = new BufferedReader(new StringReader(s));
+                String line;
+                String message = null;
+                String name = null, version = null, mainClass = null;
+                String hashes = null;
+                Set<String> conceals = null;
+                while ((line = reader.readLine()) != null) {
+                    if (line.startsWith("message:")) {
+                        message = line.substring("message:".length());
+                    } else if (line.startsWith("nameAndVersion:")) {
+                        line = line.substring("nameAndVersion:".length());
+                        int i = line.indexOf('@');
+                        if (i != -1) {
+                            name = line.substring(0, i);
+                            version = line.substring(i + 1, line.length());
+                        } else {
+                            name = line;
+                        }
+                    } else if (line.startsWith("mainClass:")) {
+                        mainClass = line.substring("mainClass:".length());
+                    } else if (line.startsWith("hashes:")) {
+                        hashes = line.substring("hashes:".length());
+                    }  else if (line.startsWith("conceals:")) {
+                        line = line.substring("conceals:".length());
+                        conceals = new HashSet<>();
+                        int i = line.indexOf(',');
+                        if (i != -1) {
+                            String[] p = line.split(",");
+                            Stream.of(p).forEach(conceals::add);
+                        } else {
+                            conceals.add(line);
+                        }
+                    } else {
+                        throw new AssertionError("Unknown value " + line);
+                    }
+                }
+
+                return new TestModuleData(name, version, mainClass, message, hashes, conceals);
+            } catch (IOException x) {
+                throw new UncheckedIOException(x);
+            }
+        }
+    }
+
+    static void assertModuleData(Result r, TestModuleData expected) {
+        //out.printf("%s%n", r.output);
+        TestModuleData received = TestModuleData.from(r.output);
+        if (expected.message != null)
+            assertTrue(expected.message.equals(received.message),
+                       "Expected message:", expected.message, ", got:", received.message);
+        assertTrue(expected.moduleName.equals(received.moduleName),
+                   "Expected moduleName: ", expected.moduleName, ", got:", received.moduleName);
+        assertTrue(expected.version.equals(received.version),
+                   "Expected version: ", expected.version, ", got:", received.version);
+        assertTrue(expected.mainClass.equals(received.mainClass),
+                   "Expected mainClass: ", expected.mainClass, ", got:", received.mainClass);
+        expected.conceals.forEach(p -> assertTrue(received.conceals.contains(p),
+                                                  "Expected ", p, ", in ", received.conceals));
+        received.conceals.forEach(p -> assertTrue(expected.conceals.contains(p),
+                                                  "Expected ", p, ", in ", expected.conceals));
+    }
+
+    @BeforeTest
+    public void compileModules() throws Exception {
+        compileModule(FOO.moduleName);
+        compileModule(BAR.moduleName, MODULE_CLASSES);
+        compileModule("baz");  // for service provider consistency checking
+    }
+
+    @Test
+    public void createFoo() throws IOException {
+        Path mp = Paths.get("createFoo");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+
+        try (InputStream fis = Files.newInputStream(modularJar);
+             JarInputStream jis = new JarInputStream(fis)) {
+            assertTrue(!jarContains(jis, "./"),
+                       "Unexpected ./ found in ", modularJar.toString());
+        }
+    }
+
+    @Test
+    public void updateFoo() throws IOException {
+        Path mp = Paths.get("updateFoo");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--no-manifest",
+            "-C", modClasses.toString(), "jdk")
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), "module-info.class")
+            .assertSuccess();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    @Test
+    public void partialUpdateFooMainClass() throws IOException {
+        Path mp = Paths.get("partialUpdateFooMainClass");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        // A "bad" main class in first create ( and no version )
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + "IAmNotTheEntryPoint",
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")  // includes module-info.class
+           .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest")
+            .assertSuccess();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    @Test
+    public void partialUpdateFooVersion() throws IOException {
+        Path mp = Paths.get("partialUpdateFooVersion");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        // A "bad" version in first create ( and no main class )
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--module-version=" + "100000000",
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")  // includes module-info.class
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest")
+            .assertSuccess();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    @Test
+    public void partialUpdateFooNotAllFiles() throws IOException {
+        Path mp = Paths.get("partialUpdateFooNotAllFiles");
+        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();
+        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();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    @Test
+    public void partialUpdateFooAllFilesAndAttributes() throws IOException {
+        Path mp = Paths.get("partialUpdateFooAllFilesAndAttributes");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        // all attributes and files
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    @Test
+    public void partialUpdateFooModuleInfo() throws IOException {
+        Path mp = Paths.get("partialUpdateFooModuleInfo");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+        Path barModInfo = MODULE_CLASSES.resolve(BAR.moduleName);
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--no-manifest",
+            "-C", barModInfo.toString(), "module-info.class")  // stuff in bar's info
+            .assertSuccess();
+        jar("-p",
+            "--file=" + modularJar.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                // Expect similar output: "Name:bar,  Requires: foo,...
+                // Conceals: jdk.test.foo, jdk.test.foo.internal"
+                Pattern p = Pattern.compile("\\s+Name:\\s+bar\\s+Requires:\\s+foo");
+                assertTrue(p.matcher(r.output).find(),
+                           "Expecting to find \"Name: bar, Requires: foo,...\"",
+                           "in output, but did not: [" + r.output + "]");
+                p = Pattern.compile(
+                        "Conceals:\\s+jdk.test.foo\\s+jdk.test.foo.internal");
+                assertTrue(p.matcher(r.output).find(),
+                           "Expecting to find \"Conceals: jdk.test.foo,...\"",
+                           "in output, but did not: [" + r.output + "]");
+            });
+    }
+
+    @Test
+    public void dependencesFooBar() throws IOException {
+        Path mp = Paths.get("dependencesFooBar");
+        createTestDir(mp);
+
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+
+        modClasses = MODULE_CLASSES.resolve(BAR.moduleName);
+        modularJar = mp.resolve(BAR.moduleName + ".jar");
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + BAR.mainClass,
+            "--module-version=" + BAR.version,
+            "--modulepath=" + mp.toString(),
+            "--hash-dependencies=" + "foo",  // dependency on foo
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+
+        java(mp, BAR.moduleName + "/" + BAR.mainClass,
+             "-XaddExports:java.base/jdk.internal.module=bar")
+            .assertSuccess()
+            .resultChecker(r -> {
+                assertModuleData(r, BAR);
+                TestModuleData received = TestModuleData.from(r.output);
+                assertTrue(received.hashes != null, "Expected non-null hashes value.");
+            });
+    }
+
+    @Test
+    public void badDependencyFooBar() throws IOException {
+        Path mp = Paths.get("badDependencyFooBar");
+        createTestDir(mp);
+
+        Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path fooJar = mp.resolve(FOO.moduleName + ".jar");
+        jar("--create",
+            "--file=" + fooJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", fooClasses.toString(), ".").assertSuccess();
+
+        Path barClasses = MODULE_CLASSES.resolve(BAR.moduleName);
+        Path barJar = mp.resolve(BAR.moduleName + ".jar");
+        jar("--create",
+            "--file=" + barJar.toString(),
+            "--main-class=" + BAR.mainClass,
+            "--module-version=" + BAR.version,
+            "--modulepath=" + mp.toString(),
+            "--hash-dependencies=" + "foo",  // dependency on foo
+            "--no-manifest",
+            "-C", barClasses.toString(), ".").assertSuccess();
+
+        // Rebuild foo.jar with a change that will cause its hash to be different
+        FileUtils.deleteFileWithRetry(fooJar);
+        jar("--create",
+            "--file=" + fooJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version + ".1", // a newer version
+            "--no-manifest",
+            "-C", fooClasses.toString(), ".").assertSuccess();
+
+        java(mp, BAR.moduleName + "/" + BAR.mainClass,
+             "-XaddExports:java.base/jdk.internal.module=bar")
+            .assertFailure()
+            .resultChecker(r -> {
+                // Expect similar output: "java.lang.module.ResolutionException: Hash
+                // of foo (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to
+                // expected hash (iepvdv8xTeVrFgMtUhcFnmetSub6qQHCHc92lSaSEg0=)"
+                Pattern p = Pattern.compile(".*Hash of foo.*differs to expected hash.*");
+                assertTrue(p.matcher(r.output).find(),
+                      "Expecting error message containing \"Hash of foo ... differs to"
+                              + " expected hash...\" but got: [", r.output + "]");
+            });
+    }
+
+    @Test
+    public void badOptionsFoo() throws IOException {
+        Path mp = Paths.get("badOptionsFoo");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--module-version=" + 1.1,   // no module-info.class
+            "-C", modClasses.toString(), "jdk")
+            .assertFailure();      // TODO: expected failure message
+
+         jar("--create",
+             "--file=" + modularJar.toString(),
+             "--hash-dependencies=" + ".*",   // no module-info.class
+             "-C", modClasses.toString(), "jdk")
+             .assertFailure();      // TODO: expected failure message
+    }
+
+    @Test
+    public void servicesCreateWithoutFailure() throws IOException {
+        Path mp = Paths.get("servicesCreateWithoutFailure");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve("baz");
+        Path modularJar = mp.resolve("baz" + ".jar");
+
+        // Positive test, create
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "module-info.class",
+            "-C", modClasses.toString(), "jdk/test/baz/BazService.class",
+            "-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
+            .assertSuccess();
+    }
+
+    @Test
+    public void servicesCreateWithoutServiceImpl() throws IOException {
+        Path mp = Paths.get("servicesWithoutServiceImpl");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve("baz");
+        Path modularJar = mp.resolve("baz" + ".jar");
+
+        // Omit service impl
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "module-info.class",
+            "-C", modClasses.toString(), "jdk/test/baz/BazService.class")
+            .assertFailure();
+    }
+
+    @Test
+    public void servicesUpdateWithoutFailure() throws IOException {
+        Path mp = Paths.get("servicesUpdateWithoutFailure");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve("baz");
+        Path modularJar = mp.resolve("baz" + ".jar");
+
+        // Positive test, update
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "jdk/test/baz/BazService.class",
+            "-C", modClasses.toString(), "jdk/test/baz/internal/BazServiceImpl.class")
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "module-info.class")
+            .assertSuccess();
+    }
+
+    @Test
+    public void servicesUpdateWithoutServiceImpl() throws IOException {
+        Path mp = Paths.get("servicesUpdateWithoutServiceImpl");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve("baz");
+        Path modularJar = mp.resolve("baz" + ".jar");
+
+        // Omit service impl
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "jdk/test/baz/BazService.class")
+            .assertSuccess();
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "module-info.class")
+            .assertFailure();
+    }
+
+    @Test
+    public void printModuleDescriptorFoo() throws IOException {
+        Path mp = Paths.get("printModuleDescriptorFoo");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+
+        for (String option : new String[]  {"--print-module-descriptor", "-p" }) {
+            jar(option,
+                "--file=" + modularJar.toString())
+                .assertSuccess()
+                .resultChecker(r ->
+                    assertTrue(r.output.contains(FOO.moduleName + "@" + FOO.version),
+                               "Expected to find ", FOO.moduleName + "@" + FOO.version,
+                               " in [", r.output, "]")
+                );
+        }
+    }
+
+    @Test
+    public void printModuleDescriptorFooFromStdin() throws IOException {
+        Path mp = Paths.get("printModuleDescriptorFooFromStdin");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), ".")
+            .assertSuccess();
+
+        for (String option : new String[]  {"--print-module-descriptor", "-p" }) {
+            jarWithStdin(modularJar.toFile(),
+                         option)
+                         .assertSuccess()
+                         .resultChecker(r ->
+                             assertTrue(r.output.contains(FOO.moduleName + "@" + FOO.version),
+                                "Expected to find ", FOO.moduleName + "@" + FOO.version,
+                                " in [", r.output, "]")
+                );
+        }
+    }
+
+    // -- Infrastructure
+
+    static Result jarWithStdin(File stdinSource, String... args) {
+        String jar = getJDKTool("jar");
+        List<String> commands = new ArrayList<>();
+        commands.add(jar);
+        Stream.of(args).forEach(x -> commands.add(x));
+        ProcessBuilder p = new ProcessBuilder(commands);
+        if (stdinSource != null)
+            p.redirectInput(stdinSource);
+        return run(p);
+    }
+
+    static Result jar(String... args) {
+        return jarWithStdin(null, args);
+    }
+
+    static Path compileModule(String mn) throws IOException {
+        return compileModule(mn, null);
+    }
+
+    static Path compileModule(String mn, Path mp)
+        throws IOException
+    {
+        Path fooSourcePath = TEST_SRC.resolve("src").resolve(mn);
+        Path build = Files.createDirectories(MODULE_CLASSES.resolve(mn));
+        javac(build, mp, fileList(fooSourcePath));
+        return build;
+    }
+
+    // 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,
+//                   Arrays.asList(sourceFiles));
+//        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+//        try (StandardJavaFileManager fileManager =
+//                     compiler.getStandardFileManager(null, null, null)) {
+//
+//            List<File> files = Stream.of(sourceFiles)
+//                                     .map(p -> p.toFile())
+//                                     .collect(Collectors.toList());
+//            List<File> dests = Stream.of(dest)
+//                                     .map(p -> p.toFile())
+//                                     .collect(Collectors.toList());
+//            Iterable<? extends JavaFileObject> compilationUnits =
+//                    fileManager.getJavaFileObjectsFromFiles(files);
+//            fileManager.setLocation(StandardLocation.CLASS_OUTPUT, dests);
+//            JavaCompiler.CompilationTask task =
+//                    compiler.getTask(null, fileManager, null, null, null, compilationUnits);
+//            boolean passed = task.call();
+//            if (!passed)
+//                throw new RuntimeException("Error compiling " + files);
+//        }
+//    }
+
+    static void javac(Path dest, Path... sourceFiles) throws IOException {
+        javac(dest, null, sourceFiles);
+    }
+
+    static void javac(Path dest, Path modulePath, Path... sourceFiles)
+        throws IOException
+    {
+        String javac = getJDKTool("javac");
+
+        List<String> commands = new ArrayList<>();
+        commands.add(javac);
+        commands.add("-d");
+        commands.add(dest.toString());
+        if (dest.toString().contains("bar"))
+            commands.add("-XaddExports:java.base/jdk.internal.module=bar");
+        if (modulePath != null) {
+            commands.add("-mp");
+            commands.add(modulePath.toString());
+        }
+        Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
+
+        quickFail(run(new ProcessBuilder(commands)));
+    }
+
+    static Result java(Path modulePath, String entryPoint, String... args) {
+        String java = getJDKTool("java");
+
+        List<String> commands = new ArrayList<>();
+        commands.add(java);
+        Stream.of(args).forEach(x -> commands.add(x));
+        commands.add("-mp");
+        commands.add(modulePath.toString());
+        commands.add("-m");
+        commands.add(entryPoint);
+
+        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 void createTestDir(Path p) throws IOException{
+        if (Files.exists(p))
+            FileUtils.deleteFileTreeWithRetry(p);
+        Files.createDirectory(p);
+    }
+
+    static boolean jarContains(JarInputStream jis, String entryName)
+        throws IOException
+    {
+        JarEntry e;
+        while((e = jis.getNextJarEntry()) != null) {
+            if (e.getName().equals(entryName))
+                return true;
+        }
+        return false;
+    }
+
+    static void quickFail(Result r) {
+        if (r.ec != 0)
+            throw new RuntimeException(r.output);
+    }
+
+    static 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);
+    }
+
+    static final String DEFAULT_IMAGE_BIN = System.getProperty("java.home")
+            + File.separator + "bin" + File.separator;
+
+    static String getJDKTool(String name) {
+        try {
+            return JDKToolFinder.getJDKTool(name);
+        } catch (Exception x) {
+            return DEFAULT_IMAGE_BIN + name;
+        }
+    }
+
+    static 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;
+        }
+        Result assertSuccess() {
+            assertTrue(ec == 0, "Expected ec 0, got: ", ec, " , output [", output, "]");
+            return this;
+        }
+        Result assertFailure() {
+            assertTrue(ec != 0, "Expected ec != 0, got:", ec, " , output [", output, "]");
+            return this;
+        }
+        Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+    }
+
+    static void assertTrue(boolean cond, Object ... failedArgs) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : failedArgs)
+            sb.append(o);
+        org.testng.Assert.assertTrue(false, sb.toString());
+    }
+
+    // Standalone entry point.
+    public static void main(String[] args) throws Throwable {
+        Basic test = new Basic();
+        test.compileModules();
+        for (Method m : Basic.class.getDeclaredMethods()) {
+            if (m.getAnnotation(Test.class) != null) {
+                System.out.println("Invoking " + m.getName());
+                m.invoke(test);
+            }
+        }
+    }
+}
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
new file mode 100644
index 0000000..7d768fc
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.bar;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Method;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import jdk.internal.module.Hasher;
+import jdk.test.bar.internal.Message;
+
+public class Bar {
+    public static void main(String[] args) throws Exception {
+        System.out.println("message:" + Message.get());
+
+        ModuleDescriptor md = Bar.class.getModule().getDescriptor();
+        System.out.println("nameAndVersion:" + md.toNameAndVersion());
+        System.out.println("mainClass:" + md.mainClass().get());
+
+        Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
+        m.setAccessible(true);
+        Optional<Hasher.DependencyHashes> optHashes =
+                (Optional<Hasher.DependencyHashes>) m.invoke(md);
+
+        System.out.println("hashes:" + optHashes.get().hashFor("foo"));
+
+        StringJoiner sj = new StringJoiner(",");
+        md.conceals().forEach(sj::add);
+        System.out.println("conceals:" + sj.toString());
+    }
+}
diff --git a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java
new file mode 100644
index 0000000..17cbe3a
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/internal/Message.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.bar.internal;
+
+public class Message  {
+    public static String get() {
+        return "Hello from Bar!";
+    }
+}
diff --git a/jdk/test/tools/jar/modularJar/src/bar/module-info.java b/jdk/test/tools/jar/modularJar/src/bar/module-info.java
new file mode 100644
index 0000000..7296518
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/bar/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module bar {
+    requires foo;
+}
diff --git a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java
new file mode 100644
index 0000000..85c585f
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/BazService.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.test.baz;
+
+public interface BazService {
+    void doSomething();
+}
diff --git a/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java
new file mode 100644
index 0000000..5f41732
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/baz/jdk/test/baz/internal/BazServiceImpl.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.baz.internal;
+
+import jdk.test.baz.BazService;
+
+public class BazServiceImpl implements jdk.test.baz.BazService {
+    @Override public void doSomething() { }
+}
diff --git a/jdk/test/tools/jar/modularJar/src/baz/module-info.java b/jdk/test/tools/jar/modularJar/src/baz/module-info.java
new file mode 100644
index 0000000..8a35edb
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/baz/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module baz {
+    exports jdk.test.baz;
+    provides jdk.test.baz.BazService with jdk.test.baz.internal.BazServiceImpl;
+}
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
new file mode 100644
index 0000000..1cb3535
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.foo;
+
+import java.lang.module.ModuleDescriptor;
+import java.util.StringJoiner;
+
+import jdk.test.foo.internal.Message;
+
+public class Foo {
+    public static void main(String[] args) {
+        System.out.println("message:" + Message.get());
+
+        ModuleDescriptor md = Foo.class.getModule().getDescriptor();
+        System.out.println("nameAndVersion:" + md.toNameAndVersion());
+        System.out.println("mainClass:" + md.mainClass().get());
+
+        StringJoiner sj = new StringJoiner(",");
+        md.conceals().forEach(sj::add);
+        System.out.println("conceals:" + sj.toString());
+    }
+}
diff --git a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java
new file mode 100644
index 0000000..298a4fc
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/internal/Message.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.foo.internal;
+
+public class Message  {
+    public static String get() {
+        return "Hello World!!!";
+    }
+}
diff --git a/jdk/test/tools/jar/modularJar/src/foo/module-info.java b/jdk/test/tools/jar/modularJar/src/foo/module-info.java
new file mode 100644
index 0000000..b46afa0
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/foo/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module foo {
+    exports jdk.test.foo;
+}
diff --git a/jdk/test/tools/jimage/JImageTest.java b/jdk/test/tools/jimage/JImageTest.java
new file mode 100644
index 0000000..be1e784
--- /dev/null
+++ b/jdk/test/tools/jimage/JImageTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.io.File;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.JImageValidator;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+/*
+ * jimage testing.
+ * @test
+ * @summary Test jimage tool
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.compiler
+ * @run build JImageTest
+ * @run build tests.*
+ * @run main/othervm -verbose:gc -Xmx1g JImageTest
+*/
+public class JImageTest {
+
+    public static void main(String[] args) throws Exception {
+        List<String> bootClasses = new ArrayList<>();
+
+        FileSystem fs;
+        try {
+            fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
+            System.out.println("Not an image build, test skipped.");
+            return;
+        }
+
+        // Build the set of locations expected in the Image
+        Consumer<Path> c = (p) -> {
+               // take only the .class resources.
+               if (Files.isRegularFile(p) && p.toString().endsWith(".class")
+                       && !p.toString().endsWith("module-info.class")) {
+                   String loc = p.toString().substring("/modules".length());
+                   bootClasses.add(loc);
+               }
+           };
+
+        Path javabase = fs.getPath("/modules/java.base");
+        Path mgtbase = fs.getPath("/modules/java.management");
+        try (Stream<Path> stream = Files.walk(javabase)) {
+            stream.forEach(c);
+        }
+        try (Stream<Path> stream = Files.walk(mgtbase)) {
+            stream.forEach(c);
+        }
+
+        if (bootClasses.isEmpty()) {
+            throw new RuntimeException("No boot class to check against");
+        }
+
+        File jdkHome = new File(System.getProperty("test.jdk"));
+        // JPRT not yet ready for jmods
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run, NO jmods directory");
+            return;
+        }
+
+        // Generate the sample image
+        String module = "mod1";
+        String[] classes = {module + ".Main"};
+        helper.generateDefaultJModule(module, Arrays.asList(classes), "java.management");
+
+        Path image = helper.generateDefaultImage(module).assertSuccess();
+        Path extractedDir = JImageGenerator.getJImageTask()
+                .dir(helper.createNewExtractedDir("modules"))
+                .image(image.resolve("lib").resolve("modules"))
+                .extract().assertSuccess();
+
+        Path recreatedImage = JImageGenerator.getJImageTask()
+                .dir(extractedDir)
+                .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString()))
+                .recreate().assertSuccess();
+        JImageValidator.validate(recreatedImage, bootClasses, Collections.emptyList());
+
+        // Check replacing the boot image by recreated one
+        Path destFile = image.resolve("lib").resolve("modules");
+        Files.copy(recreatedImage, destFile, REPLACE_EXISTING);
+        JImageValidator validator = new JImageValidator(module, Collections.emptyList(),
+                image.toFile(), Collections.emptyList(), Collections.emptyList());
+        validator.validate();
+
+        Path recreatedImage2 = JImageGenerator.getJImageTask()
+                .dir(extractedDir)
+                .option("--compress").option("2")
+                .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString()))
+                .recreate().assertSuccess();
+        JImageValidator.validate(recreatedImage2, bootClasses, Collections.emptyList());
+
+        Path recreatedImage3 = JImageGenerator.getJImageTask()
+                .dir(extractedDir)
+                .option("--strip-debug")
+                .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString()))
+                .recreate().assertSuccess();
+        JImageValidator.validate(recreatedImage3, bootClasses, Collections.emptyList());
+
+        Path recreatedImage4 = JImageGenerator.getJImageTask()
+                .dir(extractedDir)
+                .option("--exclude-resources")
+                .option("*.jcov, */META-INF/*")
+                .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString()))
+                .recreate().assertSuccess();
+        List<String> unexpectedPaths = new ArrayList<>();
+        unexpectedPaths.add(".jcov");
+        unexpectedPaths.add("/META-INF/");
+        JImageValidator.validate(recreatedImage4, bootClasses, unexpectedPaths);
+
+        Path recreatedImage5 = JImageGenerator.getJImageTask()
+                .dir(extractedDir)
+                .option("--compress")
+                .option("2")
+                .option("--strip-debug")
+                .option("--exclude-resources")
+                .option("*.jcov, */META-INF/*")
+                .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString()))
+                .recreate().assertSuccess();
+        JImageValidator.validate(recreatedImage5, bootClasses, unexpectedPaths);
+    }
+}
diff --git a/jdk/test/tools/jimage/JImageToolTest.java b/jdk/test/tools/jimage/JImageToolTest.java
new file mode 100644
index 0000000..18f22f1
--- /dev/null
+++ b/jdk/test/tools/jimage/JImageToolTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @summary Test to see if jimage tool extracts and recreates correctly.
+ * @run main/timeout=360 JImageToolTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jdk.testlibrary.ProcessTools;
+
+/**
+ * Basic test for jimage tool.
+ */
+public class JImageToolTest {
+    private static void jimage(String... jimageArgs) throws Exception {
+        ArrayList<String> args = new ArrayList<>();
+        args.add("-ms8m");
+        args.add("jdk.tools.jimage.Main");
+        args.addAll(Arrays.asList(jimageArgs));
+
+        ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
+        int res = builder.inheritIO().start().waitFor();
+
+        if (res != 0) {
+            throw new RuntimeException("JImageToolTest FAILED");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String home = System.getProperty("java.home");
+        Path jimagePath = Paths.get(home, "bin", "jimage");
+        Path modulesimagePath = Paths.get(home, "lib", "modules");
+
+        if (Files.exists(jimagePath) && Files.exists(modulesimagePath)) {
+            String jimage = jimagePath.toAbsolutePath().toString();
+            String bootimage = modulesimagePath.toAbsolutePath().toString();
+            String extractDir = Paths.get(".", "extract").toAbsolutePath().toString();
+            String recreateImage = Paths.get(".", "recreate").toAbsolutePath().toString();
+            String relativeRecreateImage = Paths.get(".", "recreate2").toString();
+            jimage("extract", "--dir", extractDir, bootimage);
+            jimage("recreate", "--dir", extractDir, recreateImage);
+            jimage("recreate", "--dir", extractDir, relativeRecreateImage);
+            System.out.println("Test successful");
+         } else {
+            System.out.println("Test skipped, not an images build");
+         }
+    }
+}
diff --git a/jdk/test/tools/jimage/VerifyJimage.java b/jdk/test/tools/jimage/VerifyJimage.java
new file mode 100644
index 0000000..c31eb88
--- /dev/null
+++ b/jdk/test/tools/jimage/VerifyJimage.java
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.DirectoryStream;
+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.Deque;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.jimage.BasicImageReader;
+import jdk.internal.jimage.ImageLocation;
+
+/*
+ * @test
+ * @summary Verify jimage
+ * @modules java.base/jdk.internal.jimage
+ */
+
+/**
+ * This test runs in two modes:
+ * (1) No argument: it verifies the jimage by loading all classes in the runtime
+ * (2) path of exploded modules: it compares bytes of each file in the exploded
+ *     module with the entry in jimage
+ *
+ * FIXME: exception thrown when findLocation from jimage by multiple threads
+ * -Djdk.test.threads=<n> to specify the number of threads.
+ */
+public class VerifyJimage {
+    private static final String MODULE_INFO = "module-info.class";
+    private static final Deque<String> failed = new ConcurrentLinkedDeque<>();
+
+    public static void main(String... args) throws Exception {
+
+        String home = System.getProperty("java.home");
+        Path bootimagePath = Paths.get(home, "lib", "modules");
+        if (Files.notExists(bootimagePath)) {
+             System.out.println("Test skipped, not an images build");
+             return;
+        }
+
+        long start = System.nanoTime();
+        int numThreads = Integer.getInteger("jdk.test.threads", 1);
+        List<JImageReader> readers = newJImageReaders();
+        VerifyJimage verify = new VerifyJimage(readers, numThreads);
+        if (args.length == 0) {
+            // load classes from jimage
+            verify.loadClasses();
+        } else {
+            Path dir = Paths.get(args[0]);
+            if (Files.notExists(dir) || !Files.isDirectory(dir)) {
+                throw new RuntimeException("Invalid argument: " + dir);
+            }
+            verify.compareExplodedModules(dir);
+        }
+        verify.waitForCompletion();
+        long end = System.nanoTime();
+        int entries = readers.stream()
+                             .mapToInt(JImageReader::entries)
+                             .sum();
+        System.out.format("%d entries %d files verified: %d ms %d errors%n",
+                          entries, verify.count.get(),
+                          TimeUnit.NANOSECONDS.toMillis(end - start), failed.size());
+        for (String f : failed) {
+            System.err.println(f);
+        }
+        if (!failed.isEmpty()) {
+            throw new AssertionError("Test failed");
+        }
+    }
+
+    private final AtomicInteger count = new AtomicInteger(0);
+    private final List<JImageReader> readers;
+    private final ExecutorService pool;
+
+    VerifyJimage(List<JImageReader> readers, int numThreads) {
+        this.readers = readers;
+        this.pool = Executors.newFixedThreadPool(numThreads);
+    }
+
+    private void waitForCompletion() throws InterruptedException {
+        pool.shutdown();
+        pool.awaitTermination(20, TimeUnit.SECONDS);
+    }
+
+    private void compareExplodedModules(Path dir) throws IOException {
+        System.out.println("comparing jimage with " + dir);
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
+            for (Path mdir : stream) {
+                if (Files.isDirectory(mdir)) {
+                    pool.execute(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                Files.find(mdir, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr)
+                                           -> !Files.isDirectory(p) &&
+                                              !mdir.relativize(p).toString().startsWith("_") &&
+                                              !p.getFileName().toString().equals("MANIFEST.MF"))
+                                     .forEach(p -> compare(mdir, p, readers));
+                            } catch (IOException e) {
+                                throw new UncheckedIOException(e);
+                            }
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    private final List<String> BOOT_RESOURCES = Arrays.asList(
+        "java.base/META-INF/services/java.nio.file.spi.FileSystemProvider"
+    );
+    private final List<String> EXT_RESOURCES = Arrays.asList(
+        "jdk.zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider"
+    );
+    private final List<String> APP_RESOURCES = Arrays.asList(
+        "jdk.hotspot.agent/META-INF/services/com.sun.jdi.connect.Connector",
+        "jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector"
+    );
+
+    private void compare(Path mdir, Path p, List<JImageReader> readers) {
+        String entry = p.getFileName().toString().equals(MODULE_INFO)
+                ? mdir.getFileName().toString() + "/" + MODULE_INFO
+                : mdir.relativize(p).toString().replace(File.separatorChar, '/');
+
+        count.incrementAndGet();
+        String file = mdir.getFileName().toString() + "/" + entry;
+        if (APP_RESOURCES.contains(file)) {
+            // skip until the service config file is merged
+            System.out.println("Skipped " + file);
+            return;
+        }
+
+        String jimage = "modules";
+        JImageReader reader = readers.stream()
+                .filter(r -> r.findLocation(entry) != null)
+                .filter(r -> jimage.isEmpty() || r.imageName().equals(jimage))
+                .findFirst().orElse(null);
+        if (reader == null) {
+            failed.add(entry + " not found: " + p.getFileName().toString());
+        } else {
+            reader.compare(entry, p);
+        }
+    }
+
+    private void loadClasses() {
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+        for (JImageReader reader : readers) {
+            Arrays.stream(reader.getEntryNames())
+                    .filter(n -> n.endsWith(".class") && !n.endsWith(MODULE_INFO))
+                    .forEach(n -> {
+                        String cn = removeModule(n).replaceAll("\\.class$", "").replace('/', '.');
+                        count.incrementAndGet();
+                        try {
+                            Class.forName(cn, false, loader);
+                        } catch (ClassNotFoundException e) {
+                            failed.add(reader.imageName() + ": " + cn + " not found");
+                        }
+                    });
+        }
+    }
+
+    private String removeModule(String path) {
+        int index = path.indexOf('/', 1);
+        return path.substring(index + 1, path.length());
+    }
+
+    private static List<JImageReader> newJImageReaders() throws IOException {
+        String home = System.getProperty("java.home");
+        Path jimage = Paths.get(home, "lib", "modules");
+        JImageReader reader = new JImageReader(jimage);
+        List<JImageReader> result = new ArrayList<>();
+        System.out.println("opened " + jimage);
+        result.add(reader);
+        return result;
+    }
+
+    static class JImageReader extends BasicImageReader {
+        final Path jimage;
+        JImageReader(Path p) throws IOException {
+            super(p);
+            this.jimage = p;
+        }
+
+        String imageName() {
+            return jimage.getFileName().toString();
+        }
+
+        int entries() {
+            return getHeader().getTableLength();
+        }
+
+        void compare(String entry, Path p) {
+            try {
+                byte[] bytes = Files.readAllBytes(p);
+                byte[] imagebytes = getResource(entry);
+                if (!Arrays.equals(bytes, imagebytes)) {
+                    failed.add(imageName() + ": bytes differs than " + p.toString());
+                }
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/CheckExecutable.java b/jdk/test/tools/jlink/CheckExecutable.java
new file mode 100644
index 0000000..4533544
--- /dev/null
+++ b/jdk/test/tools/jlink/CheckExecutable.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 8132475
+ * @summary Check that jlink creates executables in the bin directory
+ *          that are are executable by all users
+ * @run main CheckExecutable
+ * @author Volker Simonis
+ */
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.PosixFilePermission;
+import static java.nio.file.attribute.PosixFilePermission.*;
+import java.util.EnumSet;
+import java.util.Set;
+
+public class CheckExecutable {
+
+    // The bin directory may contain non-executable files (see 8132704)
+    private static final String IGNORE = "glob:{*.diz,jmc.ini}";
+
+    public static void main(String args[]) throws IOException {
+        String JAVA_HOME = System.getProperty("java.home");
+        Path bin = Paths.get(JAVA_HOME, "bin");
+
+        PathMatcher matcher = FileSystems.getDefault().getPathMatcher(IGNORE);
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(bin)) {
+            EnumSet<PosixFilePermission> execPerms
+                = EnumSet.of(GROUP_EXECUTE, OTHERS_EXECUTE, OWNER_EXECUTE);
+
+            for (Path entry : stream) {
+                Path file = entry.getFileName();
+                if (!Files.isRegularFile(entry) || matcher.matches(file)) {
+                    continue;
+                }
+
+                if (!Files.isExecutable(entry))
+                    throw new RuntimeException(entry + " is not executable!");
+
+                try {
+                    Set<PosixFilePermission> perm
+                        = Files.getPosixFilePermissions(entry);
+                    if (!perm.containsAll(execPerms)) {
+                        throw new RuntimeException(entry
+                            + " has not all executable permissions!\n"
+                            + "Should have: " + execPerms + "\nbut has: " + perm);
+                    }
+                } catch (UnsupportedOperationException uoe) { }
+
+            }
+
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/CustomPluginTest.java b/jdk/test/tools/jlink/CustomPluginTest.java
new file mode 100644
index 0000000..34e4d4b
--- /dev/null
+++ b/jdk/test/tools/jlink/CustomPluginTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.Result;
+
+/*
+ * @test
+ * @summary Test custom plugin
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm CustomPluginTest
+ */
+
+public class CustomPluginTest {
+
+    public static void main(String[] args) throws Exception {
+        new CustomPluginTest().test();
+    }
+
+    private void test() throws Exception {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+        Path jmod = registerServices(helper);
+        Path pluginModulePath = jmod.getParent();
+
+        testHelloProvider(helper, pluginModulePath);
+        testCustomPlugins(helper, pluginModulePath);
+    }
+
+    private void testCustomPlugins(Helper helper, Path pluginModulePath) {
+        Result result = JImageGenerator.getJLinkTask()
+                .option("--list-plugins")
+                .pluginModulePath(pluginModulePath)
+                .output(helper.createNewImageDir("customplugin"))
+                .call();
+        if (result.getExitCode() != 0) {
+            System.err.println(result.getMessage());
+            throw new AssertionError("jlink crashed: " + result.getExitCode());
+        }
+        List<String> customPlugins = Stream.of(result.getMessage().split("\n"))
+                .filter(s -> s.startsWith("Plugin Name:"))
+                .filter(s -> s.contains("custom"))
+                .collect(Collectors.toList());
+        if (customPlugins.size() != 1) {
+            System.err.println(result.getMessage());
+            throw new AssertionError("Found plugins: " + customPlugins);
+        }
+    }
+
+    private Path registerServices(Helper helper) throws IOException {
+        String name = "customplugin";
+        Path src = Paths.get(System.getProperty("test.src")).resolve(name);
+        Path classes = helper.getJmodClassesDir().resolve(name);
+        JImageGenerator.compile(src, classes, "-XaddExports:jdk.jlink/jdk.tools.jlink.internal=customplugin");
+        return JImageGenerator.getJModTask()
+                .addClassPath(classes)
+                .jmod(helper.getJmodDir().resolve(name + ".jmod"))
+                .create().assertSuccess();
+    }
+
+    private void testHelloProvider(Helper helper, Path pluginModulePath) throws IOException {
+        Path pluginFile = Paths.get("customplugin.txt");
+        if (Files.exists(pluginFile)) {
+            throw new AssertionError("Custom plugin output file already exists");
+        }
+        String customplugin = "customplugin";
+        {
+            // Add the path but not the option, plugin musn't be called
+            JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .pluginModulePath(pluginModulePath)
+                    .output(helper.createNewImageDir(customplugin))
+                    .addMods(customplugin)
+                    .call().assertSuccess();
+        }
+
+        if (Files.exists(pluginFile)) {
+            throw new AssertionError("Custom plugin output file exists, plugin "
+                    + " called although shouldn't have been");
+        }
+
+        { // Add the path and the option, plugin should be called.
+            JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .addMods(customplugin)
+                    .pluginModulePath(pluginModulePath)
+                    .output(helper.createNewImageDir(customplugin))
+                    .option("--hello")
+                    .call().assertSuccess();
+        }
+
+        if (!Files.exists(pluginFile)) {
+            throw new AssertionError("Custom plugin not called");
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/DefaultProviderTest.java b/jdk/test/tools/jlink/DefaultProviderTest.java
new file mode 100644
index 0000000..22c6828
--- /dev/null
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import tests.Helper;
+
+/*
+ * @test
+ * @summary Test plugins enabled by default
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm DefaultProviderTest
+ */
+public class DefaultProviderTest {
+    private static final String NAME = "disable-toto";
+    private final static Map<String, Object> expectedOptions = new HashMap<>();
+
+    static {
+        expectedOptions.put("disable-toto", "false");
+        expectedOptions.put("option1", "value1");
+        expectedOptions.put("option2", "value2");
+    }
+
+    private static class Custom implements TransformerPlugin {
+        private boolean enabled = true;
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public Set<STATE> getState() {
+             return enabled ? EnumSet.of(STATE.AUTO_ENABLED, STATE.FUNCTIONAL)
+                : EnumSet.of(STATE.DISABLED);
+        }
+
+        @Override
+        public void visit(Pool in, Pool out) {
+            if (!enabled) {
+                throw new PluginException(NAME + " was set");
+            }
+
+            DefaultProviderTest.isNewPluginsCalled = true;
+            in.visit((Pool.ModuleData content) -> {
+                return content;
+            }, out);
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public String getDescription() {
+            return NAME;
+        }
+
+        @Override
+        public boolean hasArguments() {
+            return true;
+        }
+
+        @Override
+        public void configure(Map<String, String> config) {
+            if (config.containsKey(NAME)) {
+                enabled = !Boolean.parseBoolean(config.get(NAME));
+            }
+
+            if (enabled) {
+                DefaultProviderTest.receivedOptions = config;
+            } else {
+                DefaultProviderTest.receivedOptions = null;
+            }
+        }
+    }
+
+    private static boolean isNewPluginsCalled;
+    private static Map<String, String> receivedOptions;
+
+    private static void reset() {
+        isNewPluginsCalled = false;
+        receivedOptions = null;
+    }
+
+    public static void main(String[] args) throws Exception {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+        test(helper, new Custom());
+    }
+
+    private static void test(Helper helper, Plugin plugin) throws Exception {
+        PluginRepository.registerPlugin(plugin);
+
+        {
+            String[] userOptions = {};
+            Path imageDir = helper.generateDefaultImage(userOptions, "composite2").assertSuccess();
+            helper.checkImage(imageDir, "composite2", null, null);
+            if (!isNewPluginsCalled) {
+                throw new Exception("Should have been called");
+            }
+            reset();
+        }
+
+        {
+            String[] userOptions = {"--disable-toto=false:option1=value1:option2=value2"};
+            Path imageDir = helper.generateDefaultImage(userOptions, "composite2").assertSuccess();
+            helper.checkImage(imageDir, "composite2", null, null);
+            if (!isNewPluginsCalled) {
+                throw new Exception("Should have been called");
+            }
+            if (!receivedOptions.equals(expectedOptions)) {
+                throw new Exception("Optional options " + receivedOptions + " are not expected one "
+                        + expectedOptions);
+            }
+            System.err.println("OPTIONS " + receivedOptions);
+            reset();
+        }
+
+        {
+            String[] userOptions = {"--disable-toto=true:option1=value1"};
+            Path imageDir = helper.generateDefaultImage(userOptions, "composite2").assertSuccess();
+            helper.checkImage(imageDir, "composite2", null, null);
+            if (isNewPluginsCalled) {
+                throw new Exception("Should not have been called");
+            }
+            if (receivedOptions != null) {
+                throw new Exception("Optional options are not expected");
+            }
+            reset();
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/ImageFileCreatorTest.java b/jdk/test/tools/jlink/ImageFileCreatorTest.java
new file mode 100644
index 0000000..a674925
--- /dev/null
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteOrder;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import jdk.tools.jlink.internal.Archive;
+import jdk.tools.jlink.internal.ImageFileCreator;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.plugin.Pool;
+
+
+/*
+ * @test
+ * @summary ImageFileCreator class test
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          java.base/jdk.internal.jimage
+ * @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
+ */
+public class ImageFileCreatorTest {
+
+    private static class TestArchive implements Archive {
+
+        private final String name;
+        private final List<Entry> entries = new ArrayList<>();
+
+        private TestArchive(String name, List<String> entries) {
+            this.name = name;
+            for (String p : entries) {
+                this.entries.add(new TestEntry(p, p));
+            }
+        }
+
+        @Override
+        public String moduleName() {
+            return name;
+        }
+
+        @Override
+        public Stream<Entry> entries() {
+            return entries.stream();
+        }
+
+        @Override
+        public Path getPath() {
+            return null;
+        }
+
+        @Override
+        public void open() throws IOException {
+        }
+
+        @Override
+        public void close() throws IOException {
+        }
+
+        private class TestEntry extends Entry {
+
+            TestEntry(String path, String name) {
+                super(TestArchive.this, path, name, Entry.EntryType.CLASS_OR_RESOURCE);
+            }
+
+            @Override
+            public long size() {
+                return 0;
+            }
+
+            @Override
+            public InputStream stream() throws IOException {
+                return new ByteArrayInputStream(new byte[0]);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        {
+            List<String> entries = new ArrayList<>();
+            entries.add("classes/class");
+            test(entries);
+        }
+
+        {
+            // Add an entry that is a directory, that is wrong
+            List<String> entries = new ArrayList<>();
+            entries.add("classes");
+            entries.add("classes/class");
+            test(entries);
+        }
+
+        {
+            // Add an entry that is wrongly prefixed by /
+            // /bad//classes/class is the resource added
+            // /bad/classes/class is the metadata node built.
+            List<String> entries = new ArrayList<>();
+            entries.add("/classes/class");
+            test(entries);
+        }
+
+        {
+            // Trailing '/' is wrong
+            List<String> entries = new ArrayList<>();
+            entries.add("classes/class/");
+            test(entries);
+        }
+
+        {
+            // Too much '/' characters
+            List<String> entries = new ArrayList<>();
+            entries.add("classes//class/");
+            test(entries);
+        }
+
+        {
+            // Too much '/' characters
+            List<String> entries = new ArrayList<>();
+            entries.add("classes/////class/");
+            test(entries);
+        }
+
+        {
+            // Single '/' character
+            List<String> entries = new ArrayList<>();
+            entries.add("/");
+            test(entries);
+        }
+
+        {
+            // 2 '/' characters
+            List<String> entries = new ArrayList<>();
+            entries.add("//");
+            test(entries);
+        }
+
+        {
+            // 3 '/' characters
+            List<String> entries = new ArrayList<>();
+            entries.add("///");
+            test(entries);
+        }
+
+        {
+            // no character
+            List<String> entries = new ArrayList<>();
+            entries.add("");
+            test(entries);
+        }
+
+        {
+            // all together
+            List<String> entries = new ArrayList<>();
+            entries.add("");
+            entries.add("///");
+            entries.add("//");
+            entries.add("/");
+            entries.add("classes/////class/");
+            entries.add("classes//class/");
+            entries.add("classes/class/");
+            entries.add("/classes/class");
+            entries.add("classes");
+            entries.add("classes/class");
+            test(entries);
+        }
+
+    }
+
+    private static void test(List<String> entries) throws Exception {
+        TestArchive arch = new TestArchive("bad", entries);
+        Set<Archive> archives = new HashSet<>();
+        archives.add(arch);
+        ImageBuilder noopBuilder = new ImageBuilder() {
+
+            @Override
+            public DataOutputStream getJImageOutputStream() {
+                return new DataOutputStream(new ByteArrayOutputStream());
+            }
+
+            @Override
+            public ExecutableImage getExecutableImage() {
+                return null;
+            }
+
+            @Override
+            public void storeFiles(Pool content, String bom) {
+
+            }
+
+        };
+
+        ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(),
+                null, Collections.emptyList(), "");
+
+        ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack);
+    }
+}
diff --git a/jdk/test/tools/jlink/ImageFilePoolTest.java b/jdk/test/tools/jlink/ImageFilePoolTest.java
new file mode 100644
index 0000000..7d35f9d
--- /dev/null
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test a pool containing external files.
+ * @author Andrei Eremeev
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ * @run build ImageFilePoolTest
+ * @run main ImageFilePoolTest
+ */
+
+import java.io.ByteArrayInputStream;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.Pool.Visitor;
+
+public class ImageFilePoolTest {
+    public static void main(String[] args) throws Exception {
+        new ImageFilePoolTest().test();
+    }
+
+    public void test() throws Exception {
+        checkNegative();
+        checkVisitor();
+    }
+
+    private static final String SUFFIX = "END";
+
+    private void checkVisitor() throws Exception {
+        Pool input = new PoolImpl();
+        for (int i = 0; i < 1000; ++i) {
+            String module = "module" + (i / 100);
+            input.add(new InMemoryImageFile(module, "/" + module + "/java/class" + i,
+                    ModuleDataType.CONFIG, "class" + i));
+        }
+        if (input.getContent().size() != 1000) {
+            throw new AssertionError();
+        }
+        Pool output = new PoolImpl();
+        ResourceVisitor visitor = new ResourceVisitor();
+        input.visit(visitor, output);
+        if (visitor.getAmountBefore() == 0) {
+            throw new AssertionError("Resources not found");
+        }
+        if (visitor.getAmountBefore() != input.getContent().size()) {
+            throw new AssertionError("Number of visited resources. Expected: " +
+                    visitor.getAmountBefore() + ", got: " + input.getContent().size());
+        }
+        if (visitor.getAmountAfter() != output.getContent().size()) {
+            throw new AssertionError("Number of added resources. Expected: " +
+                    visitor.getAmountAfter() + ", got: " + output.getContent().size());
+        }
+        for (ModuleData outFile : output.getContent()) {
+            String path = outFile.getPath().replaceAll(SUFFIX + "$", "");
+            ModuleData inFile = input.get(path);
+            if (inFile == null) {
+                throw new AssertionError("Unknown resource: " + path);
+            }
+        }
+    }
+
+    private static class ResourceVisitor implements Visitor {
+
+        private int amountBefore;
+        private int amountAfter;
+
+        @Override
+        public ModuleData visit(ModuleData file) {
+            int index = ++amountBefore % 3;
+            switch (index) {
+                case 0:
+                    ++amountAfter;
+                    return new InMemoryImageFile(file.getModule(), file.getPath() + SUFFIX,
+                            file.getType(), file.getPath());
+                case 1:
+                    ++amountAfter;
+                    return new InMemoryImageFile(file.getModule(), file.getPath(),
+                            file.getType(), file.getPath());
+            }
+            return null;
+        }
+
+        public int getAmountAfter() {
+            return amountAfter;
+        }
+
+        public int getAmountBefore() {
+            return amountBefore;
+        }
+    }
+
+    private void checkNegative() throws Exception {
+        PoolImpl input = new PoolImpl();
+        try {
+            input.add(null);
+            throw new AssertionError("NullPointerException is not thrown");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            input.contains(null);
+            throw new AssertionError("NullPointerException is not thrown");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        if (input.get("unknown") != null) {
+            throw new AssertionError("ImageFilePool does not return null for unknown file");
+        }
+        if (input.contains(new InMemoryImageFile("", "unknown", ModuleDataType.CONFIG, "unknown"))) {
+            throw new AssertionError("'contain' returns true for unknown file");
+        }
+        input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, ""));
+        try {
+            input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleDataType.CONFIG, ""));
+            throw new AssertionError("Exception expected");
+        } catch (Exception e) {
+            // expected
+        }
+        input.setReadOnly();
+        try {
+            input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleDataType.CONFIG, ""));
+            throw new AssertionError("Exception expected");
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    private static class InMemoryImageFile extends ModuleData {
+        public InMemoryImageFile(String module, String path, ModuleDataType type, String content) {
+            super(module, path, type, new ByteArrayInputStream(content.getBytes()), content.getBytes().length);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java
new file mode 100644
index 0000000..05c6120
--- /dev/null
+++ b/jdk/test/tools/jlink/IntegrationTest.java
@@ -0,0 +1,376 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+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.Set;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.Jlink.JlinkConfiguration;
+import jdk.tools.jlink.Jlink.PluginsConfiguration;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
+import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+import jdk.tools.jlink.plugin.Plugin;
+
+import tests.Helper;
+import tests.JImageGenerator;
+
+/*
+ * @test
+ * @summary Test integration API
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main IntegrationTest
+ */
+public class IntegrationTest {
+
+    private static final List<Integer> ordered = new ArrayList<>();
+
+    public static class MyPostProcessor implements PostProcessorPlugin {
+
+        public static final String NAME = "mypostprocessor";
+
+        @Override
+        public List<String> process(ExecutableImage image) {
+            try {
+                Files.createFile(image.getHome().resolve("toto.txt"));
+                return null;
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.PROCESSOR);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public void configure(Map<String, String> config) {
+            throw new UnsupportedOperationException("Shouldn't be called");
+        }
+    }
+
+    public static class MyPlugin1 implements TransformerPlugin {
+
+        Integer index;
+        Set<String> after;
+        Set<String> before;
+
+        private MyPlugin1(Integer index, Set<String> after, Set<String> before) {
+            this.index = index;
+            this.after = after;
+            this.before = before;
+        }
+
+        @Override
+        public Set<String> isAfter() {
+            return after;
+        }
+
+        @Override
+        public Set<String> isBefore() {
+            return before;
+        }
+
+        @Override
+        public String getName() {
+            return NAME + index;
+        }
+
+        @Override
+        public void visit(Pool in, Pool out) {
+            System.err.println(NAME + index);
+            ordered.add(index);
+            in.visit((file) -> {
+                return file;
+            }, out);
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public String getDescription() {
+            return null;
+        }
+
+        @Override
+        public String getOption() {
+            return null;
+        }
+        static final String NAME = "myprovider";
+        static final String INDEX = "INDEX";
+
+        @Override
+        public void configure(Map<String, String> config) {
+            throw new UnsupportedOperationException("Shouldn't be called");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        apitest();
+        test();
+        testOrder();
+        testCycleOrder();
+    }
+
+    private static void apitest() throws Exception {
+        boolean failed = false;
+        Jlink jl = new Jlink();
+
+        try {
+            jl.build(null);
+            failed = true;
+        } catch (Exception ex) {
+            // XXX OK
+        }
+        if (failed) {
+            throw new Exception("Should have failed");
+        }
+        System.out.println(jl);
+
+        JlinkConfiguration config
+                = new JlinkConfiguration(null, null, null, null);
+
+        System.out.println(config);
+
+        Plugin p = Jlink.newPlugin("toto", Collections.emptyMap(), null);
+        if (p != null) {
+            throw new Exception("Plugin should be null");
+        }
+
+        Plugin p2 = Jlink.newPlugin("compress", Collections.emptyMap(), null);
+        if (p2 == null) {
+            throw new Exception("Plugin should not be null");
+        }
+    }
+
+    private static void test() throws Exception {
+        Jlink jlink = new Jlink();
+        Path output = Paths.get("integrationout");
+        List<Path> modulePaths = new ArrayList<>();
+        File jmods
+                = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
+        modulePaths.add(jmods.toPath());
+        Set<String> mods = new HashSet<>();
+        mods.add("java.management");
+        Set<String> limits = new HashSet<>();
+        limits.add("java.management");
+        JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
+                modulePaths, mods, limits, null);
+
+        List<Plugin> lst = new ArrayList<>();
+
+        //Strip debug
+        {
+            Map<String, String> config1 = new HashMap<>();
+            config1.put(StripDebugPlugin.NAME, "");
+            Plugin strip = Jlink.newPlugin("strip-debug", config1, null);
+            lst.add(strip);
+        }
+        // compress
+        {
+            Map<String, String> config1 = new HashMap<>();
+            config1.put(DefaultCompressPlugin.NAME, "2");
+            Plugin compress
+                    = Jlink.newPlugin("compress", config1, null);
+            lst.add(compress);
+        }
+        // Post processor
+        {
+            lst.add(new MyPostProcessor());
+        }
+        // Image builder
+        DefaultImageBuilder builder = new DefaultImageBuilder(true, output);
+        PluginsConfiguration plugins
+                = new Jlink.PluginsConfiguration(lst, builder, null);
+
+        jlink.build(config, plugins);
+
+        if (!Files.exists(output)) {
+            throw new AssertionError("Directory not created");
+        }
+        File jimage = new File(output.toString(), "lib" + File.separator + "modules");
+        if (!jimage.exists()) {
+            throw new AssertionError("jimage not generated");
+        }
+        File bom = new File(output.toString(), "bom");
+        if (!bom.exists()) {
+            throw new AssertionError("bom not generated");
+        }
+        File release = new File(output.toString(), "release");
+        if (!release.exists()) {
+            throw new AssertionError("release not generated");
+        }
+
+        if (!Files.exists(output.resolve("toto.txt"))) {
+            throw new AssertionError("Post processing not called");
+        }
+
+    }
+
+    private static void testOrder() throws Exception {
+        Jlink jlink = new Jlink();
+        Path output = Paths.get("integrationout2");
+        List<Path> modulePaths = new ArrayList<>();
+        File jmods
+                = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
+        modulePaths.add(jmods.toPath());
+        Set<String> mods = new HashSet<>();
+        mods.add("java.management");
+        Set<String> limits = new HashSet<>();
+        limits.add("java.management");
+        JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
+                modulePaths, mods, limits, null);
+
+        List<Plugin> lst = new ArrayList<>();
+
+        // Order is Plug1>Plug2>Plug3
+        // Plug1
+
+
+        // TRANSFORMER 3, must be after 2.
+        {
+            Set<String> after = new HashSet<>();
+            after.add(MyPlugin1.NAME+"2");
+            lst.add(new MyPlugin1(3, after, Collections.emptySet()));
+        }
+
+        // TRANSFORMER 2, must be after 1.
+        {
+            Set<String> after = new HashSet<>();
+            after.add(MyPlugin1.NAME+"1");
+            lst.add(new MyPlugin1(2, after, Collections.emptySet()));
+        }
+
+        // TRANSFORMER 1
+        {
+            Set<String> before = new HashSet<>();
+            before.add(MyPlugin1.NAME+"2");
+            lst.add(new MyPlugin1(1, Collections.emptySet(), before));
+        }
+
+        // Image builder
+        DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
+        PluginsConfiguration plugins
+                = new Jlink.PluginsConfiguration(lst, builder, null);
+
+        jlink.build(config, plugins);
+
+        if (ordered.isEmpty()) {
+            throw new AssertionError("Plugins not called");
+        }
+        List<Integer> clone = new ArrayList<>();
+        clone.addAll(ordered);
+        Collections.sort(clone);
+        if (!clone.equals(ordered)) {
+            throw new AssertionError("Ordered is not properly sorted" + ordered);
+        }
+    }
+
+    private static void testCycleOrder() throws Exception {
+        Jlink jlink = new Jlink();
+        Path output = Paths.get("integrationout3");
+        List<Path> modulePaths = new ArrayList<>();
+        File jmods
+                = JImageGenerator.getJModsDir(new File(System.getProperty("test.jdk")));
+        modulePaths.add(jmods.toPath());
+        Set<String> mods = new HashSet<>();
+        mods.add("java.management");
+        Set<String> limits = new HashSet<>();
+        limits.add("java.management");
+        JlinkConfiguration config = new Jlink.JlinkConfiguration(output,
+                modulePaths, mods, limits, null);
+
+        List<Plugin> lst = new ArrayList<>();
+
+        // packager 1
+        {
+            Set<String> before = new HashSet<>();
+            before.add(MyPlugin1.NAME+"2");
+            lst.add(new MyPlugin1(1, Collections.emptySet(), before));
+        }
+
+        // packager 2
+        {
+            Set<String> before = new HashSet<>();
+            before.add(MyPlugin1.NAME+"1");
+            lst.add(new MyPlugin1(2, Collections.emptySet(), before));
+        }
+
+        // Image builder
+        DefaultImageBuilder builder = new DefaultImageBuilder(false, output);
+        PluginsConfiguration plugins
+                = new Jlink.PluginsConfiguration(lst, builder, null);
+        boolean failed = false;
+        try {
+            jlink.build(config, plugins);
+            failed = true;
+        } catch (Exception ex) {
+            // XXX OK
+        }
+        if (failed) {
+            throw new AssertionError("Should have failed");
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/JLink2Test.java b/jdk/test/tools/jlink/JLink2Test.java
new file mode 100644
index 0000000..4e08a81
--- /dev/null
+++ b/jdk/test/tools/jlink/JLink2Test.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Test image creation
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm -verbose:gc -Xmx1g JLink2Test
+ */
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Layer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.plugin.Plugin;
+
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.JImageValidator;
+
+public class JLink2Test {
+
+    public static void main(String[] args) throws Exception {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+
+        // This test case must be first one, the JlinkTask is clean
+        // and reveals possible bug related to plugin options in defaults
+        // e. g.: --genbom
+        testBomFile(helper);
+        testSameNames(helper);
+        testModulePath(helper);
+        testOptions();
+    }
+
+    private static void testModulePath(Helper helper) throws IOException {
+        Path doesNotExist = helper.createNewImageDir("doesnotexist");
+        Path jar = helper.getJarDir().resolve("bad.jar");
+        JImageGenerator.getJLinkTask()
+                .pluginModulePath(doesNotExist)
+                .option("--help")
+                .call().assertSuccess();
+        Files.createFile(jar);
+        JImageGenerator.getJLinkTask()
+                .pluginModulePath(jar)
+                .option("--help")
+                .call().assertFailure("(\n|\r|.)*Error: Invalid modules in the plugins path: (\n|\r|.)*");
+        JImageGenerator.getJLinkTask()
+                .pluginModulePath(jar.getParent())
+                .option("--help")
+                .call().assertFailure("Error: Invalid modules in the plugins path: .*zip file is empty(\n|\r|.)*");
+        try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jar.toFile()))) {
+            JarEntry entry = new JarEntry("class");
+            out.putNextEntry(entry);
+            out.write("AAAA".getBytes());
+            out.closeEntry();
+        }
+        JImageGenerator.getJLinkTask()
+                .pluginModulePath(jar.getParent())
+                .output(helper.createNewImageDir("crash"))
+                .addJmods(helper.getStdJmodsDir())
+                .addJmods(jar.getParent())
+                .addMods("bad")
+                .call().assertFailure("(\n|\r|.)*Error: jdk.tools.jlink.plugin.PluginException: module-info.class not found for bad module(\n|\r|.)*");
+        try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jar.toFile()))) {
+            JarEntry entry = new JarEntry("classes");
+            out.putNextEntry(entry);
+            out.closeEntry();
+
+            entry = new JarEntry("classes/class");
+            out.putNextEntry(entry);
+            out.write("AAAA".getBytes());
+            out.closeEntry();
+        }
+        JImageGenerator.getJLinkTask()
+                .pluginModulePath(jar.getParent())
+                .output(helper.createNewImageDir("bad"))
+                .addJmods(jar.getParent())
+                .addJars(helper.getStdJmodsDir())
+                .addMods("bad")
+                .call().assertFailure("(\n|\r|.)*Error: jdk.tools.jlink.plugin.PluginException: module-info.class not found for bad module(\n|\r|.)*");
+    }
+
+    private static void testSameNames(Helper helper) throws Exception {
+        // Multiple modules with the same name in modulepath, take the first one in the path.
+        // First jmods then jars. So jmods are found, jars are hidden.
+        String[] jarClasses = {"amodule.jar.Main"};
+        String[] jmodsClasses = {"amodule.jmods.Main"};
+        helper.generateDefaultJarModule("amodule", Arrays.asList(jarClasses));
+        helper.generateDefaultJModule("amodule", Arrays.asList(jmodsClasses));
+        List<String> okLocations = new ArrayList<>();
+        okLocations.addAll(Helper.toLocation("amodule", Arrays.asList(jmodsClasses)));
+        Path image = helper.generateDefaultImage(new String[0], "amodule").assertSuccess();
+        JImageValidator validator = new JImageValidator("amodule", okLocations,
+                image.toFile(), Collections.emptyList(), Collections.emptyList());
+        validator.validate();
+    }
+
+    private static void testBomFile(Helper helper) throws Exception {
+        String[] userOptions = {
+            "--compress",
+            "2",
+            "--addmods",
+            "bomzip",
+            "--strip-debug",
+            "--genbom",
+            "--exclude-resources",
+            "*.jcov,*/META-INF/*"};
+        String moduleName = "bomzip";
+        helper.generateDefaultJModule(moduleName, "composite2");
+        Path imgDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+        helper.checkImage(imgDir, moduleName, userOptions, null, null);
+        File bom = new File(imgDir.toFile(), "bom");
+        if (!bom.exists()) {
+            throw new RuntimeException(bom.getAbsolutePath() + " not generated");
+        }
+        String bomcontent = new String(Files.readAllBytes(bom.toPath()));
+        if (!bomcontent.contains("--strip-debug")
+                || !bomcontent.contains("--compress")
+                || !bomcontent.contains("--genbom")
+                || !bomcontent.contains("--exclude-resources *.jcov,"
+                        + "*/META-INF/*")
+                || !bomcontent.contains("--addmods bomzip")) {
+            throw new Exception("Not expected content in " + bom);
+        }
+    }
+
+    private static void testOptions() throws Exception {
+        List<Plugin> builtInPlugins = new ArrayList<>();
+        builtInPlugins.addAll(PluginRepository.getPlugins(Layer.boot()));
+        if(builtInPlugins.isEmpty()) {
+            throw new Exception("No builtin plugins");
+        }
+        List<String> options = new ArrayList<>();
+        for (Plugin p : builtInPlugins) {
+            if (p.getOption() == null) {
+                throw new Exception("Null option for " + p.getName());
+            }
+            if (options.contains(p.getName())) {
+                throw new Exception("Option " + p.getOption() + " used more than once");
+            }
+            options.add(p.getName());
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/JLinkNegativeTest.java b/jdk/test/tools/jlink/JLinkNegativeTest.java
new file mode 100644
index 0000000..4a1dcf1
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkNegativeTest.java
@@ -0,0 +1,355 @@
+/**
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Negative tests for jlink
+ * @bug 8130861
+ * @author Andrei Eremeev
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          java.base/jdk.internal.module
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run testng JLinkNegativeTest
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.module.ModuleDescriptor;
+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.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.internal.module.ModuleInfoWriter;
+import org.testng.SkipException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.JImageGenerator.InMemoryFile;
+import tests.Result;
+
+@Test
+public class JLinkNegativeTest {
+
+    private Helper helper;
+
+    @BeforeClass
+    public void setUp() throws IOException {
+        helper = Helper.newHelper();
+        if (helper == null) {
+            throw new SkipException("Not run");
+        }
+        helper.generateDefaultModules();
+    }
+
+    private void deleteDirectory(Path dir) throws IOException {
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                Files.delete(dir);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    public void testModuleNotExist() {
+        helper.generateDefaultImage("failure1").assertFailure("Error: Module failure1 not found");
+    }
+
+    public void testNotExistInAddMods() {
+        // cannot find jmod from --addmods
+        JImageGenerator.getJLinkTask()
+                .modulePath(".")
+                .addMods("not_exist")
+                .output(helper.getImageDir().resolve("failure2"))
+                .call().assertFailure("Error: Module not_exist not found");
+    }
+
+    public void test() throws IOException {
+        helper.generateDefaultJModule("failure3");
+        Path image = helper.generateDefaultImage("failure3").assertSuccess();
+        JImageGenerator.getJLinkTask()
+                .modulePath(helper.defaultModulePath())
+                .output(image)
+                .addMods("leaf1")
+                .limitMods("leaf1")
+                .call().assertFailure("Error: directory already exists: .*failure3.image(\n|\r|.)*");
+    }
+
+    public void testOutputIsFile() throws IOException {
+        // output == file
+        Path image = helper.createNewImageDir("failure4");
+        Files.createFile(image);
+        JImageGenerator.getJLinkTask()
+                .modulePath(helper.defaultModulePath())
+                .output(image)
+                .addMods("leaf1")
+                .call().assertFailure("Error: directory already exists: .*failure4.image(\n|\r|.)*");
+    }
+
+    public void testModuleNotFound() {
+        // limit module is not found
+        Path imageFile = helper.createNewImageDir("test");
+        JImageGenerator.getJLinkTask()
+                .output(imageFile)
+                .addMods("leaf1")
+                .limitMods("leaf1")
+                .limitMods("failure5")
+                .modulePath(helper.defaultModulePath())
+                .call().assertFailure("Error: Module failure5 not found");
+    }
+
+    public void testJmodIsDir() throws IOException {
+        Path imageFile = helper.createNewImageDir("test");
+        Path dirJmod = helper.createNewJmodFile("dir");
+        Files.createDirectory(dirJmod);
+        try {
+            JImageGenerator.getJLinkTask()
+                    .output(imageFile)
+                    .addMods("dir")
+                    .modulePath(helper.defaultModulePath())
+                    .call().assertFailure("Error: Module dir not found");
+        } finally {
+            deleteDirectory(dirJmod);
+        }
+    }
+
+    public void testJarIsDir() throws IOException {
+        Path imageFile = helper.createNewImageDir("test");
+        Path dirJar = helper.createNewJarFile("dir");
+        Files.createDirectory(dirJar);
+        try {
+            JImageGenerator.getJLinkTask()
+                    .output(imageFile)
+                    .addMods("dir")
+                    .modulePath(helper.defaultModulePath())
+                    .call().assertFailure("Error: Module dir not found");
+        } finally {
+            deleteDirectory(dirJar);
+        }
+    }
+
+    public void testMalformedJar() throws IOException {
+        Path imageFile = helper.createNewImageDir("test");
+        Path jar = helper.createNewJarFile("not_zip");
+        Files.createFile(jar);
+        try {
+            JImageGenerator.getJLinkTask()
+                    .output(imageFile)
+                    .addMods("not_zip")
+                    .modulePath(helper.defaultModulePath())
+                    .call().assertFailure("Error: java.util.zip.ZipException: zip file is empty");
+        } finally {
+            deleteDirectory(jar);
+        }
+    }
+
+    public void testMalformedJmod() throws IOException {
+        Path imageFile = helper.createNewImageDir("test");
+        Path jmod = helper.createNewJmodFile("not_zip");
+        Files.createFile(jmod);
+        try {
+            JImageGenerator.getJLinkTask()
+                    .output(imageFile)
+                    .addMods("not_zip")
+                    .modulePath(helper.defaultModulePath())
+                    .call().assertFailure("Error: java.util.zip.ZipException: zip file is empty");
+        } finally {
+            deleteDirectory(jmod);
+        }
+    }
+
+    // Temporarily exclude; the jmod tool can no longer be used to create a jmod
+    // with a class in the unnamed package. Find another way, or remove.
+//    public void testAddDefaultPackage() throws IOException {
+//        String moduleName = "hacked1";
+//        Path module = helper.generateModuleCompiledClasses(helper.getJmodSrcDir(), helper.getJmodClassesDir(),
+//                moduleName, Arrays.asList("hacked1.Main", "A", "B"), "leaf1");
+//        JImageGenerator
+//                .getJModTask()
+//                .addClassPath(module)
+//                .jmod(helper.getJmodDir().resolve(moduleName + ".jmod"))
+//                .create().assertSuccess();
+//        Path image = helper.generateDefaultImage(moduleName).assertSuccess();
+//        helper.checkImage(image, moduleName, null, null);
+//    }
+
+    public void testAddSomeTopLevelFiles() throws IOException {
+        String moduleName = "hacked2";
+        Path module = helper.generateModuleCompiledClasses(helper.getJmodSrcDir(), helper.getJmodClassesDir(),
+                moduleName);
+        Files.createFile(module.resolve("top-level-file"));
+        Path jmod = JImageGenerator
+                .getJModTask()
+                .addClassPath(module)
+                .jmod(helper.getJmodDir().resolve(moduleName + ".jmod"))
+                .create().assertSuccess();
+        try {
+            Path image = helper.generateDefaultImage(moduleName).assertSuccess();
+            helper.checkImage(image, moduleName, null, null);
+        } finally {
+            deleteDirectory(jmod);
+        }
+    }
+
+    public void testAddNonStandardSection() throws IOException {
+        String moduleName = "hacked3";
+        Path module = helper.generateDefaultJModule(moduleName).assertSuccess();
+        JImageGenerator.addFiles(module, new InMemoryFile("unknown/A.class", new byte[0]));
+        try {
+            Result result = helper.generateDefaultImage(moduleName);
+            if (result.getExitCode() != 4) {
+                throw new AssertionError("Crash expected");
+            }
+            if (!result.getMessage().contains("java.lang.InternalError: unexpected entry: unknown")) {
+                System.err.println(result.getMessage());
+                throw new AssertionError("InternalError expected");
+            }
+        } finally {
+            deleteDirectory(module);
+        }
+    }
+
+    @Test(enabled = true)
+    public void testSectionsAreFiles() throws IOException {
+        String moduleName = "module";
+        Path jmod = helper.generateDefaultJModule(moduleName).assertSuccess();
+        JImageGenerator.addFiles(jmod,
+                new InMemoryFile("/native", new byte[0]),
+                new InMemoryFile("/conf", new byte[0]),
+                new InMemoryFile("/bin", new byte[0]));
+        try {
+            Result result = helper.generateDefaultImage(moduleName);
+            if (result.getExitCode() != 4) {
+                throw new AssertionError("Crash expected");
+            }
+            if (!result.getMessage().contains("java.lang.InternalError: unexpected entry: ")) {
+                System.err.println(result.getMessage());
+                throw new AssertionError("InternalError expected");
+            }
+        } finally {
+            deleteDirectory(jmod);
+        }
+    }
+
+    public void testDuplicateModule1() throws IOException {
+        String moduleName1 = "dupRes1Jmod1";
+        String moduleName2 = "dupRes1Jmod2";
+        List<String> classNames = Arrays.asList("java.A", "javax.B");
+        Path module1 = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName1, classNames);
+        Path module2 = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName2, classNames);
+
+        try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) {
+            ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1)
+                    .requires("java.base").build(), out);
+        }
+
+        Path jmod1 = JImageGenerator.getJModTask()
+                .addClassPath(module1)
+                .jmod(helper.createNewJmodFile(moduleName1))
+                .create()
+                .assertSuccess();
+        Path jmod2 = JImageGenerator.getJModTask()
+                .addClassPath(module2)
+                .jmod(helper.createNewJmodFile(moduleName2))
+                .create()
+                .assertSuccess();
+        try {
+            helper.generateDefaultImage(moduleName1)
+                    .assertFailure("Error: Two versions of module dupRes1Jmod1 found in");
+        } finally {
+            deleteDirectory(jmod1);
+            deleteDirectory(jmod2);
+        }
+    }
+
+    public void testDuplicateModule2() throws IOException {
+        String moduleName = "dupRes2Jmod";
+        List<String> classNames = Arrays.asList("java.A", "javax.B");
+        Path module1 = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName, classNames);
+        Path module2 = helper.generateModuleCompiledClasses(
+                helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName, classNames);
+
+        Path jmod = JImageGenerator.getJModTask()
+                .addClassPath(module1)
+                .jmod(helper.createNewJmodFile(moduleName))
+                .create()
+                .assertSuccess();
+        Path jar = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName + ".jar"), module2);
+        Path newJar = helper.getJmodDir().resolve(jar.getFileName());
+        Files.move(jar, newJar);
+        try {
+            helper.generateDefaultImage(moduleName)
+                    .assertFailure("Error: Two versions of module dupRes2Jmod found in");
+        } finally {
+            deleteDirectory(jmod);
+            deleteDirectory(newJar);
+        }
+    }
+
+    public void testDuplicateModule3() throws IOException {
+        String moduleName1 = "dupRes3Jar1";
+        String moduleName2 = "dupRes3Jar2";
+        List<String> classNames = Arrays.asList("java.A", "javax.B");
+        Path module1 = helper.generateModuleCompiledClasses(
+                helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName1, classNames);
+        Path module2 = helper.generateModuleCompiledClasses(
+                helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName2, classNames);
+
+        try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) {
+            ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1)
+                    .requires("java.base").build(), out);
+        }
+
+        Path jar1 = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName1 + ".jar"), module1);
+        Path jar2 = JImageGenerator.createJarFile(helper.getJarDir().resolve(moduleName2 + ".jar"), module2);
+        try {
+            helper.generateDefaultImage(moduleName1)
+                    .assertFailure("Error: Two versions of module dupRes3Jar1 found in");
+        } finally {
+            deleteDirectory(jar1);
+            deleteDirectory(jar2);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/JLinkOptimTest.java b/jdk/test/tools/jlink/JLinkOptimTest.java
new file mode 100644
index 0000000..82c5431
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkOptimTest.java
@@ -0,0 +1,374 @@
+
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+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.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.plugins.OptimizationPlugin;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.internal.plugins.optim.ControlFlow;
+import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+import tests.Helper;
+import tests.JImageGenerator;
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Test image creation with class optimization
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.optim
+ *          java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.org.objectweb.asm.tree
+ *          java.base/jdk.internal.org.objectweb.asm.util
+ *          jdk.compiler
+ * @build tests.*
+ * @run main JLinkOptimTest
+ */
+public class JLinkOptimTest {
+
+    private static final String EXPECTED = "expected";
+    private static Helper helper;
+
+    public static class ControlFlowPlugin extends AsmPlugin {
+
+        private boolean called;
+        private int numMethods;
+        private int numBlocks;
+
+        private static final String NAME = "test-optim";
+
+        private ControlFlowPlugin() {
+        }
+
+        @Override
+        public void visit(AsmPools pools) {
+            called = true;
+            for (AsmModulePool p : pools.getModulePools()) {
+
+                p.visitClassReaders((reader) -> {
+                    ClassNode cn = new ClassNode();
+                    if ((reader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
+                        reader.accept(cn, ClassReader.EXPAND_FRAMES);
+                        for (MethodNode m : cn.methods) {
+                            if ((m.access & Opcodes.ACC_ABSTRACT) == 0
+                                    && (m.access & Opcodes.ACC_NATIVE) == 0) {
+                                numMethods += 1;
+                                try {
+                                    ControlFlow f
+                                            = ControlFlow.createControlFlow(cn.name, m);
+                                    for (Block b : f.getBlocks()) {
+                                        numBlocks += 1;
+                                        f.getClosure(b);
+                                    }
+                                } catch (Throwable ex) {
+                                    //ex.printStackTrace();
+                                    throw new RuntimeException("Exception in "
+                                            + cn.name + "." + m.name, ex);
+                                }
+                            }
+                        }
+                    }
+                    return null;
+                });
+            }
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    private static void testForName() throws Exception {
+        String moduleName = "optimplugin";
+        Path src = Paths.get(System.getProperty("test.src")).resolve(moduleName);
+        Path classes = helper.getJmodClassesDir().resolve(moduleName);
+        JImageGenerator.compile(src, classes);
+
+        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        Path root = fs.getPath("/modules/java.base");
+        // Access module-info.class to be reused as fake module-info.class
+        List<ModuleData> javabaseResources = new ArrayList<>();
+        try (Stream<Path> stream = Files.walk(root)) {
+            for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
+                Path p = iterator.next();
+                if (Files.isRegularFile(p)) {
+                    try {
+                        javabaseResources.add(Pool.newResource(p.toString().
+                                substring("/modules".length()), Files.readAllBytes(p)));
+                    } catch (Exception ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        }
+
+        //forName folding
+        PoolImpl pool = new PoolImpl();
+        byte[] content = Files.readAllBytes(classes.
+                resolve("optim").resolve("ForNameTestCase.class"));
+        byte[] content2 = Files.readAllBytes(classes.
+                resolve("optim").resolve("AType.class"));
+        byte[] mcontent = Files.readAllBytes(classes.resolve("module-info.class"));
+
+        pool.add(Pool.newResource("/optimplugin/optim/ForNameTestCase.class", content));
+        pool.add(Pool.newResource("/optimplugin/optim/AType.class", content2));
+        pool.add(Pool.newResource("/optimplugin/module-info.class", mcontent));
+
+        for (ModuleData r : javabaseResources) {
+            pool.add(r);
+        }
+
+        OptimizationPlugin plugin = new OptimizationPlugin();
+        Map<String, String> optional = new HashMap<>();
+        optional.put(OptimizationPlugin.NAME, OptimizationPlugin.FORNAME_REMOVAL);
+        optional.put(OptimizationPlugin.LOG, "forName.log");
+        plugin.configure(optional);
+        Pool out = new PoolImpl();
+        plugin.visit(pool, out);
+
+        ModuleData result = out.getContent().iterator().next();
+
+        ClassReader optimReader = new ClassReader(result.getBytes());
+        ClassNode optimClass = new ClassNode();
+        optimReader.accept(optimClass, ClassReader.EXPAND_FRAMES);
+
+        if (!optimClass.name.equals("optim/ForNameTestCase")) {
+            throw new Exception("Invalid class " + optimClass.name);
+        }
+        if (optimClass.methods.size() < 2) {
+            throw new Exception("Not enough methods in new class");
+        }
+        for (MethodNode mn : optimClass.methods) {
+            if (!mn.name.contains("forName") && !mn.name.contains("<clinit>")) {
+                continue;
+            }
+            if (mn.name.startsWith("negative")) {
+                checkForName(mn);
+            } else {
+                checkNoForName(mn);
+            }
+        }
+        Map<String, byte[]> newClasses = new HashMap<>();
+        newClasses.put("optim.ForNameTestCase", result.getBytes());
+        newClasses.put("optim.AType", content2);
+        MemClassLoader loader = new MemClassLoader(newClasses);
+        Class<?> loaded = loader.loadClass("optim.ForNameTestCase");
+        if (loaded.getDeclaredMethods().length < 2) {
+            throw new Exception("Not enough methods in new class");
+        }
+        for (Method m : loaded.getDeclaredMethods()) {
+            if (m.getName().contains("Exception")) {
+                try {
+                    m.invoke(null);
+                } catch (Exception ex) {
+                    //ex.getCause().printStackTrace();
+                    if (!ex.getCause().getMessage().equals(EXPECTED)) {
+                        throw new Exception("Unexpected exception " + ex);
+                    }
+                }
+            } else if (!m.getName().startsWith("negative")) {
+                Class<?> clazz = (Class<?>) m.invoke(null);
+                if (clazz != String.class && clazz != loader.findClass("optim.AType")) {
+                    throw new Exception("Invalid class " + clazz);
+                }
+            }
+        }
+    }
+
+    private static void checkNoForName(MethodNode m) throws Exception {
+        Iterator<AbstractInsnNode> it = m.instructions.iterator();
+        while (it.hasNext()) {
+            AbstractInsnNode n = it.next();
+            if (n instanceof MethodInsnNode) {
+                MethodInsnNode met = (MethodInsnNode) n;
+                if (met.name.equals("forName")
+                        && met.owner.equals("java/lang/Class")
+                        && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+                    throw new Exception("forName not removed in " + m.name);
+                }
+            }
+        }
+        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
+            if (tcb.type.equals(ClassNotFoundException.class.getName().replaceAll("\\.", "/"))) {
+                throw new Exception("ClassNotFoundException Block not removed for " + m.name);
+            }
+        }
+    }
+
+    private static void checkForName(MethodNode m) throws Exception {
+        Iterator<AbstractInsnNode> it = m.instructions.iterator();
+        boolean found = false;
+        while (it.hasNext()) {
+            AbstractInsnNode n = it.next();
+            if (n instanceof MethodInsnNode) {
+                MethodInsnNode met = (MethodInsnNode) n;
+                if (met.name.equals("forName")
+                        && met.owner.equals("java/lang/Class")
+                        && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+        if (!found) {
+            throw new Exception("forName removed but shouldn't have");
+        }
+        found = false;
+        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
+            if (tcb.type.equals(ClassNotFoundException.class.getName().replaceAll("\\.", "/"))) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            throw new Exception("tryCatchBlocks removed but shouldn't have");
+        }
+    }
+
+    static class MemClassLoader extends ClassLoader {
+
+        private final Map<String, byte[]> classes;
+        private final Map<String, Class<?>> cache = new HashMap<>();
+
+        MemClassLoader(Map<String, byte[]> classes) {
+            super(null);
+            this.classes = classes;
+        }
+
+        @Override
+        public Class findClass(String name) throws ClassNotFoundException {
+            Class<?> clazz = cache.get(name);
+            if (clazz == null) {
+                byte[] b = classes.get(name);
+                if (b == null) {
+                    return super.findClass(name);
+                } else {
+                    clazz = defineClass(name, b, 0, b.length);
+                    cache.put(name, clazz);
+                }
+            }
+            return clazz;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+
+        testForName();
+
+        helper.generateDefaultModules();
+        helper.generateDefaultJModule("optim1", "java.se");
+        {
+            String[] userOptions = {"--class-optim=all:log=./class-optim-log.txt"};
+
+            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
+            helper.checkImage(imageDir, "optim1", null, null);
+        }
+
+        /*{
+         Path dir = Paths.get("dir.log");
+         Files.createDirectory(dir);
+         String[] userOptions = {"--class-optim=all:log=" + dir.toString()};
+         helper.generateDefaultImage(userOptions, "optim1")
+         .assertFailure("java.io.FileNotFoundException: dir.log (Is a directory)");
+         }*/
+ /*{
+         String[] userOptions = {"--class-optim", "UNKNOWN"};
+         helper.generateDefaultImage(userOptions, "optim1").assertFailure("Unknown optimization");
+         }*/
+        {
+            String[] userOptions = {"--class-optim=forName-folding:log=./class-optim-log.txt"};
+            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
+            helper.checkImage(imageDir, "optim1", null, null);
+        }
+
+        {
+            ControlFlowPlugin plugin = new ControlFlowPlugin();
+            PluginRepository.registerPlugin(plugin);
+            String[] userOptions = {"--test-optim"};
+            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
+            helper.checkImage(imageDir, "optim1", null, null);
+            //System.out.println("Num methods analyzed " + provider.numMethods
+            //        + "num blocks " + provider.numBlocks);
+            if (!plugin.called) {
+                throw new Exception("Plugin not called");
+            }
+            if (plugin.numMethods < 1000) {
+                throw new Exception("Not enough method called,  should be "
+                        + "around 10000 but is " + plugin.numMethods);
+            }
+            if (plugin.numBlocks < 100000) {
+                throw new Exception("Not enough blocks,  should be "
+                        + "around 640000 but is " + plugin.numMethods);
+            }
+        }
+    }
+
+}
diff --git a/jdk/test/tools/jlink/JLinkOptionsTest.java b/jdk/test/tools/jlink/JLinkOptionsTest.java
new file mode 100644
index 0000000..8c8d241
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+import tests.Helper;
+
+/*
+ * @test
+ * @summary Test jlink options
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main JLinkOptionsTest
+ */
+public class JLinkOptionsTest {
+
+    private static class TestPlugin implements TransformerPlugin {
+        private final String name;
+        private final String option;
+
+        private TestPlugin(String name, String option) {
+            this.name = name;
+            this.option = option;
+        }
+
+
+        @Override
+        public String getOption() {
+            return option;
+        }
+
+        @Override
+        public void visit(Pool in, Pool out) {
+
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getDescription() {
+            return name;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+        {
+            // multiple plugins with same option
+
+            PluginRepository.
+                    registerPlugin(new TestPlugin("test1", "test1"));
+            PluginRepository.
+                    registerPlugin(new TestPlugin("test2", "test1"));
+            helper.generateDefaultImage("composite2").assertFailure("Error: More than one plugin enabled by test1 option");
+            PluginRepository.unregisterPlugin("test1");
+            PluginRepository.unregisterPlugin("test2");
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/JLinkPluginsTest.java b/jdk/test/tools/jlink/JLinkPluginsTest.java
new file mode 100644
index 0000000..560fc53
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkPluginsTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+
+import tests.Helper;
+
+/*
+ * @test
+ * @summary Test image creation
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm -verbose:gc -Xmx1g JLinkPluginsTest
+ */
+public class JLinkPluginsTest {
+
+    private static String createProperties(String fileName, String content) throws IOException {
+        Path p = Paths.get(fileName);
+        Files.write(p, Collections.singletonList(content));
+        return p.toAbsolutePath().toString();
+    }
+
+    public static void main(String[] args) throws Exception {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+        {
+            // Skip debug
+            String[] userOptions = {"--strip-debug"};
+            String moduleName = "skipdebugcomposite";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, null, null);
+        }
+        {
+            // Filter out files
+            String[] userOptions = {"--exclude-resources", "*.jcov, */META-INF/*"};
+            String moduleName = "excludecomposite";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            String[] res = {".jcov", "/META-INF/"};
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, res, null);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/JLinkPostProcessingTest.java b/jdk/test/tools/jlink/JLinkPostProcessingTest.java
new file mode 100644
index 0000000..b32bf20
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.plugin.ExecutableImage;
+import jdk.tools.jlink.plugin.PostProcessorPlugin;
+import tests.Helper;
+
+/*
+ * @test
+ * @summary Test post processing
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm JLinkPostProcessingTest
+ */
+public class JLinkPostProcessingTest {
+
+    private static class PPPlugin implements PostProcessorPlugin {
+
+        private static ExecutableImage called;
+        private static final String NAME = "pp";
+
+        @Override
+        public List<String> process(ExecutableImage image) {
+            called = image;
+            Path gen = image.getHome().resolve("lib").resolve("toto.txt");
+            try {
+                Files.createFile(gen);
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+            return null;
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.PROCESSOR);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public String getDescription() {
+            return NAME;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+
+        PluginRepository.registerPlugin(new PPPlugin());
+
+        // Generate an image and post-process in same jlink execution.
+        {
+            String[] userOptions = {"--pp"};
+            String moduleName = "postprocessing1";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            String[] res = {};
+            String[] files = {};
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, res, files);
+
+            test(imageDir);
+        }
+
+        // Generate an image, post-process in 2 jlink executions.
+        {
+            String[] userOptions = {};
+            String moduleName = "postprocessing2";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            String[] res = {};
+            String[] files = {};
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, res, files);
+
+            String[] ppOptions = {"--pp"};
+            helper.postProcessImage(imageDir, ppOptions);
+            test(imageDir);
+        }
+    }
+
+    private static void test(Path imageDir)
+            throws Exception {
+        if (PPPlugin.called == null) {
+            throw new Exception("Post processor not called.");
+        }
+        if (!PPPlugin.called.getHome().equals(imageDir)) {
+            throw new Exception("Not right imageDir " + PPPlugin.called.getHome());
+        }
+        if (PPPlugin.called.getExecutionArgs().isEmpty()) {
+            throw new Exception("No arguments to run java...");
+        }
+        Path gen = imageDir.resolve("lib").resolve("toto.txt");
+        if (!Files.exists(gen)) {
+            throw new Exception("Generated file doesn;t exist");
+        }
+        PPPlugin.called = null;
+    }
+}
diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java
new file mode 100644
index 0000000..180dc4c
--- /dev/null
+++ b/jdk/test/tools/jlink/JLinkTest.java
@@ -0,0 +1,229 @@
+/*
+ * 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.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Layer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.internal.PluginRepository;
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.JImageGenerator.InMemoryFile;
+
+/*
+ * @test
+ * @summary Test image creation
+ * @author Jean-Francois Denise
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm -verbose:gc -Xmx1g JLinkTest
+ */
+public class JLinkTest {
+
+    public static void main(String[] args) throws Exception {
+
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+        helper.generateDefaultModules();
+        int numPlugins = 12;
+        {
+            // number of built-in plugins
+            List<Plugin> builtInPlugins = new ArrayList<>();
+            builtInPlugins.addAll(PluginRepository.getPlugins(Layer.boot()));
+            for (Plugin p : builtInPlugins) {
+                p.getState();
+                p.getType();
+            }
+            if (builtInPlugins.size() != numPlugins) {
+                throw new AssertionError("Found plugins doesn't match expected number : " +
+                        numPlugins + "\n" + builtInPlugins);
+            }
+        }
+
+        {
+            String moduleName = "bug8134651";
+            JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .output(helper.createNewImageDir(moduleName))
+                    .addMods("leaf1")
+                    .option("")
+                    .call().assertSuccess();
+            JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .addMods("leaf1")
+                    .option("--output")
+                    .option("")
+                    .call().assertFailure("Error: no value given for --output");
+            JImageGenerator.getJLinkTask()
+                    .modulePath("")
+                    .output(helper.createNewImageDir(moduleName))
+                    .addMods("leaf1")
+                    .option("")
+                    .call().assertFailure("Error: no value given for --modulepath");
+        }
+
+        {
+            String moduleName = "filter";
+            Path jmod = helper.generateDefaultJModule(moduleName).assertSuccess();
+            String className = "_A.class";
+            JImageGenerator.addFiles(jmod, new InMemoryFile(className, new byte[0]));
+            Path image = helper.generateDefaultImage(moduleName).assertSuccess();
+            helper.checkImage(image, moduleName, new String[] {"/" + moduleName + "/" + className}, null);
+        }
+
+        {
+            // Help
+            StringWriter writer = new StringWriter();
+            jdk.tools.jlink.internal.Main.run(new String[]{"--help"}, new PrintWriter(writer));
+            String output = writer.toString();
+            if (output.split("\n").length < 10) {
+                System.err.println(output);
+                throw new AssertionError("Help");
+            }
+        }
+
+        {
+            // License files
+            String copied = "LICENSE";
+            String[] arr = copied.split(",");
+            String[] copyFiles = new String[2];
+            copyFiles[0] = "--copy-files";
+            copyFiles[1] = copied;
+            Path imageDir = helper.generateDefaultImage(copyFiles, "composite2").assertSuccess();
+            helper.checkImage(imageDir, "composite2", null, null, arr);
+        }
+
+        {
+            // List plugins
+            StringWriter writer = new StringWriter();
+            jdk.tools.jlink.internal.Main.run(new String[]{"--list-plugins"}, new PrintWriter(writer));
+            String output = writer.toString();
+            long number = Stream.of(output.split("\\R"))
+                    .filter((s) -> s.matches("Plugin Name:.*"))
+                    .count();
+            if (number != numPlugins) {
+                System.err.println(output);
+                throw new AssertionError("Found: " + number + " expected " + numPlugins);
+            }
+        }
+
+        // filter out files and resources + Skip debug + compress
+        {
+            String[] userOptions = {"--compress", "2", "--strip-debug",
+                "--exclude-resources", "*.jcov, */META-INF/*", "--exclude-files",
+                "*" + Helper.getDebugSymbolsExtension()};
+            String moduleName = "excludezipskipdebugcomposite2";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            String[] res = {".jcov", "/META-INF/"};
+            String[] files = {Helper.getDebugSymbolsExtension()};
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, res, files);
+        }
+
+        // filter out + Skip debug + compress with filter + sort resources
+        {
+            String[] userOptions2 = {"--compress=2:compress-filter=^/java.base/*",
+                "--strip-debug", "--exclude-resources",
+                "*.jcov, */META-INF/*", "--sort-resources",
+                "*/module-info.class,/sortcomposite2/*,*/javax/management/*"};
+            String moduleName = "excludezipfilterskipdebugcomposite2";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            String[] res = {".jcov", "/META-INF/"};
+            Path imageDir = helper.generateDefaultImage(userOptions2, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, res, null);
+        }
+
+        // default compress
+        {
+            testCompress(helper, "compresscmdcomposite2", "--compress", "2");
+        }
+
+        {
+            testCompress(helper, "compressfiltercmdcomposite2",
+                    "--compress=2:filter=^/java.base/java/lang/*");
+        }
+
+        // compress 0
+        {
+            testCompress(helper, "compress0filtercmdcomposite2",
+                    "--compress=0:filter=^/java.base/java/lang/*");
+        }
+
+        // compress 1
+        {
+            testCompress(helper, "compress1filtercmdcomposite2",
+                    "--compress=1:filter=^/java.base/java/lang/*");
+        }
+
+        // compress 2
+        {
+            testCompress(helper, "compress2filtercmdcomposite2",
+                    "--compress=2:filter=^/java.base/java/lang/*");
+        }
+
+        // invalid compress level
+        {
+            String[] userOptions = {"--compress", "invalid"};
+            String moduleName = "invalidCompressLevel";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid level invalid");
+        }
+
+        // @file
+        {
+            Path path = Paths.get("embedded.properties");
+            Files.write(path, Collections.singletonList("--strip-debug --addmods " +
+                    "toto.unknown --compress UNKNOWN\n"));
+            String[] userOptions = {"@", path.toAbsolutePath().toString()};
+            String moduleName = "configembeddednocompresscomposite2";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, null, null);
+        }
+
+    }
+
+    private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException {
+        helper.generateDefaultJModule(moduleName, "composite2");
+        Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+        helper.checkImage(imageDir, moduleName, null, null);
+    }
+}
diff --git a/jdk/test/tools/jlink/NativeTest.java b/jdk/test/tools/jlink/NativeTest.java
new file mode 100644
index 0000000..b147617
--- /dev/null
+++ b/jdk/test/tools/jlink/NativeTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test config, cmd and lib directories of jmod.
+ * @author Andrei Eremeev
+ * @library ../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main NativeTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+
+import tests.Helper;
+import tests.JImageGenerator;
+
+public class NativeTest {
+
+    private final Helper helper;
+
+    public NativeTest(Helper helper) {
+        this.helper = helper;
+    }
+
+    public static void main(String[] args) throws IOException {
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Not run");
+            return;
+        }
+        new NativeTest(helper).test();
+    }
+
+    public void test() throws IOException {
+        String moduleName = "native_library";
+        Path classesDir = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName);
+        Path libsDir = helper.getJmodDir().resolve("lib").resolve(moduleName);
+        Path configDir = helper.getJmodDir().resolve("config").resolve(moduleName);
+        Path cmdDir = helper.getJmodDir().resolve("cmd").resolve(moduleName);
+
+        Path config = writeFile(configDir.resolve("config.txt"), "AAAA\nBBBB");
+        Path cmd = writeFile(cmdDir.resolve("ls.sh"), "ls");
+        Path lib = writeFile(libsDir.resolve("native.so"), "native library");
+
+        JImageGenerator.getJModTask()
+                .addClassPath(classesDir)
+                .addNativeLibraries(libsDir)
+                .addCmds(cmdDir)
+                .addConfig(configDir)
+                .jmod(helper.createNewJmodFile(moduleName))
+                .create()
+                .assertSuccess();
+
+        String[] expectedFiles = new String[] {
+                "bin" + File.separator + cmd.getFileName(),
+                "conf" + File.separator + config.getFileName(),
+                "lib" + File.separator + lib.getFileName()
+        };
+        Path image = JImageGenerator.getJLinkTask()
+                .modulePath(helper.defaultModulePath())
+                .addMods(moduleName)
+                .output(helper.createNewImageDir(moduleName))
+                .call().assertSuccess();
+        helper.checkImage(image, moduleName, null, null, expectedFiles);
+    }
+
+    private Path writeFile(Path path, String content) throws IOException {
+        if (path.getParent() != null) {
+            Files.createDirectories(path.getParent());
+        }
+        Files.write(path, Arrays.asList(content.split("\n")));
+        return path;
+    }
+}
diff --git a/jdk/test/tools/jlink/ResourcePoolTest.java b/jdk/test/tools/jlink/ResourcePoolTest.java
new file mode 100644
index 0000000..77a82e5
--- /dev/null
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test a pool containing jimage resources and classes.
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ * @run build ResourcePoolTest
+ * @run main ResourcePoolTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.Module;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.Pool.Visitor;
+
+public class ResourcePoolTest {
+
+    public static void main(String[] args) throws Exception {
+        new ResourcePoolTest().test();
+    }
+
+    public void test() throws Exception {
+        checkResourceAdding();
+        checkResourceVisitor();
+        checkResourcesAfterCompression();
+    }
+
+    private static final String SUFFIX = "END";
+
+    private void checkResourceVisitor() throws Exception {
+        Pool input = new PoolImpl();
+        for (int i = 0; i < 1000; ++i) {
+            String module = "/module" + (i / 10);
+            String resourcePath = module + "/java/package" + i;
+            byte[] bytes = resourcePath.getBytes();
+            input.add(new ModuleData(module, resourcePath,
+                    ModuleDataType.CLASS_OR_RESOURCE,
+                    new ByteArrayInputStream(bytes), bytes.length));
+        }
+        Pool output = new PoolImpl();
+        ResourceVisitor visitor = new ResourceVisitor();
+        input.visit(visitor, output);
+        if (visitor.getAmountBefore() == 0) {
+            throw new AssertionError("Resources not found");
+        }
+        if (visitor.getAmountBefore() != input.getContent().size()) {
+            throw new AssertionError("Number of visited resources. Expected: " +
+                    visitor.getAmountBefore() + ", got: " + input.getContent().size());
+        }
+        if (visitor.getAmountAfter() != output.getContent().size()) {
+            throw new AssertionError("Number of added resources. Expected: " +
+                    visitor.getAmountAfter() + ", got: " + output.getContent().size());
+        }
+        for (ModuleData outResource : output.getContent()) {
+            String path = outResource.getPath().replaceAll(SUFFIX + "$", "");
+            ModuleData inResource = input.get(path);
+            if (inResource == null) {
+                throw new AssertionError("Unknown resource: " + path);
+            }
+        }
+    }
+
+    private static class ResourceVisitor implements Visitor {
+
+        private int amountBefore;
+        private int amountAfter;
+
+        @Override
+        public ModuleData visit(ModuleData resource) {
+            int index = ++amountBefore % 3;
+            switch (index) {
+                case 0:
+                    ++amountAfter;
+                    return new ModuleData(resource.getModule(), resource.getPath() + SUFFIX,
+                            resource.getType(), resource.stream(), resource.getLength());
+                case 1:
+                    ++amountAfter;
+                    return new ModuleData(resource.getModule(), resource.getPath(),
+                            resource.getType(), resource.stream(), resource.getLength());
+            }
+            return null;
+        }
+
+        public int getAmountAfter() {
+            return amountAfter;
+        }
+
+        public int getAmountBefore() {
+            return amountBefore;
+        }
+    }
+
+    private void checkResourceAdding() {
+        List<String> samples = new ArrayList<>();
+        samples.add("java.base");
+        samples.add("java/lang/Object");
+        samples.add("java.base");
+        samples.add("java/lang/String");
+        samples.add("java.management");
+        samples.add("javax/management/ObjectName");
+        test(samples, (resources, module, path) -> {
+            try {
+                resources.add(new ModuleData(module, path,
+                        ModuleDataType.CLASS_OR_RESOURCE,
+                        new ByteArrayInputStream(new byte[0]), 0));
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        });
+        test(samples, (resources, module, path) -> {
+            try {
+                resources.add(PoolImpl.
+                        newCompressedResource(new ModuleData(module, path,
+                                ModuleDataType.CLASS_OR_RESOURCE,
+                                new ByteArrayInputStream(new byte[0]), 0),
+                                ByteBuffer.allocate(99), "bitcruncher", null,
+                                ((PoolImpl)resources).getStringTable(), ByteOrder.nativeOrder()));
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        });
+    }
+
+    private void test(List<String> samples, ResourceAdder adder) {
+        if (samples.isEmpty()) {
+            throw new AssertionError("No sample to test");
+        }
+        Pool resources = new PoolImpl();
+        Set<String> modules = new HashSet<>();
+        for (int i = 0; i < samples.size(); i++) {
+            String module = samples.get(i);
+            modules.add(module);
+            i++;
+            String clazz = samples.get(i);
+            String path = "/" + module + "/" + clazz + ".class";
+            adder.add(resources, module, path);
+        }
+        for (int i = 0; i < samples.size(); i++) {
+            String module = samples.get(i);
+            i++;
+            String clazz = samples.get(i);
+            String path = "/" + module + "/" + clazz + ".class";
+            ModuleData res = resources.get(path);
+            checkModule(resources, res);
+            if (res == null) {
+                throw new AssertionError("Resource not found " + path);
+            }
+            ModuleData res2 = resources.get(clazz);
+            if (res2 != null) {
+                throw new AssertionError("Resource found " + clazz);
+            }
+        }
+        if (resources.getContent().size() != samples.size() / 2) {
+            throw new AssertionError("Invalid number of resources");
+        }
+    }
+
+    private void checkModule(Pool resources, ModuleData res) {
+        Module m = resources.getModule(res.getModule());
+        if (m == null) {
+            throw new AssertionError("No module " + res.getModule());
+        }
+        if (!m.getName().equals(res.getModule())) {
+            throw new AssertionError("Not right module name " + res.getModule());
+        }
+        if (m.get(res.getPath()) == null) {
+            throw new AssertionError("resource " + res.getPath()
+                    + " not in module " + m.getName());
+        }
+    }
+
+    private void checkResourcesAfterCompression() throws Exception {
+        PoolImpl resources1 = new PoolImpl();
+        ModuleData res1 = new ModuleData("module1", "/module1/toto1",
+                ModuleDataType.CLASS_OR_RESOURCE,
+                new ByteArrayInputStream(new byte[0]), 0);
+        ModuleData res2 = new ModuleData("module2", "/module2/toto1",
+                ModuleDataType.CLASS_OR_RESOURCE,
+                new ByteArrayInputStream(new byte[0]), 0);
+        resources1.add(res1);
+        resources1.add(res2);
+
+        checkResources(resources1, res1, res2);
+        Pool resources2 = new PoolImpl();
+        ModuleData res3 = new ModuleData("module2", "/module2/toto1",
+                ModuleDataType.CLASS_OR_RESOURCE,
+                new ByteArrayInputStream(new byte[7]), 7);
+        resources2.add(res3);
+        resources2.add(PoolImpl.newCompressedResource(res1,
+                ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(),
+                ByteOrder.nativeOrder()));
+        checkResources(resources2, res1, res2);
+    }
+
+    private void checkResources(Pool resources, ModuleData... expected) {
+        Collection<Module> ms = resources.getModules();
+        List<String> modules = new ArrayList();
+        for(Module m : ms) {
+            modules.add(m.getName());
+        }
+        for (ModuleData res : expected) {
+            if (!resources.contains(res)) {
+                throw new AssertionError("Resource not found: " + res);
+            }
+
+            if (resources.get(res.getPath()) == null) {
+                throw new AssertionError("Resource not found: " + res);
+            }
+
+            if (!modules.contains(res.getModule())) {
+                throw new AssertionError("Module not found: " + res.getModule());
+            }
+
+            if (!resources.getContent().contains(res)) {
+                throw new AssertionError("Resources not found: " + res);
+            }
+
+            try {
+                resources.add(res);
+                throw new AssertionError(res + " already present, but an exception is not thrown");
+            } catch (Exception ex) {
+                // Expected
+            }
+        }
+
+        if (resources.isReadOnly()) {
+            throw new AssertionError("ReadOnly resources");
+        }
+
+        ((PoolImpl) resources).setReadOnly();
+        try {
+            resources.add(new ModuleData("module2",  "/module2/toto1",
+                    ModuleDataType.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0));
+            throw new AssertionError("Pool is read-only, but an exception is not thrown");
+        } catch (Exception ex) {
+            // Expected
+        }
+    }
+
+    interface ResourceAdder {
+        void add(Pool resources, String module, String path);
+    }
+}
diff --git a/jdk/test/tools/jlink/SecurityTest.java b/jdk/test/tools/jlink/SecurityTest.java
new file mode 100644
index 0000000..b21c1bc
--- /dev/null
+++ b/jdk/test/tools/jlink/SecurityTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test JlinkPermission
+ * @author Jean-Francois Denise
+ * @run main SecurityTest
+ */
+
+import java.security.AccessControlException;
+import jdk.tools.jlink.Jlink;
+
+public class SecurityTest {
+
+    public static void main(String[] args) throws Exception {
+        new Jlink();
+        System.setSecurityManager(new SecurityManager());
+        boolean failed = false;
+        try {
+            new Jlink();
+            failed = true;
+        } catch (AccessControlException ex) {
+            //XXX OK.
+        }
+        if (failed) {
+            throw new Exception("Call should have failed");
+        }
+
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java
new file mode 100644
index 0000000..6a414b5
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/AddForgetResourcesTest.java
@@ -0,0 +1,509 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test resource transformation.
+ * @author Andrei Eremeev
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ *          jdk.jdeps/com.sun.tools.classfile
+ * @build AsmPluginTestBase
+ * @run main AddForgetResourcesTest
+*/
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Method;
+import java.io.UncheckedIOException;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class AddForgetResourcesTest extends AsmPluginTestBase {
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new AddForgetResourcesTest().test();
+    }
+
+    @Override
+    public void test() throws Exception {
+        TestPlugin[] plugins = new TestPlugin[] {
+                new AddClassesPlugin(),
+                new AddResourcesPlugin(),
+                new ReplaceClassesPlugin(),
+                new ReplaceResourcesPlugin(),
+                new ForgetClassesPlugin(),
+                new ForgetResourcesPlugin(),
+                new AddForgetClassesPlugin(),
+                new AddForgetResourcesPlugin(),
+                new ComboPlugin()
+        };
+        for (TestPlugin p : plugins) {
+            Pool out = p.visit(getPool());
+            p.test(getPool(), out);
+        }
+    }
+
+    private static final String SUFFIX = "HELLOWORLD";
+
+    private static class RenameClassVisitor extends ClassVisitor {
+
+        public RenameClassVisitor(ClassWriter cv) {
+            super(Opcodes.ASM5, cv);
+        }
+
+        @Override
+        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+            super.visit(version, access, name + SUFFIX, signature, superName, interfaces);
+        }
+    }
+
+    private static class AddMethodClassVisitor extends ClassVisitor {
+
+        public AddMethodClassVisitor(ClassWriter cv) {
+            super(Opcodes.ASM5, cv);
+        }
+
+        @Override
+        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+            this.visitMethod(0, SUFFIX, "()V", null, null);
+            super.visit(version, access, name, signature, superName, interfaces);
+        }
+    }
+
+    private class AddClassesPlugin extends TestPlugin {
+
+        private int expected = 0;
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
+            expected = globalPool.getClasses().size();
+            for (ModuleData res : globalPool.getClasses()) {
+                ClassReader reader = globalPool.getClassReader(res);
+                String className = reader.getClassName();
+                if (!className.endsWith("module-info")) {
+                    ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                    reader.accept(new RenameClassVisitor(writer), ClassReader.EXPAND_FRAMES);
+                    transformedClasses.addClass(writer);
+                    ++expected;
+                }
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) {
+            Collection<ModuleData> inClasses = extractClasses(inResources);
+            Collection<ModuleData> outClasses = extractClasses(outResources);
+            if (expected != outClasses.size()) {
+                throw new AssertionError("Classes were not added. Expected: " + expected
+                        + ", got: " + outClasses.size());
+            }
+            for (ModuleData in : inClasses) {
+                String path = in.getPath();
+                if (!outClasses.contains(in)) {
+                    throw new AssertionError("Class not found: " + path);
+                }
+                if (path.endsWith("module-info.class")) {
+                    continue;
+                }
+                String modifiedPath = path.replace(".class", SUFFIX + ".class");
+                if (!outClasses.contains(Pool.newResource(modifiedPath, new byte[0]))) {
+                    throw new AssertionError("Class not found: " + modifiedPath);
+                }
+            }
+        }
+    }
+
+    private class AddResourcesPlugin extends TestPlugin {
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            for (ModuleData res : globalPool.getResourceFiles()) {
+                String path = res.getPath();
+                String moduleName = getModule(path);
+                AsmModulePool modulePool = pools.getModulePool(moduleName);
+                WritableResourcePool resourcePool = modulePool.getTransformedResourceFiles();
+                resourcePool.addResourceFile(new ResourceFile(removeModule(res.getPath()) + SUFFIX,
+                        res.getBytes()));
+            }
+        }
+
+        @Override
+        public void test(Pool in, Pool out) throws Exception {
+            Collection<ModuleData> inResources = extractResources(in);
+            Collection<ModuleData> outResources = extractResources(out);
+            if (2 * inResources.size() != outResources.size()) {
+                throw new AssertionError("Classes were not added. Expected: " + (2 * inResources.size())
+                        + ", got: " + outResources.size());
+            }
+            for (ModuleData r : inResources) {
+                String path = r.getPath();
+                if (!outResources.contains(r)) {
+                    throw new AssertionError("Class not found: " + path);
+                }
+                String modifiedPath = path + SUFFIX;
+                if (!outResources.contains(Pool.newResource(modifiedPath, new byte[0]))) {
+                    throw new AssertionError("Class not found: " + modifiedPath);
+                }
+            }
+        }
+    }
+
+    private class ReplaceClassesPlugin extends TestPlugin {
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
+            for (ModuleData res : globalPool.getClasses()) {
+                ClassReader reader = globalPool.getClassReader(res);
+                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                reader.accept(new AddMethodClassVisitor(writer), ClassReader.EXPAND_FRAMES);
+                transformedClasses.addClass(writer);
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            Collection<ModuleData> inClasses = extractClasses(inResources);
+            Collection<ModuleData> outClasses = extractClasses(outResources);
+            if (inClasses.size() != outClasses.size()) {
+                throw new AssertionError("Number of classes. Expected: " + (inClasses.size())
+                        + ", got: " + outClasses.size());
+            }
+            for (ModuleData out : outClasses) {
+                String path = out.getPath();
+                if (!inClasses.contains(out)) {
+                    throw new AssertionError("Class not found: " + path);
+                }
+                ClassFile cf = ClassFile.read(new ByteArrayInputStream(out.getBytes()));
+                if (path.endsWith("module-info.class")) {
+                    continue;
+                }
+                boolean failed = true;
+                for (Method m : cf.methods) {
+                    if (m.getName(cf.constant_pool).equals(SUFFIX)) {
+                        failed = false;
+                    }
+                }
+                if (failed) {
+                    throw new AssertionError("Not found method with name " + SUFFIX + " in class " + path);
+                }
+            }
+        }
+    }
+
+    private class ReplaceResourcesPlugin extends TestPlugin {
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            for (ModuleData res : globalPool.getResourceFiles()) {
+                String path = res.getPath();
+                AsmModulePool modulePool = pools.getModulePool(getModule(path));
+                modulePool.getTransformedResourceFiles().addResourceFile(new ResourceFile(removeModule(path),
+                        "HUI".getBytes()));
+            }
+        }
+
+        @Override
+        public void test(Pool in, Pool out) throws Exception {
+            Collection<ModuleData> inResources = extractResources(in);
+            Collection<ModuleData> outResources = extractResources(out);
+            if (inResources.size() != outResources.size()) {
+                throw new AssertionError("Number of resources. Expected: " + inResources.size()
+                        + ", got: " + outResources.size());
+            }
+            for (ModuleData r : outResources) {
+                String path = r.getPath();
+                if (!inResources.contains(r)) {
+                    throw new AssertionError("Resource not found: " + path);
+                }
+                String content = new String(r.getBytes());
+                if (!"HUI".equals(content)) {
+                    throw new AssertionError("Content expected: 'HUI', got: " + content);
+                }
+            }
+        }
+    }
+
+    private class ForgetClassesPlugin extends TestPlugin {
+
+        private int expected = 0;
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
+            int i = 0;
+            for (ModuleData res : globalPool.getClasses()) {
+                String path = removeModule(res.getPath());
+                String className = path.replace(".class", "");
+                if ((i & 1) == 0 && !className.endsWith("module-info")) {
+                    transformedClasses.forgetClass(className);
+                } else {
+                    ++expected;
+                }
+                i ^= 1;
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            Collection<ModuleData> outClasses = extractClasses(outResources);
+            if (expected != outClasses.size()) {
+                throw new AssertionError("Number of classes. Expected: " + expected +
+                        ", got: " + outClasses.size());
+            }
+        }
+    }
+
+    private class ForgetResourcesPlugin extends TestPlugin {
+
+        private int expectedAmount = 0;
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            int i = 0;
+            for (ModuleData res : globalPool.getResourceFiles()) {
+                String path = res.getPath();
+                if (!path.contains("META-INF/services")) {
+                    if ((i & 1) == 0) {
+                        AsmModulePool modulePool = pools.getModulePool(getModule(path));
+                        modulePool.getTransformedResourceFiles().forgetResourceFile(removeModule(res.getPath()));
+                    } else {
+                        ++expectedAmount;
+                    }
+                    i ^= 1;
+                } else {
+                    ++expectedAmount;
+                }
+            }
+        }
+
+        @Override
+        public void test(Pool in, Pool out) throws Exception {
+            Collection<ModuleData> outResources = extractResources(out);
+            if (expectedAmount != outResources.size()) {
+                throw new AssertionError("Number of classes. Expected: " + expectedAmount
+                        + ", got: " + outResources.size());
+            }
+        }
+    }
+
+    private class AddForgetClassesPlugin extends TestPlugin {
+
+        private int expected = 0;
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
+            int i = 0;
+            for (ModuleData res : globalPool.getClasses()) {
+                ClassReader reader = globalPool.getClassReader(res);
+                String className = reader.getClassName();
+                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                if (!className.endsWith("module-info")) {
+                    reader.accept(new RenameClassVisitor(writer), ClassReader.EXPAND_FRAMES);
+                    transformedClasses.addClass(writer);
+                    ++expected;
+                }
+
+                if ((i & 1) == 0 && !className.endsWith("module-info")) {
+                    transformedClasses.forgetClass(className);
+                } else {
+                    ++expected;
+                }
+                i ^= 1;
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            Collection<ModuleData> outClasses = extractClasses(outResources);
+            if (expected != outClasses.size()) {
+                throw new AssertionError("Number of classes. Expected: " + expected
+                        + ", got: " + outClasses.size());
+            }
+        }
+    }
+
+    private class AddForgetResourcesPlugin extends TestPlugin {
+
+        private int expectedAmount = 0;
+
+        @Override
+        public void visit() {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            int i = 0;
+            for (ModuleData res : globalPool.getResourceFiles()) {
+                String path = res.getPath();
+                String moduleName = getModule(path);
+                if (!path.contains("META-INF")) {
+                    AsmModulePool modulePool = pools.getModulePool(moduleName);
+                    WritableResourcePool transformedResourceFiles = modulePool.getTransformedResourceFiles();
+                    String newPath = removeModule(path) + SUFFIX;
+                    transformedResourceFiles.addResourceFile(new ResourceFile(newPath, res.getBytes()));
+                    if ((i & 1) == 0) {
+                        transformedResourceFiles.forgetResourceFile(newPath);
+                    } else {
+                        ++expectedAmount;
+                    }
+                    i ^= 1;
+                }
+                ++expectedAmount;
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool out) throws Exception {
+            Collection<ModuleData> outResources = extractResources(out);
+            if (expectedAmount != outResources.size()) {
+                throw new AssertionError("Number of classes. Expected: " + expectedAmount
+                        + ", got: " + outResources.size());
+            }
+        }
+    }
+
+    private class ComboPlugin extends TestPlugin {
+
+        private class RenameClassVisitor extends ClassVisitor {
+
+            public RenameClassVisitor(ClassWriter cv) {
+                super(Opcodes.ASM5, cv);
+            }
+
+            @Override
+            public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+                super.visit(version, access, name + SUFFIX, signature, superName, interfaces);
+            }
+        }
+
+        @Override
+        public void visit() {
+            try {
+                renameClasses();
+                renameResources();
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            if (!isVisitCalled()) {
+                throw new AssertionError("Resources not visited");
+            }
+            AsmGlobalPool globalPool = getPools().getGlobalPool();
+            if (globalPool.getTransformedClasses().getClasses().size() != getClasses().size()) {
+                throw new AssertionError("Number of transformed classes not equal to expected");
+            }
+            // Check that only renamed classes and resource files are in the result.
+            for (ModuleData r : outResources.getContent()) {
+                String resourceName = r.getPath();
+                if (resourceName.endsWith(".class") && !resourceName.endsWith("module-info.class")) {
+                    if (!resourceName.endsWith(SUFFIX + ".class")) {
+                        throw new AssertionError("Class not renamed " + resourceName);
+                    }
+                } else if (resourceName.contains("META-INF/services/") && MODULES.containsKey(r.getModule())) {
+                    String newClassName = new String(r.getBytes());
+                    if(!newClassName.endsWith(SUFFIX)) {
+                        throw new AssertionError("Resource file not renamed " + resourceName);
+                    }
+                }
+            }
+        }
+
+        private void renameResources() throws IOException {
+            AsmPools pools = getPools();
+            // Rename the resource Files
+            for (Map.Entry<String, List<String>> mod : MODULES.entrySet()) {
+                String moduleName = mod.getKey();
+                AsmModulePool modulePool = pools.getModulePool(moduleName);
+                for (ModuleData res : modulePool.getResourceFiles()) {
+                    ResourceFile resFile = modulePool.getResourceFile(res);
+                    if (resFile.getPath().startsWith("META-INF/services/")) {
+                        String newContent = new String(resFile.getContent()) + SUFFIX;
+                        ResourceFile newResourceFile = new ResourceFile(resFile.getPath(),
+                                newContent.getBytes());
+                        modulePool.getTransformedResourceFiles().addResourceFile(newResourceFile);
+                    }
+                }
+            }
+        }
+
+        private void renameClasses() throws IOException {
+            AsmPools pools = getPools();
+            AsmGlobalPool globalPool = pools.getGlobalPool();
+            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
+            for (ModuleData res : globalPool.getClasses()) {
+                if (res.getPath().endsWith("module-info.class")) {
+                    continue;
+                }
+                ClassReader reader = globalPool.getClassReader(res);
+                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                RenameClassVisitor visitor = new RenameClassVisitor(writer);
+                reader.accept(visitor, ClassReader.EXPAND_FRAMES);
+
+                transformedClasses.forgetClass(reader.getClassName());
+                transformedClasses.addClass(writer);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java
new file mode 100644
index 0000000..d5c0355
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/AsmPluginTestBase.java
@@ -0,0 +1,249 @@
+/*
+ * 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.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.StringTable;
+
+import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public abstract class AsmPluginTestBase {
+
+    protected static final String TEST_MODULE = "jlink.test";
+    protected static final Map<String, List<String>> MODULES;
+
+    private static final Predicate<ModuleData> isClass = r -> r.getPath().endsWith(".class");
+    private final List<String> classes;
+    private final List<String> resources;
+    private final Pool pool;
+
+    static {
+        Map<String, List<String>> map = new HashMap<>();
+        map.put("jdk.localedata", new ArrayList<>());
+        map.put("java.base", new ArrayList<>());
+        map.put(TEST_MODULE, new ArrayList<>());
+        MODULES = Collections.unmodifiableMap(map);
+    }
+
+    public static boolean isImageBuild() {
+        Path javaHome = Paths.get(System.getProperty("test.jdk"));
+        Path jmods = javaHome.resolve("jmods");
+        return Files.exists(jmods);
+    }
+
+    public AsmPluginTestBase() {
+        try {
+            List<String> classes = new ArrayList<>();
+            List<String> resources = new ArrayList<>();
+
+            pool = new PoolImpl();
+
+            FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+            Path root = fs.getPath("/modules");
+
+            List<byte[]> moduleInfos = new ArrayList<>();
+            try (Stream<Path> stream = Files.walk(root)) {
+                for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext(); ) {
+                    Path p = iterator.next();
+                    if (Files.isRegularFile(p)) {
+                        String module = p.toString().substring("/modules/".length());
+                        module = module.substring(0, module.indexOf("/"));
+                        if (MODULES.keySet().contains(module)) {
+                            try {
+                                boolean isModuleInfo = p.endsWith("module-info.class");
+                                if (isModuleInfo) {
+                                    moduleInfos.add(Files.readAllBytes(p));
+                                }
+                                byte[] content = Files.readAllBytes(p);
+                                if (p.toString().endsWith(".class") && !isModuleInfo) {
+                                    classes.add(toClassName(p));
+                                } else if (!isModuleInfo) {
+                                    MODULES.get(module).add(toResourceFile(p));
+                                }
+                                resources.add(toPath(p.toString()));
+                                ModuleData res = Pool.newResource(toPath(p.toString()), content);
+                                pool.add(res);
+                            } catch (Exception ex) {
+                                throw new RuntimeException(ex);
+                            }
+                        }
+                    }
+                }
+            }
+            // There is more than 10 classes in java.base...
+            if (classes.size() < 10 || pool.getContent().size() < 10) {
+                throw new AssertionError("Not expected resource or class number");
+            }
+
+            //Add a fake resource file
+            String content = "java.lang.Object";
+            String path = "META-INF/services/com.foo.BarProvider";
+            ModuleData resFile = Pool.newResource("/" + TEST_MODULE + "/" +
+                    path, content.getBytes());
+            pool.add(resFile);
+            ModuleData fakeInfoFile = Pool.newResource("/" + TEST_MODULE
+                    + "/module-info.class", moduleInfos.get(0));
+            pool.add(fakeInfoFile);
+            MODULES.get(TEST_MODULE).add(path);
+            for(Map.Entry<String, List<String>> entry : MODULES.entrySet()) {
+                if (entry.getValue().isEmpty()) {
+                    throw new AssertionError("No resource file for " + entry.getKey());
+                }
+            }
+            this.classes = Collections.unmodifiableList(classes);
+            this.resources = Collections.unmodifiableList(resources);
+        } catch (Exception e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    public List<String> getClasses() {
+        return classes;
+    }
+
+    public List<String> getResources() {
+        return resources;
+    }
+
+    public Pool getPool() {
+        return pool;
+    }
+
+    public abstract void test() throws Exception;
+
+    public Collection<ModuleData> extractClasses(Pool pool) {
+        return pool.getContent().stream()
+                .filter(isClass)
+                .collect(Collectors.toSet());
+    }
+
+    public Collection<ModuleData> extractResources(Pool pool) {
+        return pool.getContent().stream()
+                .filter(isClass.negate())
+                .collect(Collectors.toSet());
+    }
+
+    public String getModule(String path) {
+        int index = path.indexOf("/", 1);
+        return path.substring(1, index);
+    }
+
+    public String removeModule(String path) {
+        int index = path.indexOf("/", 1);
+        return path.substring(index + 1);
+    }
+
+    private String toPath(String p) {
+        return p.substring("/modules".length());
+    }
+
+    private String toClassName(Path p) {
+        String path = p.toString();
+        path = path.substring("/modules/".length());
+        // remove module
+        if (!path.endsWith("module-info.class")) {
+            path = path.substring(path.indexOf("/") + 1);
+        }
+        path = path.substring(0, path.length() - ".class".length());
+
+        return path;
+    }
+
+    private String toResourceFile(Path p) {
+        String path = p.toString();
+        path = path.substring("/modules/".length());
+        // remove module
+        path = path.substring(path.indexOf("/") + 1);
+
+        return path;
+    }
+
+    public abstract class TestPlugin extends AsmPlugin {
+
+        private AsmPools pools;
+
+        public AsmPools getPools() {
+            return pools;
+        }
+
+        public boolean isVisitCalled() {
+            return pools != null;
+        }
+
+        public Pool visit(Pool inResources) throws IOException {
+            try {
+                Pool outResources = new PoolImpl(inResources.getByteOrder(), new StringTable() {
+                    @Override
+                    public int addString(String str) {
+                        return -1;
+                    }
+
+                    @Override
+                    public String getString(int id) {
+                        return null;
+                    }
+                });
+                visit(inResources, outResources);
+                return outResources;
+            } catch (Exception e) {
+                throw new IOException(e);
+            }
+        }
+
+        @Override
+        public void visit(AsmPools pools) {
+            if (isVisitCalled()) {
+                throw new AssertionError("Visit was called twice");
+            }
+            this.pools = pools;
+            visit();
+        }
+
+        public abstract void visit();
+        public abstract void test(Pool inResources, Pool outResources) throws Exception;
+
+        @Override
+        public String getName() {
+            return "test-plugin";
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/BasicTest.java b/jdk/test/tools/jlink/asmplugin/BasicTest.java
new file mode 100644
index 0000000..0c42d4c
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/BasicTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test basic functionality.
+ * @author Jean-Francois Denise
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @build AsmPluginTestBase
+ * @run main BasicTest
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class BasicTest extends AsmPluginTestBase {
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new BasicTest().test();
+    }
+
+    @Override
+    public void test() throws Exception {
+        BasicPlugin basicPlugin = new BasicPlugin(getClasses());
+        Pool res = basicPlugin.visit(getPool());
+        basicPlugin.test(getPool(), res);
+    }
+
+    private class BasicPlugin extends TestPlugin {
+
+        private final List<String> classes;
+
+        public BasicPlugin(List<String> classes) {
+            this.classes = classes;
+        }
+
+        @Override
+        public void visit() {
+            for (String m : MODULES.keySet()) {
+                AsmModulePool pool = getPools().getModulePool(m);
+                if (pool == null) {
+                    throw new AssertionError(m + " pool not found");
+                }
+                if(!pool.getModuleName().equals(m)) {
+                    throw new AssertionError("Invalid module name " +
+                            pool.getModuleName() + " should be "+ m);
+                }
+                if (pool.getClasses().size() == 0 && !m.equals(TEST_MODULE)) {
+                    throw new AssertionError("Empty pool " + m);
+                }
+                pool.addPackage("toto");
+                if (!pool.getTransformedClasses().getClasses().isEmpty()) {
+                    throw new AssertionError("Should be empty");
+                }
+                for(String res : MODULES.get(m)) {
+                    AsmPool.ResourceFile resFile = pool.getResourceFile(res);
+                    if(resFile == null) {
+                        throw new AssertionError("No resource file for " + res);
+                    }
+                }
+            }
+            try {
+                testPools();
+                testVisitor();
+            } catch (IOException ex) {
+                throw new UncheckedIOException(ex);
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            if (!isVisitCalled()) {
+                throw new AssertionError("Resources not visited");
+            }
+            if (inResources.getContent().size() != outResources.getContent().size()) {
+                throw new AssertionError("Input size " + inResources.getContent().size() +
+                        " != to " + outResources.getContent().size());
+            }
+        }
+
+        private void testVisitor() throws IOException {
+            List<String> seen = new ArrayList<>();
+            getPools().getGlobalPool().visitClassReaders((reader) -> {
+                String className = reader.getClassName();
+                // Wrong naming of module-info.class in ASM
+                if (className.endsWith("module-info")) {
+                    return null;
+                }
+                if (!classes.contains(className)) {
+                    throw new AssertionError("Class is not expected " + className);
+                }
+                if (getPools().getGlobalPool().getClassReader(className) == null) {
+                    throw new AssertionError("Class not found in pool " + className);
+                }
+                seen.add(className);
+                return null;
+            });
+
+            if (!seen.equals(classes)) {
+                throw new AssertionError("Expected and seen are not equal");
+            }
+        }
+
+        private void testPools() throws IOException {
+            Set<String> remain = new HashSet<>(classes);
+            for (ModuleData res : getPools().getGlobalPool().getClasses()) {
+                ClassReader reader = getPools().getGlobalPool().getClassReader(res);
+                String className = reader.getClassName();
+                // Wrong naming of module-info.class in ASM
+                if (className.endsWith("module-info")) {
+                    continue;
+                }
+                if (!classes.contains(className)) {
+                    throw new AssertionError("Class is not expected " + className);
+                }
+                if (getPools().getGlobalPool().getClassReader(className) == null) {
+                    throw new AssertionError("Class " + className + " not found in pool ");
+                }
+                // Check the module pool
+                boolean found = false;
+                for(AsmModulePool mp : getPools().getModulePools()) {
+                    if(mp.getClassReader(className) != null) {
+                        found = true;
+                        break;
+                    }
+                }
+                if(!found) {
+                    throw new AssertionError("No modular pool for " +
+                            className);
+                }
+                remain.remove(className);
+            }
+            if (!remain.isEmpty()) {
+                throw new AssertionError("Remaining classes " + remain);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java
new file mode 100644
index 0000000..ceb2e50
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/IdentityPluginTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test basic functionality.
+ * @author Jean-Francois Denise
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @build AsmPluginTestBase
+ * @run main IdentityPluginTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class IdentityPluginTest extends AsmPluginTestBase {
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new IdentityPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        IdentityPlugin asm = new IdentityPlugin();
+        Pool resourcePool = asm.visit(getPool());
+        asm.test(getPool(), resourcePool);
+    }
+
+    private class IdentityPlugin extends TestPlugin {
+
+        @Override
+        public void visit() {
+            for (ModuleData res : getPools().getGlobalPool().getClasses()) {
+                if (res.getPath().endsWith("module-info.class")) {
+                    continue;
+                }
+                ClassReader reader = getPools().getGlobalPool().getClassReader(res);
+                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                IdentityClassVisitor visitor = new IdentityClassVisitor(writer);
+                reader.accept(visitor, ClassReader.EXPAND_FRAMES);
+                getPools().getGlobalPool().getTransformedClasses().addClass(writer);
+            }
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws IOException {
+            if (outResources.isEmpty()) {
+                throw new AssertionError("Empty result");
+            }
+            if (!isVisitCalled()) {
+                throw new AssertionError("Resources not visited");
+            }
+            WritableClassPool transformedClasses = getPools().getGlobalPool().getTransformedClasses();
+            if (transformedClasses.getClasses().size() != getClasses().size()) {
+                throw new AssertionError("Number of transformed classes not equal to expected");
+            }
+            for (String className : getClasses()) {
+                if (transformedClasses.getClassReader(className) == null) {
+                    throw new AssertionError("Class not transformed " + className);
+                }
+            }
+            for (ModuleData r : outResources.getContent()) {
+                if (r.getPath().endsWith(".class") && !r.getPath().endsWith("module-info.class")) {
+                    ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes()));
+                    ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                    reader.accept(w, ClassReader.EXPAND_FRAMES);
+                }
+            }
+        }
+
+        @Override
+        public String getName() {
+            return "identity-plugin";
+        }
+    }
+
+    private static class IdentityClassVisitor extends ClassVisitor {
+        public IdentityClassVisitor(ClassWriter cv) {
+            super(Opcodes.ASM5, cv);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/NegativeTest.java b/jdk/test/tools/jlink/asmplugin/NegativeTest.java
new file mode 100644
index 0000000..f95b7c6
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/NegativeTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test basic functionality.
+ * @author Andrei Eremeev
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @build AsmPluginTestBase
+ * @run main NegativeTest
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.ByteOrder;
+import java.util.Map;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+
+public class NegativeTest extends AsmPluginTestBase {
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new NegativeTest().test();
+    }
+
+    @Override
+    public void test() throws Exception {
+        testNull();
+        testUnknownPackage();
+    }
+
+    private void testUnknownPackage() throws Exception {
+        AsmPlugin t = new AsmPlugin() {
+            @Override
+            public void visit(AsmPools pools) {
+                try {
+                    AsmGlobalPool globalPool = pools.getGlobalPool();
+                    AsmModulePool javabase = pools.getModulePool("java.base");
+                    ClassReader cr = new ClassReader(NegativeTest.class.getResourceAsStream("NegativeTest.class"));
+                    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
+                    cr.accept(new RenameClassVisitor(cw), ClassReader.EXPAND_FRAMES);
+                    action(() -> globalPool.getTransformedClasses().addClass(cw),
+                            "Unknown package", PluginException.class);
+                    action(() -> javabase.getTransformedClasses().addClass(cw),
+                            "Unknown package", PluginException.class);
+
+                    ResourceFile newResFile = new ResourceFile("java/aaa/file", new byte[0]);
+                    action(() -> globalPool.getTransformedResourceFiles().addResourceFile(newResFile),
+                            "Unknown package", PluginException.class);
+                    action(() -> javabase.getTransformedResourceFiles().addResourceFile(newResFile),
+                            "Unknown package", PluginException.class);
+
+                    action(() -> globalPool.getTransformedClasses().forgetClass("java/aaa/file"),
+                            "Unknown package", PluginException.class);
+                    action(() -> javabase.getTransformedClasses().forgetClass("java/aaa/file"),
+                            "Unknown package", PluginException.class);
+                    action(() -> globalPool.getTransformedResourceFiles().forgetResourceFile("java/aaa/file"),
+                            "Unknown package", PluginException.class);
+                    action(() -> javabase.getTransformedResourceFiles().forgetResourceFile("java/aaa/file"),
+                            "Unknown package", PluginException.class);
+                } catch (IOException ex) {
+                   throw new UncheckedIOException(ex);
+                }
+            }
+        };
+        Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        });
+        t.visit(getPool(), resources);
+    }
+
+    private static class RenameClassVisitor extends ClassVisitor {
+
+        public RenameClassVisitor(ClassWriter cv) {
+            super(Opcodes.ASM5, cv);
+        }
+
+        @Override
+        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+            super.visit(version, access, "RENAMED", signature, superName, interfaces);
+        }
+    }
+
+    private void testNull() throws Exception {
+        AsmPlugin t = new AsmPlugin() {
+            @Override
+            public void visit(AsmPools pools) {
+                action(() -> pools.getModulePool(null), "Module name is null", NullPointerException.class);
+                action(() -> pools.fillOutputResources(null), "Output resource is null", NullPointerException.class);
+            }
+        };
+        Pool resources = new PoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        });
+        action(() -> t.visit(null, resources), "Input resource is null", NullPointerException.class);
+        action(() -> t.visit(resources, null), "Output resource is null", NullPointerException.class);
+        t.visit(resources, resources);
+    }
+
+    private void action(Action action, String message, Class<? extends Exception> expected) {
+        try {
+            System.err.println("Testing: " + message);
+            action.call();
+            throw new AssertionError(message + ": should have failed");
+        } catch (Exception e) {
+            if (!expected.isInstance(e)) {
+                throw new RuntimeException(e);
+            } else {
+                System.err.println("Got exception as expected: " + e);
+            }
+        }
+    }
+
+    private interface Action {
+        void call() throws Exception;
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java
new file mode 100644
index 0000000..9453ac5
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/PackageMappingTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test plugins
+ * @author Andrei Eremeev
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @run main PackageMappingTest
+ */
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class PackageMappingTest extends AsmPluginTestBase {
+
+    private final List<String> newFiles = Arrays.asList(
+            "/java.base/a1/bbb/c",
+            "/" + TEST_MODULE + "/a2/bbb/d"
+    );
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new PackageMappingTest().test();
+    }
+
+    public void test() throws Exception {
+        TestPlugin[] plugins = new TestPlugin[]{
+            new PackageMappingPlugin(newFiles, false),
+            new PackageMappingPlugin(newFiles, true)
+        };
+        for (TestPlugin p : plugins) {
+            Pool pool = p.visit(getPool());
+            p.test(getPool(), pool);
+        }
+    }
+
+    public class PackageMappingPlugin extends TestPlugin {
+
+        private final Map<String, List<ResourceFile>> newFiles;
+        private final boolean testGlobal;
+
+        private String getModuleName(String res) {
+            return res.substring(1, res.indexOf("/", 1));
+        }
+
+        private PackageMappingPlugin(List<String> files, boolean testGlobal) {
+            this.newFiles = new HashMap<>();
+            this.testGlobal = testGlobal;
+            for (String file : files) {
+                String moduleName = getModuleName(file);
+                String path = file.substring(1 + moduleName.length() + 1);
+                newFiles.computeIfAbsent(moduleName, $ -> new ArrayList<>()).add(
+                        new ResourceFile(path, new byte[0]));
+            }
+        }
+
+        @Override
+        public void visit() {
+            testMapToUnknownModule();
+            testMapPackageTwice();
+            testPackageMapping();
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) {
+            Set<String> in = getPools().getGlobalPool().getResourceFiles().stream()
+                    .map(ModuleData::getPath)
+                    .collect(Collectors.toSet());
+            Set<String> out = extractResources(outResources).stream()
+                    .map(ModuleData::getPath)
+                    .collect(Collectors.toSet());
+            in.addAll(PackageMappingTest.this.newFiles);
+            if (!Objects.equals(in, out)) {
+                throw new AssertionError("Expected: " + in + ", got: " + outResources);
+            }
+        }
+
+        private void testPackageMapping() {
+            AsmGlobalPool globalPool = getPools().getGlobalPool();
+            try {
+                Map<String, Set<String>> mappedPackages = new HashMap<>();
+                Function<String, Set<String>> produceSet = $ -> new HashSet<>();
+                for (Map.Entry<String, List<ResourceFile>> entry : newFiles.entrySet()) {
+                    String moduleName = entry.getKey();
+                    Set<String> module = mappedPackages.computeIfAbsent(moduleName, produceSet);
+                    AsmModulePool modulePool = getPools().getModulePool(moduleName);
+                    for (ResourceFile r : entry.getValue()) {
+                        String name = r.getPath();
+                        String packageName = name.substring(0, name.lastIndexOf('/'));
+                        if (module.add(packageName)) {
+                            globalPool.addPackageModuleMapping(packageName, moduleName);
+                        }
+                        WritableResourcePool transformedResourceFiles = testGlobal
+                                ? globalPool.getTransformedResourceFiles()
+                                : modulePool.getTransformedResourceFiles();
+                        transformedResourceFiles.addResourceFile(r);
+                    }
+                    try {
+                        modulePool.getTransformedResourceFiles().addResourceFile(
+                                new ResourceFile("a3/bbb", new byte[0]));
+                        throw new AssertionError("Exception expected");
+                    } catch (Exception ex) {
+                        // expected
+                    }
+                }
+                try {
+                    globalPool.getTransformedResourceFiles().addResourceFile(
+                            new ResourceFile("a3/bbb", new byte[0]));
+                    throw new AssertionError("Exception expected");
+                } catch (Exception ex) {
+                    // expected
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        private void testMapPackageTwice() {
+            try {
+                AsmGlobalPool globalPool = getPools().getGlobalPool();
+                globalPool.addPackageModuleMapping("a/p1", TEST_MODULE);
+                globalPool.addPackageModuleMapping("a/p1", TEST_MODULE);
+                throw new AssertionError("Exception expected after mapping a package twice to the same module");
+            } catch (Exception e) {
+                if (e instanceof PluginException) {
+                    // expected
+                    String message = e.getMessage();
+                    if (!(TEST_MODULE + " module already contains package a.p1").equals(message)) {
+                        throw new AssertionError(e);
+                    }
+                } else {
+                    throw new AssertionError(e);
+                }
+            }
+        }
+
+        private void testMapToUnknownModule() {
+            AsmModulePool unknownModule = getPools().getModulePool("UNKNOWN");
+            if (unknownModule != null) {
+                throw new AssertionError("getModulePool returned not null value: " + unknownModule.getModuleName());
+            }
+            try {
+                AsmGlobalPool globalPool = getPools().getGlobalPool();
+                globalPool.addPackageModuleMapping("a/b", "UNKNOWN");
+                throw new AssertionError("Exception expected after mapping a package to unknown module");
+            } catch (Exception e) {
+                String message = e.getMessage();
+                if (message == null || !message.startsWith("Unknown module UNKNOWN")) {
+                    throw new AssertionError(e);
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/SortingTest.java b/jdk/test/tools/jlink/asmplugin/SortingTest.java
new file mode 100644
index 0000000..0fc4c7a
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/SortingTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test resource sorting.
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @build AsmPluginTestBase
+ * @run main SortingTest
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class SortingTest extends AsmPluginTestBase {
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new SortingTest().test();
+    }
+
+    @Override
+    public void test() {
+        try {
+            classSorting();
+            moduleSorting();
+        } catch (Exception ex) {
+            throw new PluginException(ex);
+        }
+    }
+
+    private void classSorting() throws Exception {
+        List<String> sorted = new ArrayList<>(getResources());
+        sorted.sort(null);
+        ClassSorterPlugin sorterPlugin = new ClassSorterPlugin(sorted);
+        Pool resourcePool = sorterPlugin.visit(getPool());
+        sorterPlugin.test(getPool(), resourcePool);
+    }
+
+    private String getModuleName(String p) {
+        return p.substring(1, p.indexOf('/', 1));
+    }
+
+    private void moduleSorting() throws Exception {
+        List<String> sorted = new ArrayList<>(getResources());
+        sorted.sort((s1, s2) -> -getModuleName(s1).compareTo(getModuleName(s2)));
+        ModuleSorterPlugin sorterPlugin = new ModuleSorterPlugin();
+        Pool resourcePool = sorterPlugin.visit(getPool());
+        sorterPlugin.test(getPool(), resourcePool);
+    }
+
+    private class ModuleSorterPlugin extends TestPlugin {
+
+        @Override
+        public void visit() {
+            for (AsmModulePool modulePool : getPools().getModulePools()) {
+                modulePool.setSorter(resources -> {
+                    List<String> sort = resources.getContent().stream()
+                            .map(ModuleData::getPath)
+                            .collect(Collectors.toList());
+                    sort.sort(null);
+                    return sort;
+                });
+            }
+            getPools().setModuleSorter(modules -> {
+                modules.sort((s1, s2) -> -s1.compareTo(s2));
+                return modules;
+            });
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            if (!isVisitCalled()) {
+                throw new AssertionError("Resources not visited");
+            }
+            List<String> sortedResourcePaths = outResources.getContent().stream()
+                    .map(ModuleData::getPath)
+                    .collect(Collectors.toList());
+
+            List<String> defaultResourceOrder = new ArrayList<>();
+            for (ModuleData r : inResources.getContent()) {
+                if (!inResources.getContent().contains(r)) {
+                    throw new AssertionError("Resource " + r.getPath() + " not in result pool");
+                }
+                defaultResourceOrder.add(r.getPath());
+            }
+            // Check that default sorting is not equal to sorted one
+            if (defaultResourceOrder.equals(sortedResourcePaths)) {
+                throw new AssertionError("Sorting not applied, default ordering");
+            }
+            // Check module order.
+            for (int i = 0; i < sortedResourcePaths.size() - 1; ++i) {
+                String first = sortedResourcePaths.get(i);
+                String p1 = getModuleName(first);
+                String second = sortedResourcePaths.get(i + 1);
+                String p2 = getModuleName(second);
+                if (p1.compareTo(p2) < 0 || p1.compareTo(p2) == 0 &&
+                        removeModule(first).compareTo(removeModule(second)) >= 0) {
+                    throw new AssertionError("Modules are not sorted properly: resources: " + first + " " + second);
+                }
+            }
+        }
+    }
+
+    private class ClassSorterPlugin extends TestPlugin {
+
+        private final List<String> expectedClassesOrder;
+
+        private ClassSorterPlugin(List<String> expectedClassesOrder) {
+            this.expectedClassesOrder = expectedClassesOrder;
+        }
+
+        @Override
+        public void visit() {
+            getPools().getGlobalPool().setSorter(
+                    (resources) -> expectedClassesOrder.stream()
+                            .map(resources::get)
+                            .map(ModuleData::getPath)
+                            .collect(Collectors.toList()));
+        }
+
+        @Override
+        public void test(Pool inResources, Pool outResources) throws Exception {
+            if (!isVisitCalled()) {
+                throw new AssertionError("Resources not visited");
+            }
+            List<String> sortedResourcePaths = outResources.getContent().stream()
+                    .map(ModuleData::getPath)
+                    .collect(Collectors.toList());
+
+            List<String> defaultResourceOrder = new ArrayList<>();
+            for (ModuleData r : getPool().getContent()) {
+                if (!getPool().getContent().contains(r)) {
+                    throw new AssertionError("Resource " + r.getPath() + " not in result pool");
+                }
+                defaultResourceOrder.add(r.getPath());
+            }
+            // Check that default sorting is not equal to sorted one
+            if (defaultResourceOrder.equals(sortedResourcePaths)) {
+                throw new AssertionError("Sorting not applied, default ordering");
+            }
+            // Check that sorted is equal to result.
+            if (!expectedClassesOrder.equals(sortedResourcePaths)) {
+                throw new AssertionError("Sorting not properly applied");
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/asmplugin/VisitorTest.java b/jdk/test/tools/jlink/asmplugin/VisitorTest.java
new file mode 100644
index 0000000..1b278a8
--- /dev/null
+++ b/jdk/test/tools/jlink/asmplugin/VisitorTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ */
+
+/*
+ * Asm plugin testing.
+ * @test
+ * @summary Test visitors.
+ * @author Andrei Eremeev
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
+ * @build AsmPluginTestBase
+ * @run main VisitorTest
+ */
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.function.Function;
+
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ClassReaderVisitor;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
+import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFileVisitor;
+import jdk.tools.jlink.internal.plugins.asm.AsmPools;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class VisitorTest extends AsmPluginTestBase {
+
+    public static void main(String[] args) throws Exception {
+        if (!isImageBuild()) {
+            System.err.println("Test not run. Not image build.");
+            return;
+        }
+        new VisitorTest().test();
+    }
+
+    @Override
+    public void test() throws Exception {
+        TestPlugin[] plugins = new TestPlugin[] {
+                new ClassVisitorPlugin("Class-global-pool", AsmPools::getGlobalPool),
+                new ClassVisitorPlugin("Class-module-pool", pools -> pools.getModulePool("java.base")),
+                new ResourceVisitorPlugin("Resource-global-pool", AsmPools::getGlobalPool),
+                new ResourceVisitorPlugin("Resource-module-pool", pools -> pools.getModulePool("java.base"))
+        };
+        for (TestPlugin p : plugins) {
+            System.err.println("Testing: " + p.getName());
+            Pool out = p.visit(getPool());
+            p.test(getPool(), out);
+        }
+    }
+
+    private static class CustomClassReaderVisitor implements ClassReaderVisitor {
+        private int amount = 0;
+        private int changed = 0;
+
+        @Override
+        public ClassWriter visit(ClassReader reader) {
+            if ((amount++ % 2) == 0) {
+                String className = reader.getClassName();
+                if (className.endsWith("module-info")) {
+                    return null;
+                }
+                ClassWriter cw = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+                reader.accept(new ClassVisitor(Opcodes.ASM5, cw) {
+                    @Override
+                    public void visit(int i, int i1, String s, String s1, String s2, String[] strings) {
+                        super.visit(i, i1, s + "Changed", s1, s2, strings);
+                    }
+                }, ClassReader.EXPAND_FRAMES);
+                ++changed;
+                return cw;
+            } else {
+                return null;
+            }
+        }
+
+        public int getAmount() {
+            return amount;
+        }
+
+        public int getNumberOfChanged() {
+            return changed;
+        }
+    }
+
+    private static class CustomResourceFileVisitor implements ResourceFileVisitor {
+        private int amount = 0;
+        private int changed = 0;
+
+        @Override
+        public ResourceFile visit(ResourceFile resourceFile) {
+            if ((amount++ % 2) == 0) {
+                ++changed;
+                return new ResourceFile(resourceFile.getPath() + "Changed", resourceFile.getContent());
+            } else {
+                return null;
+            }
+        }
+
+        public int getAmount() {
+            return amount;
+        }
+
+        public int getNumberOfChanged() {
+            return changed;
+        }
+    }
+
+    public class ClassVisitorPlugin extends TestPlugin {
+
+        private final String name;
+        private final Function<AsmPools, AsmPool> getPool;
+        private final CustomClassReaderVisitor classReaderVisitor = new CustomClassReaderVisitor();
+
+        public ClassVisitorPlugin(String name, Function<AsmPools, AsmPool> getPool) {
+            this.name = name;
+            this.getPool = getPool;
+        }
+
+        @Override
+        public void visit() {
+            AsmPool pool = getPool.apply(getPools());
+            pool.visitClassReaders(classReaderVisitor);
+        }
+
+        @Override
+        public void test(Pool in, Pool out) throws Exception {
+            Collection<ModuleData> inClasses = getPool.apply(getPools()).getClasses();
+            if (inClasses.size() != classReaderVisitor.getAmount()) {
+                throw new AssertionError("Testing " + name + ". Number of visited classes. Expected: " +
+                        inClasses.size() + ", got: " + classReaderVisitor.getAmount());
+            }
+            Collection<ModuleData> outClasses = extractClasses(out);
+            int changedClasses = 0;
+            for (ModuleData r : outClasses) {
+                if (r.getPath().endsWith("Changed.class")) {
+                    ++changedClasses;
+                }
+            }
+            if (changedClasses != classReaderVisitor.getNumberOfChanged()) {
+                throw new AssertionError("Testing " + name + ". Changed classes. Expected: " + changedClasses +
+                        ", got: " + classReaderVisitor.getNumberOfChanged());
+            }
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+    }
+
+    public class ResourceVisitorPlugin extends TestPlugin {
+
+        private final String name;
+        private final Function<AsmPools, AsmPool> getPool;
+        private final CustomResourceFileVisitor resourceFileVisitor = new CustomResourceFileVisitor();
+
+        public ResourceVisitorPlugin(String name, Function<AsmPools, AsmPool> getPool) {
+            this.name = name;
+            this.getPool = getPool;
+        }
+
+        @Override
+        public void visit() {
+            AsmPool pool = getPool.apply(getPools());
+            pool.visitResourceFiles(resourceFileVisitor);
+        }
+
+        @Override
+        public void test(Pool in, Pool out) throws Exception {
+            Collection<ModuleData> inResources = getPool.apply(getPools()).getResourceFiles();
+            if (inResources.size() != resourceFileVisitor.getAmount()) {
+                throw new AssertionError("Testing " + name + ". Number of visited resources. Expected: " +
+                        inResources.size() + ", got: " + resourceFileVisitor.getAmount());
+            }
+            Collection<ModuleData> outResources = extractResources(out);
+            int changedClasses = 0;
+            for (ModuleData r : outResources) {
+                if (r.getPath().endsWith("Changed")) {
+                    ++changedClasses;
+                }
+            }
+            if (changedClasses != resourceFileVisitor.getNumberOfChanged()) {
+                throw new AssertionError("Testing " + name + ". Changed classes. Expected: " + changedClasses +
+                        ", got: " + resourceFileVisitor.getNumberOfChanged());
+            }
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/basic/BasicTest.java b/jdk/test/tools/jlink/basic/BasicTest.java
new file mode 100644
index 0000000..4135f4a
--- /dev/null
+++ b/jdk/test/tools/jlink/basic/BasicTest.java
@@ -0,0 +1,131 @@
+/**
+ * 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 Basic test of jlink to create jmods and images
+ * @author Andrei Eremeev
+ * @library /lib/testlibrary
+ * @modules java.base/jdk.internal.module
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build jdk.testlibrary.ProcessTools
+ *        jdk.testlibrary.OutputAnalyzer
+ *        JarUtils CompilerUtils
+ * @run main BasicTest
+ */
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class BasicTest {
+
+    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 classes = Paths.get("classes");
+    private final Path jmods = Paths.get("jmods");
+    private final Path jars = Paths.get("jars");
+
+    public static void main(String[] args) throws Throwable {
+        new BasicTest().run();
+    }
+
+    public void run() throws Throwable {
+        if (Files.notExists(jdkMods)) {
+            return;
+        }
+
+        if (!CompilerUtils.compile(src, classes)) {
+            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);
+
+        Files.delete(jmods.resolve(modName + ".jmod"));
+
+        image = Paths.get("myimage");
+        runJmod(classes.toString(), modName);
+        runJlink(image, modName);
+        execute(image, modName);
+    }
+
+    private void execute(Path image, String moduleName) throws Throwable {
+        String cmd = image.resolve("bin").resolve(moduleName).toString();
+        OutputAnalyzer analyzer;
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            analyzer = ProcessTools.executeProcess("sh.exe", cmd, "1", "2", "3");
+        } else {
+            analyzer = ProcessTools.executeProcess(cmd, "1", "2", "3");
+        }
+        if (analyzer.getExitValue() != 0) {
+            throw new AssertionError("Image invocation failed: rc=" + analyzer.getExitValue());
+        }
+    }
+
+    private void runJlink(Path image, String modName, String... options) {
+        List<String> args = new ArrayList<>();
+        Collections.addAll(args,
+                "--modulepath", jdkMods + File.pathSeparator + jmods,
+                "--addmods", modName,
+                "--output", image.toString());
+        Collections.addAll(args, options);
+        int rc = jdk.tools.jlink.internal.Main.run(args.toArray(new String[args.size()]), new PrintWriter(System.out));
+        if (rc != 0) {
+            throw new AssertionError("Jlink failed: rc = " + rc);
+        }
+    }
+
+    private void runJmod(String cp, String modName) {
+        int rc = jdk.tools.jmod.Main.run(new String[] {
+                "create",
+                "--class-path", cp,
+                "--module-version", "1.0",
+                "--main-class", "jdk.test.Test",
+                jmods.resolve(modName + ".jmod").toString(),
+        }, System.out);
+        if (rc != 0) {
+            throw new AssertionError("Jmod failed: rc = " + rc);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/basic/src/test/jdk/test/Test.java b/jdk/test/tools/jlink/basic/src/test/jdk/test/Test.java
new file mode 100644
index 0000000..e038745
--- /dev/null
+++ b/jdk/test/tools/jlink/basic/src/test/jdk/test/Test.java
@@ -0,0 +1,47 @@
+/**
+ * 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.
+ */
+
+package jdk.test;
+
+import java.lang.reflect.Module;
+import java.lang.reflect.Layer;
+
+public class Test {
+    public static void main(String[] args) {
+        System.out.println(Test.class + " ...");
+        for (String arg: args) {
+            System.out.println(arg);
+        }
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        ClassLoader cl1 = Test.class.getClassLoader();
+        Module testModule = Test.class.getModule();
+        ClassLoader cl2 = Layer.boot().findLoader(testModule.getName());
+
+        if (cl1 != scl)
+            throw new RuntimeException("Not loaded by system class loader");
+        if (cl2 != scl)
+            throw new RuntimeException("Not associated with system class loader");
+
+    }
+}
diff --git a/jdk/test/tools/jlink/basic/src/test/module-info.java b/jdk/test/tools/jlink/basic/src/test/module-info.java
new file mode 100644
index 0000000..1972e2c
--- /dev/null
+++ b/jdk/test/tools/jlink/basic/src/test/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 {
+}
diff --git a/jdk/test/tools/jlink/customplugin/module-info.java b/jdk/test/tools/jlink/customplugin/module-info.java
new file mode 100644
index 0000000..63e2275
--- /dev/null
+++ b/jdk/test/tools/jlink/customplugin/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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 customplugin {
+    requires jdk.jlink;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with plugin.HelloPlugin;
+    provides jdk.tools.jlink.plugin.TransformerPlugin with plugin.CustomPlugin;
+}
diff --git a/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
new file mode 100644
index 0000000..38054ec
--- /dev/null
+++ b/jdk/test/tools/jlink/customplugin/plugin/CustomPlugin.java
@@ -0,0 +1,69 @@
+/*
+ * 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 plugin;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class CustomPlugin implements TransformerPlugin {
+
+    private final static String NAME = "custom-plugin";
+
+    public CustomPlugin() {
+    }
+
+    @Override
+    public void visit(Pool in, Pool out) {
+        in.visit(new Pool.Visitor() {
+            @Override
+            public Pool.ModuleData visit(Pool.ModuleData content) {
+                return content;
+            }
+        }, out);
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public String getDescription() {
+        return NAME + "-description";
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.PROCESSOR);
+        return Collections.unmodifiableSet(set);
+    }
+}
diff --git a/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
new file mode 100644
index 0000000..d06f990
--- /dev/null
+++ b/jdk/test/tools/jlink/customplugin/plugin/HelloPlugin.java
@@ -0,0 +1,76 @@
+/*
+ * 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 plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+/**
+ * Custom plugin
+ */
+public final class HelloPlugin implements TransformerPlugin {
+
+    private static final String OUTPUT_FILE = "customplugin.txt";
+    public static final String NAME = "hello";
+
+    public static boolean called;
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(Pool inResources, Pool outResources) {
+        try {
+            System.out.println("Hello!!!!!!!!!!");
+            File f = new File(OUTPUT_FILE);
+            f.createNewFile();
+            for (ModuleData res : inResources.getContent()) {
+                outResources.add(res);
+            }
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public Set<PluginType> getType() {
+        Set<PluginType> set = new HashSet<>();
+        set.add(CATEGORY.TRANSFORMER);
+        return Collections.unmodifiableSet(set);
+    }
+
+    @Override
+    public String getDescription() {
+        return NAME + "-description";
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/HashesTest.java b/jdk/test/tools/jlink/hashes/HashesTest.java
new file mode 100644
index 0000000..8060bd9
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/HashesTest.java
@@ -0,0 +1,160 @@
+/**
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test the recording and checking of dependency hashes
+ * @author Andrei Eremeev
+ * @library /lib/testlibrary
+ * @modules java.base/jdk.internal.module
+ *          jdk.jlink/jdk.tools.jlink
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @ignore
+ * @build jdk.testlibrary.ProcessTools jdk.testlibrary.OutputAnalyzer CompilerUtils
+ * @run main HashesTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+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.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class HashesTest {
+
+    private final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
+    private final Path stdJmods = jdkHome.resolve("jmods");
+    private final Path testSrc = Paths.get(System.getProperty("test.src"));
+    private final Path modSrc = testSrc.resolve("src");
+    private final Path newModSrc = testSrc.resolve("newsrc");
+    private final Path classes = Paths.get("classes");
+    private final Path jmods = Paths.get("jmods");
+
+    public static void main(String[] args) throws Exception {
+        new HashesTest().run();
+    }
+
+    private void run() throws Exception {
+        if (!Files.exists(stdJmods)) {
+            return;
+        }
+        Files.createDirectories(jmods);
+        Path m1Classes = classes.resolve("m1");
+        Path m2Classes = classes.resolve("m2");
+        Path m3Classes = classes.resolve("not_matched");
+        // build the second module
+        compileClasses(modSrc, m2Classes);
+        runJmod(m2Classes.toString(), m2Classes.getFileName().toString());
+
+        // build the third module
+        compileClasses(modSrc, m3Classes);
+        runJmod(m3Classes.toString(), m3Classes.getFileName().toString());
+
+        compileClasses(modSrc, m1Classes, "-mp", jmods.toString());
+        runJmod(m1Classes.toString(), m1Classes.getFileName().toString(),
+                "--modulepath", jmods.toString(), "--hash-dependencies", "m2");
+        runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
+
+        deleteDirectory(m3Classes);
+        Files.delete(jmods.resolve("not_matched.jmod"));
+
+        // build the new third module
+        compileClasses(newModSrc, m3Classes);
+        runJmod(m3Classes.toString(), m3Classes.getFileName().toString());
+        runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
+
+        deleteDirectory(m2Classes);
+        Files.delete(jmods.resolve("m2.jmod"));
+
+        compileClasses(newModSrc, m2Classes);
+        runJmod(m2Classes.toString(), m2Classes.getFileName().toString());
+
+        runJava(1, "-mp", jmods.toString(), "-m", "m1/org.m1.Main");
+
+        if (jdk.tools.jlink.internal.Main.run(new String[]{
+                "--modulepath", stdJmods.toString() + File.pathSeparator + jmods.toString(),
+                "--addmods", "m1", "--output", "myimage"}, new PrintWriter(System.out)) == 0) {
+            throw new AssertionError("Expected failure. rc = 0");
+        }
+    }
+
+    private void deleteDirectory(Path dir) throws IOException {
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                Files.delete(dir);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    private void runJava(int expectedExitCode, String... args) throws Exception {
+        OutputAnalyzer analyzer = ProcessTools.executeTestJava(args);
+        if (analyzer.getExitValue() != expectedExitCode) {
+            throw new AssertionError("Expected exit code: " + expectedExitCode +
+                    ", got: " + analyzer.getExitValue());
+        }
+    }
+
+    private void compileClasses(Path src, Path output, String... options) throws IOException {
+        List<String> args = new ArrayList<>();
+        Collections.addAll(args, options);
+        Collections.addAll(args, "-d", output.toString());
+        args.add(src.toString());
+        System.out.println("javac options: " + args.stream().collect(Collectors.joining(" ")));
+        if (!CompilerUtils.compile(src.resolve(output.getFileName()), output, options)) {
+            throw new AssertionError("Compilation failure. See log.");
+        }
+    }
+
+    private void runJmod(String cp, String modName, String... options) {
+        List<String> args = new ArrayList<>();
+        args.add("create");
+        Collections.addAll(args, options);
+        Collections.addAll(args, "--class-path", cp,
+                jmods + File.separator + modName + ".jmod");
+        int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out);
+        System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" ")));
+        if (rc != 0) {
+            throw new AssertionError("Jmod failed: rc = " + rc);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java b/jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java
new file mode 100644
index 0000000..4489049
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports org.m2;
+}
diff --git a/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java b/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java
new file mode 100644
index 0000000..b7e0b62
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m2;
+
+public class Util {
+    private Util() { }
+
+    public static String timeOfDay() {
+        return "Time for a beer";
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java b/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java
new file mode 100644
index 0000000..a72988a
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 not_matched {
+    exports org.not_matched;
+}
diff --git a/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java b/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java
new file mode 100644
index 0000000..eb71f80
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.not_matched;
+
+public class Name {
+    private Name() { }
+
+    public static String name() {
+        return "new_module";
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/src/m1/module-info.java b/jdk/test/tools/jlink/hashes/src/m1/module-info.java
new file mode 100644
index 0000000..8268cd8
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/m1/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    requires m2;
+    requires not_matched;
+}
diff --git a/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java b/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java
new file mode 100644
index 0000000..5b1d2f0
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m1;
+
+import org.m2.Util;
+import org.not_matched.Name;
+
+public class Main {
+    public static void main(String[] args) {
+        System.out.println(Util.timeOfDay());
+        System.out.println(Name.name());
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/src/m2/module-info.java b/jdk/test/tools/jlink/hashes/src/m2/module-info.java
new file mode 100644
index 0000000..4489049
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    exports org.m2;
+}
diff --git a/jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java b/jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java
new file mode 100644
index 0000000..b6ae495
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.m2;
+
+public class Util {
+    private Util() { }
+
+    public static String timeOfDay() {
+        return "Time for lunch";
+    }
+}
diff --git a/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java b/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java
new file mode 100644
index 0000000..a72988a
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 not_matched {
+    exports org.not_matched;
+}
diff --git a/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java b/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java
new file mode 100644
index 0000000..d173334
--- /dev/null
+++ b/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.not_matched;
+
+public class Name {
+    private Name() { }
+
+    public static String name() {
+        return "old_module";
+    }
+}
diff --git a/jdk/test/tools/jlink/optimplugin/module-info.java b/jdk/test/tools/jlink/optimplugin/module-info.java
new file mode 100644
index 0000000..87eac36
--- /dev/null
+++ b/jdk/test/tools/jlink/optimplugin/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 optimplugin {
+    exports optim;
+}
diff --git a/jdk/test/tools/jlink/optimplugin/optim/AType.java b/jdk/test/tools/jlink/optimplugin/optim/AType.java
new file mode 100644
index 0000000..6f5e038
--- /dev/null
+++ b/jdk/test/tools/jlink/optimplugin/optim/AType.java
@@ -0,0 +1,28 @@
+/*
+ * 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 optim;
+
+//package class
+class AType {
+}
diff --git a/jdk/test/tools/jlink/optimplugin/optim/ForNameTestCase.java b/jdk/test/tools/jlink/optimplugin/optim/ForNameTestCase.java
new file mode 100644
index 0000000..b3452c3
--- /dev/null
+++ b/jdk/test/tools/jlink/optimplugin/optim/ForNameTestCase.java
@@ -0,0 +1,172 @@
+/*
+ * 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 optim;
+
+public class ForNameTestCase {
+    private static final String EXPECTED = "expected";
+    public static Class<?> forName() {
+        try {
+            Class<?> cl = Class.forName("java.lang.String");
+            return cl;
+        } catch (ClassNotFoundException |
+                IllegalArgumentException |
+                ClassCastException x) {
+            throw new InternalError(x);
+        }
+    }
+
+    public static Class<?> forName0() throws ClassNotFoundException {
+        return Class.forName("java.lang.String");
+    }
+
+    public static Class<?> forName1() throws Exception {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("java.lang.String");
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+        return clazz;
+    }
+
+    public static void forNameException() throws Exception {
+        try {
+            Class.forName("java.lang.String");
+            throw new Exception(EXPECTED);
+        } catch (ClassNotFoundException e) {
+            return;
+        } catch (RuntimeException e) {
+            return;
+        }
+    }
+
+    public static Class<?> forName2() throws Exception {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("java.lang.String");
+            try {
+                throw new Exception("das");
+            } catch (Exception ex) {
+            }
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+        return clazz;
+    }
+
+    public static Class<?> forName3() throws Exception {
+        Class<?> clazz = null;
+        try {
+            return clazz = Class.forName("java.lang.String");
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    public static Class<?> forName4() throws Exception {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("java.lang.String");
+        } catch (ClassNotFoundException e) {
+            return null;
+        } catch (RuntimeException e) {
+            return null;
+        }
+        return clazz;
+    }
+
+    public static Class<?> forName5() {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("java.lang.String");
+        } catch (ClassNotFoundException e) {
+        }
+        int i;
+        try {
+            i = 0;
+        } catch (Exception e) {
+        }
+        return clazz;
+    }
+
+    public static Class<?> forName6() {
+        Class<?> clazz = null;
+        try {
+            return Class.forName("java.lang.String");
+        } catch (ClassNotFoundException e) {
+        }
+
+        try {
+                // This one is removed because no more reachable when
+            // Class.forName is removed
+            int k = 0;
+        } catch (RuntimeException e) {
+        }
+
+        int i;
+        try {
+                // This one is removed because no more reachable when
+            // Class.forName is removed
+            return Class.forName("TOTO");
+        } catch (ClassNotFoundException e) {
+        }
+        try {
+                // This one is removed because no more reachable when
+            // Class.forName is removed
+            return Class.forName("TOTO");
+        } catch (ClassNotFoundException e) {
+        }
+        try {
+                // This one is removed because no more reachable when
+            // Class.forName is removed
+            return Class.forName("TOTO");
+        } catch (ClassNotFoundException e) {
+        }
+        try {
+                // This one is removed because no more reachable when
+            // Class.forName is removed
+            return Class.forName("TOTO");
+        } catch (ClassNotFoundException e) {
+        }
+        return clazz;
+    }
+
+    public static Class<?> forName7() {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("optim.AType");
+        } catch (ClassNotFoundException e) {
+        }
+        return clazz;
+    }
+
+    public static Class<?> negativeforName() {
+        Class<?> clazz = null;
+        try {
+            clazz = Class.forName("jdk.internal.jimage.BasicImageReader");
+        } catch (ClassNotFoundException e) {
+        }
+        return clazz;
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/CompressIndexesTest.java b/jdk/test/tools/jlink/plugins/CompressIndexesTest.java
new file mode 100644
index 0000000..d13807e
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/CompressIndexesTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test CompressIndexes
+ * @author Jean-Francois Denise
+ * @modules java.base/jdk.internal.jimage.decompressor
+ * @run main CompressIndexesTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.internal.jimage.decompressor.CompressIndexes;
+
+public class CompressIndexesTest {
+
+    public static void main(String[] args) throws IOException {
+        new CompressIndexesTest().test();
+    }
+
+    public void test() throws IOException {
+        int[] data = {
+                // compressed length 1
+                0x00000000,
+                0x00000001,
+                0x0000000F,
+                0x0000001F,
+                // compressed length 2
+                0x0000002F,
+                0x00000100,
+                0x00001FFF,
+                // compressed length 3
+                0x00002FFF,
+                0x00010000,
+                0x001FFFFF,
+                // compressed length 4
+                0x00200000,
+                0x01000000,
+                Integer.MAX_VALUE
+        };
+        int[] intervals = {4, 7, 10, data.length};
+        List<byte[]> arrays = new ArrayList<>();
+        int length = 0;
+        int begin = 0;
+        for (int interval : intervals) {
+            ++length;
+            for (int j = begin; j < interval; ++j) {
+                arrays.add(check(data[j], length));
+            }
+            begin = interval;
+        }
+
+        int totalLength = arrays.stream().mapToInt(b -> b.length).sum();
+        ByteBuffer all = ByteBuffer.allocate(totalLength);
+        arrays.forEach(all::put);
+        byte[] flow = all.array();
+        check(flow, arrays);
+        System.err.println(arrays.size() * 4 + " compressed in " + flow.length
+                + " gain of " + (100 - ((flow.length * 100) / (arrays.size() * 4))) + "%");
+        try (DataInputStream is = new DataInputStream(new ByteArrayInputStream(flow))) {
+            int index = 0;
+            while (is.available() > 0) {
+                int d = CompressIndexes.readInt(is);
+                if (data[index] != d) {
+                    throw new AssertionError("Expected: " + data[index] + ", got: " + d);
+                }
+                ++index;
+            }
+        }
+    }
+
+    private void check(byte[] flow, List<byte[]> arrays) {
+        List<Integer> d = CompressIndexes.decompressFlow(flow);
+        List<Integer> dd = new ArrayList<>();
+        for (byte[] b : arrays) {
+            int i = CompressIndexes.decompress(b, 0);
+            dd.add(i);
+        }
+        if (!d.equals(dd)) {
+            System.err.println(dd);
+            System.err.println(d);
+            throw new AssertionError("Invalid flow " + d);
+        } else {
+            System.err.println("OK for flow");
+        }
+    }
+
+    private byte[] check(int val, int size) {
+        byte[] c = CompressIndexes.compress(val);
+        if (c.length != size) {
+            throw new AssertionError("Invalid compression size " + c.length);
+        }
+        int d = CompressIndexes.decompress(c, 0);
+        if (val != d) {
+            throw new AssertionError("Invalid " + d);
+        } else {
+            System.err.println("Ok for " + val);
+        }
+        return c;
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java
new file mode 100644
index 0000000..cd01b93
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test zip compressor
+ * @author Jean-Francois Denise
+ * @modules java.base/jdk.internal.jimage.decompressor
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main CompressorPluginTest
+ */
+import java.net.URI;
+import java.nio.ByteOrder;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.internal.jimage.decompressor.ResourceDecompressor;
+import jdk.internal.jimage.decompressor.ResourceDecompressorFactory;
+import jdk.internal.jimage.decompressor.StringSharingDecompressorFactory;
+import jdk.internal.jimage.decompressor.ZipDecompressorFactory;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
+import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
+import jdk.tools.jlink.internal.plugins.ZipPlugin;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class CompressorPluginTest {
+
+    private static int strID = 1;
+
+    public static void main(String[] args) throws Exception {
+        new CompressorPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        FileSystem fs;
+        try {
+            fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+        } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
+            System.err.println("Not an image build, test skipped.");
+            return;
+        }
+        Path javabase = fs.getPath("/modules/java.base");
+
+        checkCompress(gatherResources(javabase), new ZipPlugin(), null,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory()
+                });
+
+        Pool classes = gatherClasses(javabase);
+        // compress = String sharing
+        checkCompress(classes, new StringSharingPlugin(), null,
+                new ResourceDecompressorFactory[]{
+                    new StringSharingDecompressorFactory()});
+
+        // compress == ZIP + String sharing
+        Properties options = new Properties();
+        options.setProperty(ZipPlugin.NAME, "");
+        checkCompress(classes, new DefaultCompressPlugin(), options,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory(),
+                    new StringSharingDecompressorFactory()
+                });
+
+        // compress == ZIP + String sharing + filter
+        options.setProperty(DefaultCompressPlugin.FILTER,
+                "*Exception.class,^*IOException.class");
+        checkCompress(classes, new DefaultCompressPlugin(), options,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory(),
+                    new StringSharingDecompressorFactory()
+                }, Collections.singletonList(".*Exception.class"),
+                Collections.singletonList(".*IOException.class"));
+
+        // compress level 1 == ZIP
+        Properties options1 = new Properties();
+        options1.setProperty(DefaultCompressPlugin.NAME,
+                "1");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options1,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory()
+                });
+
+        // compress level 1 == ZIP
+        options1.setProperty(DefaultCompressPlugin.FILTER,
+                "*Exception.class,^*IOException.class");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options1,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory()
+                }, Collections.singletonList(".*Exception.class"),
+                Collections.singletonList(".*IOException.class"));
+
+        // compress level 2 == ZIP + String sharing
+        Properties options2 = new Properties();
+        options2.setProperty(DefaultCompressPlugin.NAME,
+                "2");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options2,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory(),
+                    new StringSharingDecompressorFactory()
+                });
+
+        // compress level 2 == ZIP + String sharing + filter
+        options2.setProperty(DefaultCompressPlugin.FILTER,
+                "*Exception.class,^*IOException.class");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options2,
+                new ResourceDecompressorFactory[]{
+                    new ZipDecompressorFactory(),
+                    new StringSharingDecompressorFactory()
+                }, Collections.singletonList(".*Exception.class"),
+                Collections.singletonList(".*IOException.class"));
+
+        // compress level 0 == String sharing
+        Properties options0 = new Properties();
+        options0.setProperty(DefaultCompressPlugin.NAME, "0");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options0,
+                new ResourceDecompressorFactory[]{
+                    new StringSharingDecompressorFactory()
+                });
+
+        // compress level 0 == String sharing + filter
+        options0.setProperty(DefaultCompressPlugin.FILTER,
+                "*Exception.class,^*IOException.class");
+        checkCompress(classes, new DefaultCompressPlugin(),
+                options0,
+                new ResourceDecompressorFactory[]{
+                    new StringSharingDecompressorFactory()
+                }, Collections.singletonList(".*Exception.class"),
+                Collections.singletonList(".*IOException.class"));
+    }
+
+    private Pool gatherResources(Path module) throws Exception {
+        Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+        try (Stream<Path> stream = Files.walk(module)) {
+            for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
+                Path p = iterator.next();
+                if (Files.isRegularFile(p)) {
+                    byte[] content = Files.readAllBytes(p);
+                    pool.add(Pool.newResource(p.toString(), content));
+                }
+            }
+        }
+        return pool;
+    }
+
+    private Pool gatherClasses(Path module) throws Exception {
+        Pool pool = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+
+            @Override
+            public int addString(String str) {
+                return -1;
+            }
+
+            @Override
+            public String getString(int id) {
+                return null;
+            }
+        });
+        try (Stream<Path> stream = Files.walk(module)) {
+            for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
+                Path p = iterator.next();
+                if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
+                    byte[] content = Files.readAllBytes(p);
+                    pool.add(Pool.newResource(p.toString(), content));
+                }
+            }
+        }
+        return pool;
+    }
+
+    private void checkCompress(Pool resources, Plugin prov,
+            Properties config,
+            ResourceDecompressorFactory[] factories) throws Exception {
+        checkCompress(resources, prov, config, factories, Collections.emptyList(), Collections.emptyList());
+    }
+
+    private void checkCompress(Pool resources, Plugin prov,
+            Properties config,
+            ResourceDecompressorFactory[] factories,
+            List<String> includes,
+            List<String> excludes) throws Exception {
+        long original = 0;
+        long compressed = 0;
+        for (ModuleData resource : resources.getContent()) {
+            List<Pattern> includesPatterns = includes.stream()
+                    .map(Pattern::compile)
+                    .collect(Collectors.toList());
+            List<Pattern> excludesPatterns = excludes.stream()
+                    .map(Pattern::compile)
+                    .collect(Collectors.toList());
+
+            Map<String, String> props = new HashMap<>();
+            if (config != null) {
+                for (String p : config.stringPropertyNames()) {
+                    props.put(p, config.getProperty(p));
+                }
+            }
+            prov.configure(props);
+            final Map<Integer, String> strings = new HashMap<>();
+            PoolImpl inputResources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+                @Override
+                public int addString(String str) {
+                    int id = strID;
+                    strID += 1;
+                    strings.put(id, str);
+                    return id;
+                }
+
+                @Override
+                public String getString(int id) {
+                    return strings.get(id);
+                }
+            });
+            inputResources.add(resource);
+            Pool compressedResources = applyCompressor(prov, inputResources, resource, includesPatterns, excludesPatterns);
+            original += resource.getLength();
+            compressed += compressedResources.get(resource.getPath()).getLength();
+            applyDecompressors(factories, inputResources, compressedResources, strings, includesPatterns, excludesPatterns);
+        }
+        String compressors = Stream.of(factories)
+                .map(Object::getClass)
+                .map(Class::getSimpleName)
+                .collect(Collectors.joining(", "));
+        String size = "Compressed size: " + compressed + ", original size: " + original;
+        System.out.println("Used " + compressors + ". " + size);
+        if (original <= compressed) {
+            throw new AssertionError("java.base not compressed.");
+        }
+    }
+
+    private Pool applyCompressor(Plugin plugin,
+            PoolImpl inputResources,
+            ModuleData res,
+            List<Pattern> includesPatterns,
+            List<Pattern> excludesPatterns) throws Exception {
+        TransformerPlugin compressor = (TransformerPlugin) plugin;
+        Pool compressedPool = new PoolImpl(ByteOrder.nativeOrder(), inputResources.getStringTable());
+        compressor.visit(inputResources, compressedPool);
+        String path = res.getPath();
+        ModuleData compressed = compressedPool.get(path);
+        CompressedResourceHeader header
+                = CompressedResourceHeader.readFromResource(ByteOrder.nativeOrder(), compressed.getBytes());
+        if (isIncluded(includesPatterns, excludesPatterns, path)) {
+            if (header == null) {
+                throw new AssertionError("Path should be compressed: " + path);
+            }
+            if (header.getDecompressorNameOffset() == 0) {
+                throw new AssertionError("Invalid plugin offset "
+                        + header.getDecompressorNameOffset());
+            }
+            if (header.getResourceSize() <= 0) {
+                throw new AssertionError("Invalid compressed size "
+                        + header.getResourceSize());
+            }
+        } else if (header != null) {
+            throw new AssertionError("Path should not be compressed: " + path);
+        }
+        return compressedPool;
+    }
+
+    private void applyDecompressors(ResourceDecompressorFactory[] decompressors,
+            Pool inputResources,
+            Pool compressedResources,
+            Map<Integer, String> strings,
+            List<Pattern> includesPatterns,
+            List<Pattern> excludesPatterns) throws Exception {
+        for (ModuleData compressed : compressedResources.getContent()) {
+            CompressedResourceHeader header = CompressedResourceHeader.readFromResource(
+                    ByteOrder.nativeOrder(), compressed.getBytes());
+            String path = compressed.getPath();
+            ModuleData orig = inputResources.get(path);
+            if (!isIncluded(includesPatterns, excludesPatterns, path)) {
+                continue;
+            }
+            byte[] decompressed = compressed.getBytes();
+            for (ResourceDecompressorFactory factory : decompressors) {
+                ResourceDecompressor decompressor = factory.newDecompressor(new Properties());
+                decompressed = decompressor.decompress(
+                        strings::get, decompressed,
+                        CompressedResourceHeader.getSize(), header.getUncompressedSize());
+            }
+
+            if (decompressed.length != orig.getLength()) {
+                throw new AssertionError("Invalid uncompressed size "
+                        + header.getUncompressedSize());
+            }
+            byte[] origContent = orig.getBytes();
+            for (int i = 0; i < decompressed.length; i++) {
+                if (decompressed[i] != origContent[i]) {
+                    throw new AssertionError("Decompressed and original differ at index " + i);
+                }
+            }
+        }
+    }
+
+    private boolean isIncluded(List<Pattern> includesPatterns, List<Pattern> excludesPatterns, String path) {
+        return !excludesPatterns.stream().anyMatch((pattern) -> pattern.matcher(path).matches())
+                && (includesPatterns.isEmpty()
+                || includesPatterns.stream().anyMatch((pattern) -> pattern.matcher(path).matches()));
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
new file mode 100644
index 0000000..cde83aa
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test exclude files plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main ExcludeFilesPluginTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+
+import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class ExcludeFilesPluginTest {
+    public static void main(String[] args) throws Exception {
+        new ExcludeFilesPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        checkFiles("*.jcov", "num/toto.jcov", "", true);
+        checkFiles("*.jcov", "/toto.jcov", "", true);
+        checkFiles("*.jcov", "toto.jcov/tutu/tata", "", false);
+        checkFiles("/java.base/*.jcov", "toto.jcov", "java.base", true);
+        checkFiles("/java.base/toto.jcov", "iti.jcov", "t/java.base", false);
+        checkFiles("/java.base/*/toto.jcov", "toto.jcov", "java.base", false);
+        checkFiles("/java.base/*/toto.jcov", "tutu/toto.jcov", "java.base", true);
+        checkFiles("*/java.base/*/toto.jcov", "java.base/tutu/toto.jcov", "/tutu", true);
+
+        checkFiles("/*$*.properties", "tutu/Toto$Titi.properties", "java.base", true);
+        checkFiles("*$*.properties", "tutu/Toto$Titi.properties", "java.base", true);
+
+        // Excluded files list in a file
+        File order = new File("files.exc");
+        order.createNewFile();
+        Files.write(order.toPath(), "*.jcov".getBytes());
+        checkFiles(order.getAbsolutePath(), "/num/toto.jcov", "", true);
+    }
+
+    public void checkFiles(String s, String sample, String module, boolean exclude) throws Exception {
+        Map<String, String> prop = new HashMap<>();
+        prop.put(ExcludeFilesPlugin.NAME, s);
+        ExcludeFilesPlugin fplug = new ExcludeFilesPlugin();
+        fplug.configure(prop);
+        PoolImpl files = new PoolImpl();
+        PoolImpl fresult = new PoolImpl();
+        ModuleData f = Pool.newImageFile(module, "/" + module + "/" + sample,
+                ModuleDataType.CONFIG, new ByteArrayInputStream(new byte[0]), 0);
+        files.add(f);
+
+        fplug.visit(files, fresult);
+
+        if (exclude) {
+            if (fresult.getContent().contains(f)) {
+                throw new Exception(sample + " should be excluded by " + s);
+            }
+        } else {
+            if (!fresult.getContent().contains(f)) {
+                throw new Exception(sample + " shouldn't be excluded by " + s);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java
new file mode 100644
index 0000000..0f50807
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test exclude plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main ExcludePluginTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+
+import jdk.tools.jlink.internal.plugins.ExcludePlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+
+public class ExcludePluginTest {
+
+    public static void main(String[] args) throws Exception {
+        new ExcludePluginTest().test();
+    }
+
+    public void test() throws Exception {
+        check("*.jcov", "/num/toto.jcov", true);
+        check("*.jcov", "//toto.jcov", true);
+        check("*.jcov", "/toto.jcov/tutu/tata", false);
+        check("/java.base/*.jcov", "/java.base/toto.jcov", true);
+        check("/java.base/toto.jcov", "t/java.base/iti.jcov", false);
+        check("/java.base/*/toto.jcov", "/java.base/toto.jcov", false);
+        check("/java.base/*/toto.jcov", "/java.base/tutu/toto.jcov", true);
+        check("*/java.base/*/toto.jcov", "/tutu/java.base/tutu/toto.jcov", true);
+        check("*/META-INF/*", "/META-INF/services/  MyProvider ", false);
+        check("*/META-INF/*", "/META-INF/services/MyProvider", false);
+        check("*/META-INF", " /META-INF/services/MyProvider", false);
+        check("*/META-INF/*", "/java.base//META-INF/services/MyProvider", true);
+        check("/java.base/*/Toto$Titi.class", "/java.base/tutu/Toto$Titi.class", true);
+        check("/*$*.class", "/java.base/tutu/Toto$Titi.class", true);
+        check("*$*.class", "/java.base/tutu/Toto$Titi.class", true);
+
+        // Excluded resource list in a file
+        File order = new File("resources.exc");
+        order.createNewFile();
+        Files.write(order.toPath(), "*.jcov".getBytes());
+        check(order.getAbsolutePath(), "/num/toto.jcov", true);
+    }
+
+    public void check(String s, String sample, boolean exclude) throws Exception {
+        Map<String, String> prop = new HashMap<>();
+        prop.put(ExcludePlugin.NAME, s);
+        ExcludePlugin excludePlugin = new ExcludePlugin();
+        excludePlugin.configure(prop);
+        Pool resources = new PoolImpl();
+        ModuleData resource = Pool.newResource(sample, new byte[0]);
+        resources.add(resource);
+        Pool result = new PoolImpl();
+        excludePlugin.visit(resources, result);
+        if (exclude) {
+            if (result.getContent().contains(resource)) {
+                throw new AssertionError(sample + " should be excluded by " + s);
+            }
+        } else {
+            if (!result.getContent().contains(resource)) {
+                throw new AssertionError(sample + " shouldn't be excluded by " + s);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
new file mode 100644
index 0000000..701368c
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Test exclude VM plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main ExcludeVMPluginTest
+ */
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+
+import jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class ExcludeVMPluginTest {
+
+    private static final String TAG = "# orig in test\n";
+
+    private static final String[] ARCHITECTURES = {"/", "/amd64/", "/i386/", "/arm/",
+        "/aarch64/", "/toto/"};
+
+    private static final String[] CLIENT = {"client/" + jvmlib(),};
+    private static final String[] SERVER = {"server/" + jvmlib()};
+    private static final String[] MINIMAL = {"minimal/" + jvmlib()};
+    private static final String[] ALL = {CLIENT[0], SERVER[0], MINIMAL[0]};
+    private static final String JVM_CFG_ALL = TAG + "-server KNOWN\n-client KNOWN\n-minimal KNOWN\n";
+    private static final String JVM_CFG_CLIENT = TAG + "-client KNOWN\n";
+    private static final String JVM_CFG_SERVER = TAG + "-server KNOWN\n";
+    private static final String JVM_CFG_SERVER_ALIAS_OTHERS = TAG + "-server KNOWN\n-client ALIASED_TO -server\n-minimal ALIASED_TO -server\n";
+    private static final String JVM_CFG_CLIENT_ALIAS_OTHERS = TAG + "-client KNOWN\n-server ALIASED_TO -client\n-minimal ALIASED_TO -client\n";
+    private static final String JVM_CFG_MINIMAL_ALIAS_OTHERS = TAG + "-minimal KNOWN\n-server ALIASED_TO -minimal\n-client ALIASED_TO -minimal\n";
+    private static final String JVM_CFG_MINIMAL = TAG + "-minimal KNOWN\n";
+
+    public static void main(String[] args) throws Exception {
+        new ExcludeVMPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        boolean failed = false;
+
+        try {
+            checkVM("toto", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+
+        checkVM("all", ALL, JVM_CFG_ALL, ALL, JVM_CFG_ALL);
+        checkVM("all", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
+        checkVM("all", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
+        checkVM("all", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
+
+        checkVM("server", ALL, JVM_CFG_ALL, SERVER, JVM_CFG_SERVER_ALIAS_OTHERS);
+        checkVM("server", SERVER, JVM_CFG_SERVER, SERVER, JVM_CFG_SERVER);
+        try {
+            checkVM("server", CLIENT, JVM_CFG_CLIENT, SERVER, JVM_CFG_SERVER);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+        try {
+            checkVM("server", MINIMAL, JVM_CFG_MINIMAL, SERVER, JVM_CFG_SERVER);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+
+        checkVM("client", ALL, JVM_CFG_ALL, CLIENT, JVM_CFG_CLIENT_ALIAS_OTHERS);
+        checkVM("client", CLIENT, JVM_CFG_CLIENT, CLIENT, JVM_CFG_CLIENT);
+        try {
+            checkVM("client", SERVER, JVM_CFG_SERVER, CLIENT, JVM_CFG_CLIENT);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+        try {
+            checkVM("client", MINIMAL, JVM_CFG_MINIMAL, CLIENT, JVM_CFG_CLIENT);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+
+        checkVM("minimal", ALL, JVM_CFG_ALL, MINIMAL, JVM_CFG_MINIMAL_ALIAS_OTHERS);
+        checkVM("minimal", MINIMAL, JVM_CFG_MINIMAL, MINIMAL, JVM_CFG_MINIMAL);
+        try {
+            checkVM("minimal", SERVER, JVM_CFG_SERVER, MINIMAL, JVM_CFG_MINIMAL);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+        try {
+            checkVM("minimal", CLIENT, JVM_CFG_CLIENT, MINIMAL, JVM_CFG_MINIMAL);
+            failed = true;
+            throw new Exception("Should have failed");
+        } catch (Exception ex) {
+            if (failed) {
+                throw ex;
+            }
+        }
+
+    }
+
+    public void checkVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
+
+        for (String arch : ARCHITECTURES) {
+            String[] winput = new String[input.length];
+            String[] woutput = new String[expectedOutput.length];
+            for (int i = 0; i < input.length; i++) {
+                winput[i] = "/java.base/native" + arch + input[i];
+            }
+            for (int i = 0; i < expectedOutput.length; i++) {
+                woutput[i] = "/java.base/native" + arch + expectedOutput[i];
+            }
+            doCheckVM(vm, winput, jvmcfg, woutput, expectdJvmCfg);
+        }
+    }
+
+    private void doCheckVM(String vm, String[] input, String jvmcfg, String[] expectedOutput, String expectdJvmCfg) throws Exception {
+        // Create a pool with jvm.cfg and the input paths.
+        byte[] jvmcfgContent = jvmcfg.getBytes();
+        Pool pool = new PoolImpl();
+        pool.add(Pool.newImageFile("java.base", "/java.base/native/jvm.cfg",
+                ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length));
+        for (String in : input) {
+            pool.add(Pool.newImageFile("java.base", in,
+                    ModuleDataType.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0));
+        }
+        Pool out = new PoolImpl();
+
+        TransformerPlugin p = new ExcludeVMPlugin();
+        Map<String, String> config = new HashMap<>();
+        if (vm != null) {
+            config.put(ExcludeVMPlugin.NAME, vm);
+        }
+        p.configure(config);
+        p.visit(pool, out);
+
+        String newContent = new String(out.get("/java.base/native/jvm.cfg").stream().readAllBytes());
+
+        if (!expectdJvmCfg.equals(newContent)) {
+            throw new Exception("Got content " + newContent + " expected " + expectdJvmCfg);
+        }
+
+        if (out.getContent().size() != (expectedOutput.length + 1)) {
+            for (ModuleData m : out.getContent()) {
+                System.err.println(m.getPath());
+            }
+            throw new Exception("Invalid output size " + out.getContent().size() + " expected " + (expectedOutput.length + 1));
+        }
+
+        for (ModuleData md : out.getContent()) {
+            if (md.getPath().equals("/java.base/native/jvm.cfg")) {
+                continue;
+            }
+            boolean contained = false;
+            for (String o : expectedOutput) {
+                if (md.getPath().equals(o)) {
+                    contained = true;
+                    break;
+                }
+            }
+            if (!contained) {
+                throw new Exception(md.getPath() + " not expected");
+            }
+        }
+
+    }
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").startsWith("Windows");
+    }
+
+    private static boolean isMac() {
+        return System.getProperty("os.name").startsWith("Mac OS");
+    }
+
+    private static String jvmlib() {
+        String lib = "libjvm.so";
+        if (isWindows()) {
+            lib = "jvm.dll";
+        } else if (isMac()) {
+            lib = "libjvm.dylib";
+        }
+        return lib;
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
new file mode 100644
index 0000000..69388e7
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test files copy plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main FileCopierPluginTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+
+import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.Pool.ModuleDataType;
+
+public class FileCopierPluginTest {
+
+    public static void main(String[] args) throws Exception {
+        new FileCopierPluginTest().test();
+    }
+
+    /**
+     * 3 cases - Absolute, no target ==> copy in image root dir - Absolute and
+     * target ==> copy in image root dir/target - Relative ==> copy from JDK
+     * home dir.
+     *
+     * @throws Exception
+     */
+    public void test() throws Exception {
+        FileCopierPlugin plug = new FileCopierPlugin();
+        String content = "You \n should \n be \bthere.\n";
+        String name = "sample.txt";
+        File src = new File("src");
+        src.mkdir();
+        // Need a fake bin
+        File bin = new File("bin");
+        bin.mkdir();
+
+        File txt = new File(src, name);
+        txt.createNewFile();
+
+        String target = "target" + File.separator + name;
+        Files.write(txt.toPath(), content.getBytes());
+        File lic = new File(System.getProperty("java.home"), "LICENSE");
+        StringBuilder builder = new StringBuilder();
+        int expected = lic.exists() ? 4 : 3;
+        if (lic.exists()) {
+            builder.append("LICENSE,");
+        }
+        builder.append(txt.getAbsolutePath()+",");
+        builder.append(txt.getAbsolutePath() + "=" + target+",");
+        builder.append(src.getAbsolutePath() + "=src2");
+
+        Map<String, String> conf = new HashMap<>();
+        conf.put(FileCopierPlugin.NAME, builder.toString());
+        plug.configure(conf);
+        Pool pool = new PoolImpl();
+        plug.visit(new PoolImpl(), pool);
+        if (pool.getContent().size() != expected) {
+            throw new AssertionError("Wrong number of added files");
+        }
+        for (ModuleData f : pool.getContent()) {
+            if (!f.getType().equals(ModuleDataType.OTHER)) {
+                throw new AssertionError("Invalid type " + f.getType()
+                        + " for file " + f.getPath());
+            }
+            if (f.stream() == null) {
+                throw new AssertionError("Null stream for file " + f.getPath());
+            }
+
+        }
+        Path root = new File(".").toPath();
+        DefaultImageBuilder imgbuilder = new DefaultImageBuilder(false,
+                root);
+        imgbuilder.storeFiles(pool, "");
+
+        if (lic.exists()) {
+            File license = new File(root.toFile(), "LICENSE");
+            if (!license.exists() || license.length() == 0) {
+                throw new AssertionError("Invalide license file "
+                        + license.getAbsoluteFile());
+            }
+        }
+
+        File sample1 = new File(root.toFile(), txt.getName());
+        if (!sample1.exists() || sample1.length() == 0) {
+            throw new AssertionError("Invalide sample1 file "
+                    + sample1.getAbsoluteFile());
+        }
+        if (!new String(Files.readAllBytes(sample1.toPath())).equals(content)) {
+            throw new AssertionError("Invalid Content in sample1");
+        }
+
+        File sample2 = new File(root.toFile(), target);
+        if (!sample2.exists() || sample2.length() == 0) {
+            throw new AssertionError("Invalide sample2 file "
+                    + sample2.getAbsoluteFile());
+        }
+        if (!new String(Files.readAllBytes(sample2.toPath())).equals(content)) {
+            throw new AssertionError("Invalid Content in sample2");
+        }
+
+        File src2 = new File(root.toFile(), "src2");
+        if (!src2.exists() || src2.list().length != 1) {
+            throw new AssertionError("Invalide src2 dir "
+                    + src2.getAbsoluteFile());
+        }
+        File f = src2.listFiles()[0];
+        if (!f.getName().equals(txt.getName())) {
+            throw new AssertionError("Invalide file name in src2 dir "
+                    + f.getAbsoluteFile());
+        }
+        if (!new String(Files.readAllBytes(f.toPath())).equals(content)) {
+            throw new AssertionError("Invalid Content in src2 dir");
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/GetAvailableLocales.java b/jdk/test/tools/jlink/plugins/GetAvailableLocales.java
new file mode 100644
index 0000000..5752f01
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/GetAvailableLocales.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.Arrays;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+class GetAvailableLocales {
+
+    public static void main(String[] args) {
+        String availableLocales = Arrays.stream(Locale.getAvailableLocales())
+            .map(l -> l.toString())
+            .sorted()
+            .collect(Collectors.joining(" "));
+
+        if (!availableLocales.equals(args[0])) {
+            throw new RuntimeException("Available locales are not equal to the expected ones.\n" +
+                "Expected: " + args[0] + "\n" +
+                "Actual:   " + availableLocales);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java
new file mode 100644
index 0000000..b29c30f
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Layer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.internal.PluginRepository;
+import tests.Helper;
+import tests.JImageGenerator;
+import tests.JImageValidator;
+
+/*
+ * @test
+ * @summary IncludeLocalesPlugin tests
+ * @author Naoto Sato
+ * @library ../../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @build tools.jlink.plugins.GetAvailableLocales
+ * @run main/othervm -verbose:gc -Xmx1g IncludeLocalesPluginTest
+ */
+public class IncludeLocalesPluginTest {
+
+    private final static String moduleName = "IncludeLocalesTest";
+    private static Helper helper;
+    private final static int INCLUDE_LOCALES_OPTION = 0;
+    private final static int EXPECTED_LOCATIONS     = 1;
+    private final static int UNEXPECTED_PATHS       = 2;
+    private final static int AVAILABLE_LOCALES      = 3;
+
+    private final static Object[][] testData = {
+        // without --include-locales option: should include all locales
+        {
+            "",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
+            List.of(),
+            " af af_NA af_ZA agq agq_CM ak ak_GH am am_ET ar ar_001 ar_AE ar_BH " +
+            "ar_DJ ar_DZ ar_EG ar_EH ar_ER ar_IL ar_IQ ar_JO ar_KM ar_KW ar_LB " +
+            "ar_LY ar_MA ar_MR ar_OM ar_PS ar_QA ar_SA ar_SD ar_SO ar_SS ar_SY " +
+            "ar_TD ar_TN ar_YE as as_IN asa asa_TZ ast ast_ES az az_AZ_#Cyrl " +
+            "az_AZ_#Latn az__#Cyrl az__#Latn bas bas_CM be be_BY bem bem_ZM bez " +
+            "bez_TZ bg bg_BG bm bm_ML_#Latn bm__#Latn bn bn_BD bn_IN bo bo_CN " +
+            "bo_IN br br_FR brx brx_IN bs bs_BA_#Cyrl bs_BA_#Latn bs__#Cyrl " +
+            "bs__#Latn ca ca_AD ca_ES ca_ES_VALENCIA ca_FR ca_IT cgg cgg_UG chr " +
+            "chr_US cs cs_CZ cy cy_GB da da_DK da_GL dav dav_KE de de_AT de_BE " +
+            "de_CH de_DE de_GR de_LI de_LU dje dje_NE dsb dsb_DE dua dua_CM dyo " +
+            "dyo_SN dz dz_BT ebu ebu_KE ee ee_GH ee_TG el el_CY el_GR en en_001 " +
+            "en_150 en_AG en_AI en_AS en_AU en_BB en_BE en_BM en_BS en_BW en_BZ " +
+            "en_CA en_CC en_CK en_CM en_CX en_DG en_DM en_ER en_FJ en_FK en_FM " +
+            "en_GB en_GD en_GG en_GH en_GI en_GM en_GU en_GY en_HK en_IE en_IM " +
+            "en_IN en_IO en_JE en_JM en_KE en_KI en_KN en_KY en_LC en_LR en_LS " +
+            "en_MG en_MH en_MO en_MP en_MS en_MT en_MU en_MW en_MY en_NA en_NF " +
+            "en_NG en_NR en_NU en_NZ en_PG en_PH en_PK en_PN en_PR en_PW en_RW " +
+            "en_SB en_SC en_SD en_SG en_SH en_SL en_SS en_SX en_SZ en_TC en_TK " +
+            "en_TO en_TT en_TV en_TZ en_UG en_UM en_US en_US_POSIX en_VC en_VG " +
+            "en_VI en_VU en_WS en_ZA en_ZM en_ZW eo eo_001 es es_419 es_AR es_BO " +
+            "es_CL es_CO es_CR es_CU es_DO es_EA es_EC es_ES es_GQ es_GT es_HN " +
+            "es_IC es_MX es_NI es_PA es_PE es_PH es_PR es_PY es_SV es_US es_UY " +
+            "es_VE et et_EE eu eu_ES ewo ewo_CM fa fa_AF fa_IR ff ff_CM ff_GN " +
+            "ff_MR ff_SN fi fi_FI fil fil_PH fo fo_FO fr fr_BE fr_BF fr_BI fr_BJ " +
+            "fr_BL fr_CA fr_CD fr_CF fr_CG fr_CH fr_CI fr_CM fr_DJ fr_DZ fr_FR " +
+            "fr_GA fr_GF fr_GN fr_GP fr_GQ fr_HT fr_KM fr_LU fr_MA fr_MC fr_MF " +
+            "fr_MG fr_ML fr_MQ fr_MR fr_MU fr_NC fr_NE fr_PF fr_PM fr_RE fr_RW " +
+            "fr_SC fr_SN fr_SY fr_TD fr_TG fr_TN fr_VU fr_WF fr_YT fur fur_IT fy " +
+            "fy_NL ga ga_IE gd gd_GB gl gl_ES gsw gsw_CH gsw_FR gsw_LI gu gu_IN " +
+            "guz guz_KE gv gv_IM ha ha_GH_#Latn ha_NE_#Latn ha_NG_#Latn ha__#Latn " +
+            "haw haw_US hi hi_IN hr hr_BA hr_HR hsb hsb_DE hu hu_HU hy hy_AM ig " +
+            "ig_NG ii ii_CN in in_ID is is_IS it it_CH it_IT it_SM iw iw_IL ja " +
+            "ja_JP ja_JP_JP_#u-ca-japanese jgo jgo_CM ji ji_001 jmc jmc_TZ ka " +
+            "ka_GE kab kab_DZ kam kam_KE kde kde_TZ kea kea_CV khq khq_ML ki " +
+            "ki_KE kk kk_KZ_#Cyrl kk__#Cyrl kkj kkj_CM kl kl_GL kln kln_KE km " +
+            "km_KH kn kn_IN ko ko_KP ko_KR kok kok_IN ks ks_IN_#Arab ks__#Arab " +
+            "ksb ksb_TZ ksf ksf_CM ksh ksh_DE kw kw_GB ky ky_KG_#Cyrl ky__#Cyrl " +
+            "lag lag_TZ lb lb_LU lg lg_UG lkt lkt_US ln ln_AO ln_CD ln_CF ln_CG " +
+            "lo lo_LA lt lt_LT lu lu_CD luo luo_KE luy luy_KE lv lv_LV mas " +
+            "mas_KE mas_TZ mer mer_KE mfe mfe_MU mg mg_MG mgh mgh_MZ mgo mgo_CM " +
+            "mk mk_MK ml ml_IN mn mn_MN_#Cyrl mn__#Cyrl mr mr_IN ms ms_BN_#Latn " +
+            "ms_MY ms_MY_#Latn ms_SG_#Latn ms__#Latn mt mt_MT mua mua_CM my " +
+            "my_MM naq naq_NA nb nb_NO nb_SJ nd nd_ZW ne ne_IN ne_NP nl nl_AW " +
+            "nl_BE nl_BQ nl_CW nl_NL nl_SR nl_SX nmg nmg_CM nn nn_NO nnh nnh_CM " +
+            "no no_NO no_NO_NY nus nus_SD nyn nyn_UG om om_ET om_KE or or_IN os " +
+            "os_GE os_RU pa pa_IN_#Guru pa_PK_#Arab pa__#Arab pa__#Guru pl pl_PL " +
+            "ps ps_AF pt pt_AO pt_BR pt_CV pt_GW pt_MO pt_MZ pt_PT pt_ST pt_TL qu " +
+            "qu_BO qu_EC qu_PE rm rm_CH rn rn_BI ro ro_MD ro_RO rof rof_TZ ru " +
+            "ru_BY ru_KG ru_KZ ru_MD ru_RU ru_UA rw rw_RW rwk rwk_TZ sah sah_RU " +
+            "saq saq_KE sbp sbp_TZ se se_FI se_NO se_SE seh seh_MZ ses ses_ML sg " +
+            "sg_CF shi shi_MA_#Latn shi_MA_#Tfng shi__#Latn shi__#Tfng si si_LK " +
+            "sk sk_SK sl sl_SI smn smn_FI sn sn_ZW so so_DJ so_ET so_KE so_SO sq " +
+            "sq_AL sq_MK sq_XK sr sr_BA sr_BA_#Cyrl sr_BA_#Latn sr_CS sr_ME " +
+            "sr_ME_#Cyrl sr_ME_#Latn sr_RS sr_RS_#Cyrl sr_RS_#Latn sr_XK_#Cyrl " +
+            "sr_XK_#Latn sr__#Cyrl sr__#Latn sv sv_AX sv_FI sv_SE sw sw_CD sw_KE " +
+            "sw_TZ sw_UG ta ta_IN ta_LK ta_MY ta_SG te te_IN teo teo_KE teo_UG " +
+            "th th_TH th_TH_TH_#u-nu-thai ti ti_ER ti_ET to to_TO tr tr_CY tr_TR " +
+            "twq twq_NE tzm tzm_MA_#Latn tzm__#Latn ug ug_CN_#Arab ug__#Arab uk " +
+            "uk_UA ur ur_IN ur_PK uz uz_AF_#Arab uz_UZ_#Cyrl uz_UZ_#Latn " +
+            "uz__#Arab uz__#Cyrl uz__#Latn vai vai_LR_#Latn vai_LR_#Vaii " +
+            "vai__#Latn vai__#Vaii vi vi_VN vun vun_TZ wae wae_CH xog xog_UG yav " +
+            "yav_CM yo yo_BJ yo_NG zgh zgh_MA zh zh_CN zh_CN_#Hans zh_HK " +
+            "zh_HK_#Hans zh_HK_#Hant zh_MO_#Hans zh_MO_#Hant zh_SG zh_SG_#Hans " +
+            "zh_TW zh_TW_#Hant zh__#Hans zh__#Hant zu zu_ZA",
+        },
+
+        // All English/Japanese locales
+        {
+            "--include-locales=en,ja",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
+            " en en_001 en_150 en_AG en_AI en_AS en_AU en_BB en_BE en_BM en_BS " +
+            "en_BW en_BZ en_CA en_CC en_CK en_CM en_CX en_DG en_DM en_ER en_FJ " +
+            "en_FK en_FM en_GB en_GD en_GG en_GH en_GI en_GM en_GU en_GY en_HK " +
+            "en_IE en_IM en_IN en_IO en_JE en_JM en_KE en_KI en_KN en_KY en_LC " +
+            "en_LR en_LS en_MG en_MH en_MO en_MP en_MS en_MT en_MU en_MW en_MY " +
+            "en_NA en_NF en_NG en_NR en_NU en_NZ en_PG en_PH en_PK en_PN en_PR " +
+            "en_PW en_RW en_SB en_SC en_SD en_SG en_SH en_SL en_SS en_SX en_SZ " +
+            "en_TC en_TK en_TO en_TT en_TV en_TZ en_UG en_UM en_US en_US_POSIX " +
+            "en_VC en_VG en_VI en_VU en_WS en_ZA en_ZM en_ZW ja ja_JP ja_JP_JP_#u-ca-japanese",
+        },
+
+        // All locales in India
+        {
+            "--include-locales=*-IN",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_IN.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_hi_IN.class",
+                "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_as_IN.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_IN.class",
+                "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_kok_IN.class",
+                "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_ks_Arab_IN.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
+            " as_IN bn_IN bo_IN brx_IN en en_IN en_US en_US_POSIX gu_IN hi_IN kn_IN " +
+            "kok_IN ks_IN_#Arab ml_IN mr_IN ne_IN or_IN pa_IN_#Guru ta_IN te_IN ur_IN",
+        },
+
+        // Thai
+        {"--include-locales=th",
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
+            " en en_US en_US_POSIX th th_TH th_TH_TH_#u-nu-thai",
+        },
+
+        // Hong Kong
+        {"--include-locales=zh-HK",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh_HK.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_zh_TW.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
+            " en en_US en_US_POSIX zh_HK zh_HK_#Hans zh_HK_#Hant",
+        },
+
+        // Norwegian
+        {"--include-locales=nb,nn,no",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_no.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_no_NO.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_no_NO_NY.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nb.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nn.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
+            " en en_US en_US_POSIX nb nb_NO nb_SJ nn nn_NO no no_NO no_NO_NY",
+        },
+
+        // Hebrew/Indonesian/Yiddish
+        {"--include-locales=he,id,yi",
+            List.of(
+                "/jdk.localedata/sun/text/resources/ext/FormatData_in.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_in_ID.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_iw.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_iw_IL.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_in.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_iw.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ji.class"),
+            List.of(
+                "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/thai_dict",
+                "/jdk.localedata/sun/text/resources/WordBreakIteratorData_th",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorRules_th.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class",
+                "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"),
+            " en en_US en_US_POSIX in in_ID iw iw_IL ji ji_001",
+        },
+    };
+
+    public static void main(String[] args) throws Exception {
+        helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run");
+            return;
+        }
+
+        helper.generateDefaultModules();
+
+        for (Object[] data : testData) {
+            // create image for each test data
+            Path image = JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .output(helper.createNewImageDir(moduleName))
+                    .addMods("jdk.localedata")
+                    .option((String)data[INCLUDE_LOCALES_OPTION])
+                    .call().assertSuccess();
+
+            // test locale data entries
+            testLocaleDataEntries(image,
+                (List<String>)data[EXPECTED_LOCATIONS],
+                (List<String>)data[UNEXPECTED_PATHS]);
+
+            // test available locales
+            testAvailableLocales(image, (String)data[AVAILABLE_LOCALES]);
+        }
+    }
+
+    private static void testLocaleDataEntries(Path image, List<String> expectedLocations,
+                        List<String> unexpectedPaths) throws Exception {
+        JImageValidator.validate(
+            image.resolve("lib").resolve("modules"),
+            expectedLocations, unexpectedPaths);
+    }
+
+    private static void testAvailableLocales(Path image, String availableLocales) throws Exception {
+        Path launcher = image.resolve("bin/java" +
+            (System.getProperty("os.name").startsWith("Windows") ? ".exe" : ""));
+        System.out.print(launcher);
+        ProcessBuilder pb = new ProcessBuilder(launcher.toString(),
+            "GetAvailableLocales", availableLocales);
+        int ret = pb.start().waitFor();
+        System.out.println(" Return code: " + ret);
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/InstalledModulesTest.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/InstalledModulesTest.java
new file mode 100644
index 0000000..af1fe3e
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/InstalledModulesTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @modules java.base/jdk.internal.misc
+ * @run testng InstalledModulesTest
+ * @summary Verify the properties of ModuleDescriptor created
+ *          by InstalledModules
+ */
+
+public class InstalledModulesTest {
+    private static final JavaLangModuleAccess jlma = SharedSecrets.getJavaLangModuleAccess();
+
+    /**
+     * Verify ModuleDescriptor contains unmodifiable sets
+     */
+    @Test
+    public void testUnmodifableDescriptors() throws Exception {
+        ModuleFinder.ofSystem().findAll()
+                    .stream()
+                    .map(ModuleReference::descriptor)
+                    .forEach(this::testModuleDescriptor);
+    }
+
+    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"));
+        assertUnmodifiable(md.uses(), "use");
+        assertUnmodifiable(md.provides(), "provide",
+                           jlma.newProvides("provide", Collections.singleton("provide")));
+
+    }
+
+    private <T> void assertUnmodifiable(Set<T> set, T dummy) {
+        try {
+            set.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);
+            fail("Should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            // pass
+        } catch (Exception e) {
+            fail("Should throw UnsupportedOperationException");
+        }
+    }
+
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/UserModuleTest.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/UserModuleTest.java
new file mode 100644
index 0000000..f5bbe62
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/UserModuleTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import jdk.testlibrary.FileUtils;
+import static jdk.testlibrary.ProcessTools.*;
+
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build UserModuleTest CompilerUtils jdk.testlibrary.FileUtils jdk.testlibrary.ProcessTools
+ * @run testng UserModuleTest
+ */
+
+public class UserModuleTest {
+    private static final String JAVA_HOME = System.getProperty("java.home");
+    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 MODS_DIR = Paths.get("mods");
+    private static final Path IMAGE = Paths.get("image");
+    private static final Path JMODS = Paths.get(JAVA_HOME, "jmods");
+
+    // the names of the modules in this test
+    private static String[] modules = new String[] {"m1", "m2", "m3"};
+
+    private static boolean hasJmods() {
+        if (!Files.exists(JMODS)) {
+            System.err.println("Test skipped. NO jmods directory");
+            return false;
+        }
+        return true;
+    }
+
+    /*
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Throwable {
+        if (!hasJmods()) return;
+
+        for (String mn : modules) {
+            Path msrc = SRC_DIR.resolve(mn);
+            assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "-modulesourcepath", SRC_DIR.toString()));
+        }
+
+        if (Files.exists(IMAGE)) {
+            FileUtils.deleteFileTreeUnchecked(IMAGE);
+        }
+
+        createImage(IMAGE, "java.base", "m1");
+    }
+
+    private void createImage(Path outputDir, String... modules) throws Throwable {
+        Path jlink = Paths.get(JAVA_HOME, "bin", "jlink");
+        String mp = JMODS.toString() + File.pathSeparator + MODS_DIR.toString();
+        assertTrue(executeProcess(jlink.toString(), "--output", outputDir.toString(),
+                        "--addmods", Arrays.stream(modules).collect(Collectors.joining(",")),
+                        "--modulepath", mp)
+                        .outputTo(System.out)
+                        .errorTo(System.out)
+                        .getExitValue() == 0);
+    }
+
+    /*
+     * Test the image created when linking with a module with
+     * no ConcealedPackages attribute
+     */
+    @Test
+    public void test() throws Throwable {
+        if (!hasJmods()) return;
+
+        Path java = IMAGE.resolve("bin").resolve("java");
+        assertTrue(executeProcess(java.toString(), "-m", "m1/p1.Main")
+                        .outputTo(System.out)
+                        .errorTo(System.out)
+                        .getExitValue() == 0);
+    }
+
+    /*
+     * Disable the fast loading of installed modules.
+     * Parsing module-info.class
+     */
+    @Test
+    public void disableInstalledModules() throws Throwable {
+        if (!hasJmods()) return;
+
+        Path java = IMAGE.resolve("bin").resolve("java");
+        assertTrue(executeProcess(java.toString(),
+                                  "-Djdk.installed.modules.disable",
+                                  "-m", "m1/p1.Main")
+                        .outputTo(System.out)
+                        .errorTo(System.out)
+                        .getExitValue() == 0);
+    }
+
+    /*
+     * Test the optimization that deduplicates Set<String> on targets of exports,
+     * uses, provides.
+     */
+    @Test
+    public void testDedupSet() throws Throwable {
+        if (!hasJmods()) return;
+
+        Path dir = Paths.get("newImage");
+        createImage(dir, "java.base", "m1", "m2", "m3");
+        Path java = dir.resolve("bin").resolve("java");
+        assertTrue(executeProcess(java.toString(), "-m", "m1/p1.Main")
+                        .outputTo(System.out)
+                        .errorTo(System.out)
+                        .getExitValue() == 0);
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/module-info.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/module-info.java
new file mode 100644
index 0000000..f6ecf6b
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java
new file mode 100644
index 0000000..4e51697
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java
@@ -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.
+ */
+
+package p1;
+
+import java.lang.module.ModuleDescriptor;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+
+public class Main {
+    public static void main(String... args) throws Exception {
+        // load another package
+        p2.T.test();
+
+        // check the module descriptor of an installed module
+        validate(Main.class.getModule().getDescriptor());
+
+        // read m1/module-info.class
+        FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), null);
+        Path path = fs.getPath("/", "modules", "m1", "module-info.class");
+        validate(ModuleDescriptor.read(Files.newInputStream(path)));
+    }
+
+    static void validate(ModuleDescriptor md) {
+        checkPackages(md.conceals(), "p1", "p2");
+        checkPackages(md.packages(), "p1", "p2");
+    }
+
+    static void checkPackages(Set<String> pkgs, String... expected) {
+        for (String pn : expected) {
+            if (!pkgs.contains(pn)) {
+                throw new RuntimeException(pn + " missing in " + pkgs);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p2/T.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p2/T.java
new file mode 100644
index 0000000..7a83ae9
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p2/T.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 p2;
+
+public class T {
+    public static void test() { }
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/module-info.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/module-info.java
new file mode 100644
index 0000000..dae7a3a
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    uses q.S1;
+    uses q.S2;
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S1.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S1.java
new file mode 100644
index 0000000..3aa3b38
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S1.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 q;
+
+public interface S1 {
+    public String name();
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S2.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S2.java
new file mode 100644
index 0000000..57cb646
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m2/q/S2.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 q;
+
+public interface S2 {
+    public String name();
+}
diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m3/module-info.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m3/module-info.java
new file mode 100644
index 0000000..b164b24
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m3/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m3 {
+}
diff --git a/jdk/test/tools/jlink/plugins/LastSorterTest.java b/jdk/test/tools/jlink/plugins/LastSorterTest.java
new file mode 100644
index 0000000..100ca1e
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 last sorter property
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ * @run main/othervm LastSorterTest
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.tools.jlink.internal.ImagePluginConfiguration;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.Jlink.PluginsConfiguration;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class LastSorterTest {
+
+    public LastSorterTest() {
+        for (int i = 1; i <= 6; i++) {
+            PluginRepository.registerPlugin(new SorterPlugin("sorterplugin" + i));
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        new LastSorterTest().test();
+    }
+
+    public void test() throws Exception {
+        checkUnknownPlugin();
+
+        checkOrderAfterLastSorter();
+
+        checkPositiveCase();
+
+        checkTwoLastSorters();
+    }
+
+    private void checkTwoLastSorters() throws Exception {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("sorterplugin5", "/a"));
+        plugins.add(createPlugin("sorterplugin6", "/a"));
+        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
+                null, "sorterplugin5");
+
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
+
+        // check order
+        PoolImpl res = fillOutResourcePool();
+
+        try {
+            stack.visitResources(res);
+            throw new AssertionError("Exception expected: Order of resources is already frozen." +
+                    "Plugin sorterplugin6 is badly located");
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    private PoolImpl fillOutResourcePool() throws Exception {
+        PoolImpl res = new PoolImpl();
+        res.add(Pool.newResource("/eee/bbb/res1.class", new byte[90]));
+        res.add(Pool.newResource("/aaaa/bbb/res2.class", new byte[90]));
+        res.add(Pool.newResource("/bbb/aa/res1.class", new byte[90]));
+        res.add(Pool.newResource("/aaaa/bbb/res3.class", new byte[90]));
+        res.add(Pool.newResource("/bbb/aa/res2.class", new byte[90]));
+        res.add(Pool.newResource("/fff/bbb/res1.class", new byte[90]));
+        res.add(Pool.newResource("/aaaa/bbb/res1.class", new byte[90]));
+        res.add(Pool.newResource("/bbb/aa/res3.class", new byte[90]));
+        res.add(Pool.newResource("/ccc/bbb/res1.class", new byte[90]));
+        res.add(Pool.newResource("/ddd/bbb/res1.class", new byte[90]));
+        return res;
+    }
+
+    private static Plugin createPlugin(String name, String arg) {
+        Map<String, String> conf = new HashMap<>();
+        conf.put(name, arg);
+        return Jlink.newPlugin(name, conf, null);
+    }
+
+    private void checkPositiveCase() throws Exception {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("sorterplugin1", "/c"));
+        plugins.add(createPlugin("sorterplugin2", "/b"));
+        plugins.add(createPlugin("sorterplugin3", "/a"));
+
+        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
+                null, "sorterplugin3");
+
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
+
+        // check order
+        PoolImpl res = fillOutResourcePool();
+
+        stack.visitResources(res);
+    }
+
+    private void checkUnknownPlugin() {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("sorterplugin1", "/1"));
+        plugins.add(createPlugin("sorterplugin2", "/1"));
+        plugins.add(createPlugin("sorterplugin3", "/1"));
+        plugins.add(createPlugin("sorterplugin4", "/1"));
+
+        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
+                null, "sorterplugin5");
+        try {
+            ImagePluginConfiguration.parseConfiguration(config);
+            throw new AssertionError("Unknown plugin should have failed.");
+        } catch (Exception ex) {
+            // XXX OK expected
+        }
+    }
+
+    private void checkOrderAfterLastSorter() throws Exception {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("sorterplugin1", "/c"));
+        plugins.add(createPlugin("sorterplugin2", "/b"));
+        plugins.add(createPlugin("sorterplugin3", "/a"));
+        plugins.add(createPlugin("sorterplugin4", "/d"));
+
+        PluginsConfiguration config = new Jlink.PluginsConfiguration(plugins,
+                null, "sorterplugin3");
+
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(config);
+
+        // check order
+        PoolImpl res = fillOutResourcePool();
+        try {
+            stack.visitResources(res);
+            throw new AssertionError("Order was changed after the last sorter, but no exception occurred");
+        } catch (Exception ex) {
+            // XXX OK expected
+        }
+    }
+
+    public static class SorterPlugin implements TransformerPlugin {
+
+        private final String name;
+        private String starts;
+
+        private SorterPlugin(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public void visit(Pool resources, Pool output) {
+            List<ModuleData> paths = new ArrayList<>();
+            for (ModuleData res : resources.getContent()) {
+                if (res.getPath().startsWith(starts)) {
+                    paths.add(0, res);
+                } else {
+                    paths.add(res);
+                }
+            }
+
+            for (ModuleData r : paths) {
+                output.add(r);
+            }
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public void configure(Map<String, String> config) {
+            String arguments = config.get(name);
+            this.starts = arguments;
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/PluginOrderTest.java b/jdk/test/tools/jlink/plugins/PluginOrderTest.java
new file mode 100644
index 0000000..42655d4
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/PluginOrderTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Test order of plugins
+ * @author Jean-Francois Denise
+ * @library ../../lib
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.compiler
+ * @build tests.*
+ * @run main/othervm PluginOrderTest
+ */
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.tools.jlink.internal.PluginOrderingGraph;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Plugin.CATEGORY;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class PluginOrderTest {
+
+    public static void main(String[] args) throws Exception {
+
+        validGraph0();
+        validGraph1();
+
+        boolean failed = false;
+
+        try {
+            withCycles0();
+            failed = true;
+        } catch (Exception ex) {
+            //ok
+            System.err.println(ex.getMessage());
+        }
+        if (failed) {
+            throw new Exception("Should have failed");
+        }
+
+        try {
+            withCycles1();
+            failed = true;
+        } catch (Exception ex) {
+            //ok
+            System.err.println(ex.getMessage());
+        }
+        if (failed) {
+            throw new Exception("Should have failed");
+        }
+
+        try {
+            withCycles2();
+            failed = true;
+        } catch (Exception ex) {
+            //ok
+            System.err.println(ex.getMessage());
+        }
+        if (failed) {
+            throw new Exception("Should have failed");
+        }
+    }
+
+    private static void validGraph0() throws Exception {
+        Set<String> set = new HashSet<>();
+        set.add("plug2");
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(new Plug("plug2", Collections.emptySet(), Collections.emptySet(),
+                CATEGORY.TRANSFORMER));
+        plugins.add(new Plug("plug1", set, Collections.emptySet(), CATEGORY.TRANSFORMER));
+        List<Plugin> ordered = PluginOrderingGraph.sort(plugins);
+        if (ordered.get(0) != plugins.get(1) || ordered.get(1) != plugins.get(0)) {
+            throw new Exception("Invalid sorting");
+        }
+    }
+
+    private static void validGraph1() {
+        Set<String> lst1 = new HashSet<>();
+        lst1.add("plug2");
+        lst1.add("plug3");
+        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst3 = new HashSet<>();
+        lst3.add("plug4");
+        lst3.add("plug6");
+        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst5 = new HashSet<>();
+        lst5.add("plug3");
+        lst5.add("plug1");
+        lst5.add("plug2");
+        lst5.add("plug6");
+        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst6 = new HashSet<>();
+        lst6.add("plug4");
+        lst6.add("plug2");
+        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(p1);
+        plugins.add(p2);
+        plugins.add(p3);
+        plugins.add(p4);
+        plugins.add(p5);
+        plugins.add(p6);
+        plugins.add(p7);
+        plugins.add(p8);
+
+        PluginOrderingGraph.sort(plugins);
+    }
+
+    private static void withCycles0() throws Exception {
+        Set<String> set2 = new HashSet<>();
+        set2.add("plug1");
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(new Plug("plug2", set2, Collections.emptySet(),
+                CATEGORY.TRANSFORMER));
+
+        Set<String> set1 = new HashSet<>();
+        set1.add("plug2");
+        plugins.add(new Plug("plug1", set1, Collections.emptySet(), CATEGORY.TRANSFORMER));
+        PluginOrderingGraph.sort(plugins);
+
+    }
+
+    private static void withCycles2() {
+        Set<String> lst1 = new HashSet<>();
+        lst1.add("plug2");
+        lst1.add("plug3");
+        Plugin p1 = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst3 = new HashSet<>();
+        lst3.add("plug4");
+        lst3.add("plug6");
+        Plugin p3 = new Plug("plug3", lst3, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p4 = new Plug("plug4", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst5 = new HashSet<>();
+        lst5.add("plug3");
+        lst5.add("plug1");
+        lst5.add("plug2");
+        Plugin p5 = new Plug("plug5", lst5, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst6 = new HashSet<>();
+        lst6.add("plug4");
+        lst6.add("plug1");
+        Plugin p6 = new Plug("plug6", lst6, Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p7 = new Plug("plug7", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Plugin p8 = new Plug("plug8", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(p1);
+        plugins.add(p2);
+        plugins.add(p3);
+        plugins.add(p4);
+        plugins.add(p5);
+        plugins.add(p6);
+        plugins.add(p7);
+        plugins.add(p8);
+        PluginOrderingGraph.sort(plugins);
+    }
+
+    private static void withCycles1() {
+        Set<String> lst1 = new HashSet<>();
+        lst1.add("plug2");
+        lst1.add("plug3");
+        Plugin p = new Plug("plug1", lst1, Collections.emptySet(), CATEGORY.TRANSFORMER);
+        Plugin p2 = new Plug("plug2", Collections.emptySet(), Collections.emptySet(), CATEGORY.TRANSFORMER);
+
+        Set<String> lst3 = new HashSet<>();
+        lst3.add("plug2");
+
+        Set<String> lst4 = new HashSet<>();
+        lst4.add("plug1");
+
+        Plugin p3 = new Plug("plug3", lst4, lst3, CATEGORY.TRANSFORMER);
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(p);
+        plugins.add(p2);
+        plugins.add(p3);
+        PluginOrderingGraph.sort(plugins);
+    }
+
+    private static class Plug implements TransformerPlugin {
+
+        private final Set<String> isBefore;
+        private final Set<String> isAfter;
+        private final CATEGORY category;
+        private final String name;
+
+        private Plug(String name, Set<String> isBefore, Set<String> isAfter, CATEGORY category) {
+            this.name = name;
+            this.isBefore = isBefore;
+            this.isAfter = isAfter;
+            this.category = category;
+        }
+
+        @Override
+        public Set<String> isAfter() {
+            return isAfter;
+        }
+
+        @Override
+        public Set<String> isBefore() {
+            return isBefore;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        @Override
+        public void visit(Pool in, Pool out) {
+
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            return Collections.singleton(category);
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
new file mode 100644
index 0000000..525fb0b
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Negative test for ImagePluginStack.
+ * @author Andrei Eremeev
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ * @run main/othervm PluginsNegativeTest
+ */
+import java.lang.reflect.Layer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import jdk.tools.jlink.internal.ImagePluginConfiguration;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.Jlink.PluginsConfiguration;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class PluginsNegativeTest {
+
+    public static void main(String[] args) throws Exception {
+        new PluginsNegativeTest().test();
+    }
+
+    public void test() throws Exception {
+        testDuplicateBuiltInProviders();
+        testUnknownProvider();
+        PluginRepository.registerPlugin(new CustomPlugin("plugin"));
+        testEmptyInputResource();
+        testEmptyOutputResource();
+    }
+
+    private void testDuplicateBuiltInProviders() {
+        List<Plugin> javaPlugins = new ArrayList<>();
+        javaPlugins.addAll(PluginRepository.getPlugins(Layer.boot()));
+        for (Plugin javaPlugin : javaPlugins) {
+            System.out.println("Registered plugin: " + javaPlugin.getName());
+        }
+        for (Plugin javaPlugin : javaPlugins) {
+            String pluginName = javaPlugin.getName();
+            try {
+                PluginRepository.registerPlugin(new CustomPlugin(pluginName));
+                try {
+                    PluginRepository.getPlugin(pluginName, Layer.boot());
+                    throw new AssertionError("Exception is not thrown for duplicate plugin: " + pluginName);
+                } catch (Exception ignored) {
+                }
+            } finally {
+                PluginRepository.unregisterPlugin(pluginName);
+            }
+        }
+    }
+
+    private void testUnknownProvider() {
+        if (PluginRepository.getPlugin("unknown", Layer.boot()) != null) {
+            throw new AssertionError("Exception expected for unknown plugin name");
+        }
+    }
+
+    private static Plugin createPlugin(String name) {
+        return Jlink.newPlugin(name, Collections.emptyMap(), null);
+    }
+
+    private void testEmptyOutputResource() throws Exception {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("plugin"));
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
+                null, null));
+        PoolImpl inResources = new PoolImpl();
+        inResources.add(Pool.newResource("/aaa/bbb/A", new byte[10]));
+        try {
+            stack.visitResources(inResources);
+            throw new AssertionError("Exception expected when output resource is empty");
+        } catch (Exception ignored) {
+        }
+    }
+
+    private void testEmptyInputResource() throws Exception {
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin("plugin"));
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new PluginsConfiguration(plugins,
+                null, null));
+        PoolImpl inResources = new PoolImpl();
+        PoolImpl outResources = (PoolImpl) stack.visitResources(inResources);
+        if (!outResources.isEmpty()) {
+            throw new AssertionError("Output resource is not empty");
+        }
+    }
+
+    public static class CustomPlugin implements TransformerPlugin {
+
+        private final String name;
+
+        CustomPlugin(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public void visit(Pool inResources, Pool outResources) {
+            // do nothing
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+
+        @Override
+        public String getDescription() {
+            return null;
+        }
+
+        @Override
+        public void configure(Map<String, String> config) {
+
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/PrevisitorTest.java b/jdk/test/tools/jlink/plugins/PrevisitorTest.java
new file mode 100644
index 0000000..16d79f0
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @summary Test previsitor
+ * @author Andrei Eremeev
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ * @run main/othervm PrevisitorTest
+ */
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import jdk.tools.jlink.internal.ImagePluginConfiguration;
+import jdk.tools.jlink.internal.PluginRepository;
+import jdk.tools.jlink.internal.ImagePluginStack;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.ResourcePrevisitor;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class PrevisitorTest {
+
+    public static void main(String[] args) throws Exception {
+        new PrevisitorTest().test();
+    }
+
+    private static Plugin createPlugin(String name) {
+        return Jlink.newPlugin(name, Collections.emptyMap(), null);
+    }
+
+    public void test() throws Exception {
+        CustomPlugin plugin = new CustomPlugin();
+        PluginRepository.registerPlugin(plugin);
+        List<Plugin> plugins = new ArrayList<>();
+        plugins.add(createPlugin(CustomPlugin.NAME));
+        ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(new Jlink.PluginsConfiguration(plugins,
+                null, null));
+        PoolImpl inResources = new PoolImpl(ByteOrder.nativeOrder(), new CustomStringTable());
+        inResources.add(Pool.newResource("/aaa/bbb/res1.class", new byte[90]));
+        inResources.add(Pool.newResource("/aaa/bbb/res2.class", new byte[90]));
+        inResources.add(Pool.newResource("/aaa/bbb/res3.class", new byte[90]));
+        inResources.add(Pool.newResource("/aaa/ddd/res1.class", new byte[90]));
+        inResources.add(Pool.newResource("/aaa/res1.class", new byte[90]));
+        Pool outResources = stack.visitResources(inResources);
+        Collection<String> input = inResources.getContent().stream()
+                .map(Object::toString)
+                .collect(Collectors.toList());
+        Collection<String> output = outResources.getContent().stream()
+                .map(Object::toString)
+                .collect(Collectors.toList());
+        if (!input.equals(output)) {
+            throw new AssertionError("Input and output resources differ: input: "
+                    + input + ", output: " + output);
+        }
+    }
+
+    private static class CustomStringTable implements StringTable {
+
+        private final List<String> strings = new ArrayList<>();
+
+        @Override
+        public int addString(String str) {
+            strings.add(str);
+            return strings.size() - 1;
+        }
+
+        @Override
+        public String getString(int id) {
+            return strings.get(id);
+        }
+
+        public int size() {
+            return strings.size();
+        }
+    }
+
+    private static class CustomPlugin implements TransformerPlugin, ResourcePrevisitor {
+
+        private static String NAME = "plugin";
+
+        private boolean isPrevisitCalled = false;
+
+        @Override
+        public void visit(Pool inResources, Pool outResources) {
+            if (!isPrevisitCalled) {
+                throw new AssertionError("Previsit was not called");
+            }
+            CustomStringTable table = (CustomStringTable)
+                    ((PoolImpl) inResources).getStringTable();
+            if (table.size() == 0) {
+                throw new AssertionError("Table is empty");
+            }
+            Map<String, Integer> count = new HashMap<>();
+            for (int i = 0; i < table.size(); ++i) {
+                String s = table.getString(i);
+                if (inResources.get(s) != null) {
+                    throw new AssertionError();
+                }
+                count.compute(s, (k, c) -> 1 + (c == null ? 0 : c));
+            }
+            count.forEach((k, v) -> {
+                if (v != 1) {
+                    throw new AssertionError("Expected one entry in the table, got: " + v + " for " + k);
+                }
+            });
+            for (ModuleData r : inResources.getContent()) {
+                outResources.add(r);
+            }
+        }
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public void previsit(Pool resources, StringTable strings) {
+            isPrevisitCalled = true;
+            for (ModuleData r : resources.getContent()) {
+                String s = r.getPath();
+                int lastIndexOf = s.lastIndexOf('/');
+                if (lastIndexOf >= 0) {
+                    strings.addString(s.substring(0, lastIndexOf));
+                }
+            }
+        }
+
+        @Override
+        public Set<PluginType> getType() {
+            Set<PluginType> set = new HashSet<>();
+            set.add(CATEGORY.TRANSFORMER);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/ResourceFilterTest.java b/jdk/test/tools/jlink/plugins/ResourceFilterTest.java
new file mode 100644
index 0000000..b7b0f2b
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/ResourceFilterTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test ResourceFilter class
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main ResourceFilterTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import jdk.tools.jlink.internal.plugins.ResourceFilter;
+
+public class ResourceFilterTest {
+
+    public static void main(String[] args) throws Exception {
+        new ResourceFilterTest().test();
+    }
+
+    public void test() throws Exception {
+        String[] samples = {"toto.jcov", "/module/META-INF/services/MyProvider"};
+        String[] patterns = {"*.jcov", "*/META-INF/*"};
+        ResourceFilter rf = new ResourceFilter(patterns);
+        for (String s : samples) {
+            if (!rf.test(s)) {
+                throw new Exception("Sample " + s + "not accepted");
+            }
+        }
+        ResourceFilter rf2 = new ResourceFilter(patterns, true);
+        for (String s : samples) {
+            if (rf2.test(s)) {
+                throw new Exception("Sample " + s + " accepted");
+            }
+        }
+
+        // Excluded resource list in a file
+        File resources = new File("resources.exc");
+        resources.createNewFile();
+        StringBuilder builder = new StringBuilder();
+        for (String p : patterns) {
+            builder.append(p).append("\n");
+        }
+        Files.write(resources.toPath(), builder.toString().getBytes());
+
+        String[] input = {resources.getAbsolutePath()};
+        ResourceFilter rf3 = new ResourceFilter(input);
+        for (String s : samples) {
+            if (!rf3.test(s)) {
+                throw new Exception("Sample " + s + "not accepted");
+            }
+        }
+        ResourceFilter rf4 = new ResourceFilter(input, true);
+        for (String s : samples) {
+            if (rf4.test(s)) {
+                throw new Exception("Sample " + s + " accepted");
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/SignatureParserTest.java b/jdk/test/tools/jlink/plugins/SignatureParserTest.java
new file mode 100644
index 0000000..836c401
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/SignatureParserTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test SignatureParser
+ * @author Jean-Francois Denise
+ * @modules java.base/jdk.internal.jimage.decompressor
+ * @run main SignatureParserTest
+ */
+
+import java.util.Arrays;
+import java.util.Objects;
+
+import jdk.internal.jimage.decompressor.SignatureParser;
+
+public class SignatureParserTest {
+
+    private int passed = 0;
+    private int failed = 0;
+
+    public static void main(String[] args) {
+        new SignatureParserTest().test();
+    }
+
+    private void test() {
+        test("[Ljava/lang/String;", "[L;", "java/lang/String");
+        test("[[[[[[[[[[Ljava/lang/String;", "[[[[[[[[[[L;", "java/lang/String");
+        test("<T:Ljava/lang/Object;:Ljava/lang/Comparable<-TT;>;>" +
+                        "(Ljava/lang/String;Ljava/lang/Class<TT;>;TT;Ljava/lang/Comparable<-TT;>;" +
+                        "Ljava/lang/Comparable<-TT;>;ZZ)V",
+                "<T:L;:L<-TT;>;>(L;L<TT;>;TT;L<-TT;>;L<-TT;>;ZZ)V",
+                "java/lang/Object", "java/lang/Comparable", "java/lang/String",
+                "java/lang/Class", "java/lang/Comparable", "java/lang/Comparable");
+        test("(Ljava/lang/String;ZLjava/util/EventListener;TTK;)V",
+                "(L;ZL;TTK;)V",
+                "java/lang/String", "java/util/EventListener");
+        test("<Y:Ljava/lang/String;>", "<Y:L;>", "java/lang/String");
+        test("<Y:Ljava/lang/String;Z::Ljava/util/EventListener;>",
+                "<Y:L;Z::L;>", "java/lang/String",
+                "java/util/EventListener");
+        test("<Y:Ljava/lang/String;Z::Ljava/util/EventListener;O::Ljava/lang/Comparable<Ljava/lang/String;>;>",
+                "<Y:L;Z::L;O::L<L;>;>",
+                "java/lang/String", "java/util/EventListener", "java/lang/Comparable", "java/lang/String");
+        test("<Y:Ljava/lang/String;O::Ljava/lang/Comparable<Ljava/lang/String;Ljava/lang/Float;>;>",
+                "<Y:L;O::L<L;L;>;>",
+                "java/lang/String", "java/lang/Comparable", "java/lang/String", "java/lang/Float");
+        test("<Y:Ljava/lang/String;O::Ljava/lang/Comparable<Ljava/lang/String;Ljava/lang/Float<Ljava/lang/Object;>;>;>",
+                "<Y:L;O::L<L;L<L;>;>;>",
+                "java/lang/String", "java/lang/Comparable", "java/lang/String", "java/lang/Float", "java/lang/Object");
+        test("Ljava/util/Set;", "L;", "java/util/Set");
+        test("Ljavaapplication20/Titi<[Ljava/lang/String;Ljava/lang/Integer;>;", "L<[L;L;>;",
+                "javaapplication20/Titi",
+                "java/lang/String", "java/lang/Integer");
+        test("Ljava/lang/Comparable<TK;>;", "L<TK;>;", "java/lang/Comparable");
+        test("Ljava/io/Serializable;Ljava/lang/Comparable<TK;>;", "L;L<TK;>;",
+                "java/io/Serializable", "java/lang/Comparable");
+        test("<Y:Ljava/lang/String;Z::Ljava/util/EventListener;K::Ljava/util/EventListener;O::"
+                + "Ljava/lang/Comparable<Ljava/lang/String;>;>"
+                + "Ljavaapplication20/Titi<[Ljava/lang/String;Ljava/lang/Integer;TZ;>;"
+                + "Ljava/io/Serializable;Ljava/lang/Comparable<TK;>;",
+                "<Y:L;Z::L;K::L;O::L<L;>;>L<[L;L;TZ;>;L;L<TK;>;",
+                "java/lang/String", "java/util/EventListener", "java/util/EventListener", "java/lang/Comparable",
+                "java/lang/String", "javaapplication20/Titi", "java/lang/String", "java/lang/Integer",
+                "java/io/Serializable", "java/lang/Comparable");
+        test("<PO:Ljava/lang/Object;>(Ljava/lang/Integer;TPO;)Ljava/lang/Integer;",
+                "<PO:L;>(L;TPO;)L;",
+                "java/lang/Object", "java/lang/Integer", "java/lang/Integer");
+        test("<PO:Ljava/lang/Object;>(Ljava/lang/Integer;TPO;)TPO;", "<PO:L;>(L;TPO;)TPO;",
+                "java/lang/Object", "java/lang/Integer");
+        test("<T::Ljava/util/EventListener;>(Ljava/lang/Class<TT;>;)[TT;",
+                "<T::L;>(L<TT;>;)[TT;",
+                "java/util/EventListener", "java/lang/Class");
+        test("<PO:LTiti;>(Ljava/lang/Integer;ITPO;)Z", "<PO:L;>(L;ITPO;)Z",
+                "Titi", "java/lang/Integer");
+        test("<K:Ljava/lang/Object;V:Ljava/lang/Object;>Ljava/lang/Object;",
+                "<K:L;V:L;>L;",
+                "java/lang/Object", "java/lang/Object", "java/lang/Object");
+        test("Ljava/util/LinkedHashMap<TK;TV;>.LinkedHashIterator;Ljava/util/Iterator<TV;>;",
+                "L<TK;TV;>.L;L<TV;>;",
+                "java/util/LinkedHashMap",
+                "inkedHashIterator",
+                "java/util/Iterator");
+        test("LToto<Ljava/lang/String;>;", "L<L;>;", "Toto",
+                "java/lang/String");
+        test("Ljavaapplication20/Titi<[Ljava/lang/String;Ljava/lang/Integer<LToto;>;TZ;>;",
+                "L<[L;L<L;>;TZ;>;",
+                "javaapplication20/Titi", "java/lang/String", "java/lang/Integer", "Toto");
+        test("LX<[LQ;LW<LToto;>;TZ;>;", "L<[L;L<L;>;TZ;>;",
+                "X", "Q", "W", "Toto");
+        test("Ljava/lang/String<*>;", "L<*>;", "java/lang/String");
+        test("Ljava/util/List<[B>;", "L<[B>;", "java/util/List");
+        test("<T:Ljava/lang/Object;T_NODE::Ljava/util/stream/Node<TT;>;>Ljava/lang/Object;Ljava/util/stream/Node<TT;>;",
+                "<T:L;T_NODE::L<TT;>;>L;L<TT;>;",
+                "java/lang/Object", "java/util/stream/Node", "java/lang/Object", "java/util/stream/Node");
+        test("Ljavaapplication20/Titi<[Ljava/lang/String;>;", "L<[L;>;",
+                "javaapplication20/Titi", "java/lang/String");
+        test("<A::Ljava/lang/annotation/Annotation;"
+                        + "W::Lcom/sun/codemodel/internal/JAnnotationWriter<TA;>;>"
+                        + "Ljava/lang/Object;Ljava/lang/reflect/InvocationHandler;"
+                        + "Lcom/sun/codemodel/internal/JAnnotationWriter<TA;>;",
+                "<A::L;W::L<TA;>;>L;L;L<TA;>;",
+                "java/lang/annotation/Annotation", "com/sun/codemodel/internal/JAnnotationWriter",
+                "java/lang/Object", "java/lang/reflect/InvocationHandler", "com/sun/codemodel/internal/JAnnotationWriter");
+        test("<W::Lcom/sun/codemodel/internal/JAnnotationWriter<*>;>(Ljava/lang/Class<TW;>;" +
+                "Lcom/sun/codemodel/internal/JAnnotatable;)TW;",
+                "<W::L<*>;>(L<TW;>;L;)TW;",
+                "com/sun/codemodel/internal/JAnnotationWriter", "java/lang/Class", "com/sun/codemodel/internal/JAnnotatable");
+        test("Ljava/util/Set<Lcom/sun/tools/jdeps/JdepsTask$DotGraph<TT;>.Edge;>;",
+                "L<L<TT;>.Edge;>;",
+                "java/util/Set",
+                "com/sun/tools/jdeps/JdepsTask$DotGraph");
+        test("<E::Lcom/sun/xml/internal/rngom/ast/om/ParsedElementAnnotation;" +
+                "L::Lcom/sun/xml/internal/rngom/ast/om/Location;" +
+                "CL::Lcom/sun/xml/internal/rngom/ast/builder/CommentList<TL;>;>Ljava/lang/Object;",
+                "<E::L;L::L;CL::L<TL;>;>L;",
+                "com/sun/xml/internal/rngom/ast/om/ParsedElementAnnotation",
+                "",
+                "com/sun/xml/internal/rngom/ast/om/Location",
+                "",
+                "com/sun/xml/internal/rngom/ast/builder/CommentList",
+                "",
+                "java/lang/Object");
+        test("(Ljava/util/List<Lcom/sun/xml/internal/rngom/nc/NameClass;>;TL;TA;)" +
+                "Lcom/sun/xml/internal/rngom/nc/NameClass;",
+                "(L<L;>;TL;TA;)L;",
+                "java/util/List",
+                "com/sun/xml/internal/rngom/nc/NameClass",
+                "",
+                "com/sun/xml/internal/rngom/nc/NameClass");
+        test("[Ljava/util/List;", "[L;", "java/util/List");
+        test("[Ljava/util/List<+Lcom/sun/jdi/request/EventRequest;>;",
+                "[L<+L;>;",
+                "java/util/List", "com/sun/jdi/request/EventRequest");
+        test("Lcom/sun/xml/internal/bind/v2/util/QNameMap<TV;>.HashIterator" +
+                "<Lcom/sun/xml/internal/bind/v2/util/QNameMap$Entry<TV;>;>;",
+                "L<TV;>.HashIterator<L<TV;>;>;",
+                "com/sun/xml/internal/bind/v2/util/QNameMap", "com/sun/xml/internal/bind/v2/util/QNameMap$Entry");
+        test("[Ljava/lang/String;", "[L;", "java/lang/String");
+        test("[Ljava/lang/String<Ljava/lang/Toto<Ljava/lang/Titi;>;>;",
+                "[L<L<L;>;>;",
+                "java/lang/String", "java/lang/Toto", "java/lang/Titi");
+        test("<T::Ljava/util/EventListener;K:Ljava/util/BOO;>(ZCLjava/lang/Class<TT;>;IJS)[TT;",
+                "<T::L;K:L;>(ZCL<TT;>;IJS)[TT;",
+                "java/util/EventListener", "java/util/BOO", "java/lang/Class");
+        test("<T:Ljava/lang/Object;>(TT;ILjava/lang/Long;)TT;",
+                "<T:L;>(TT;IL;)TT;", "java/lang/Object", "java/lang/Long");
+        test("<T:Ljava/lang/Object;>(TT;ILjava/lang/Long;)TT;^TT;",
+                "<T:L;>(TT;IL;)TT;^TT;", "java/lang/Object", "java/lang/Long");
+        test("<T:Ljava/lang/Object;>(TT;ILjava/lang/Long;)TT;^TT;^Ljava/lang/Exception;",
+                "<T:L;>(TT;IL;)TT;^TT;^L;",
+                "java/lang/Object", "java/lang/Long", "java/lang/Exception");
+        if (passed + failed == 0) {
+            throw new AssertionError("No tests were run");
+        }
+        String message = String.format("Passed: %d, failed: %d, total: %d", passed, failed, passed + failed);
+        if (failed > 0) {
+            throw new AssertionError("Test failed: " + message);
+        } else {
+            System.err.println(message);
+        }
+    }
+
+    private void test(String type, String formatted, String...classNames) {
+        try {
+            SignatureParser.ParseResult result = SignatureParser.parseSignatureDescriptor(type);
+            String[] parsedNames = parse(classNames);
+            assertEquals(result.formatted, formatted, "Input: '" + type + "', checking 'formatted'");
+            assertEquals(result.types.size(), 2 * classNames.length,
+                    "Input: '" + type + "', checking the length of 'types':" +
+                            "\nexpected: " + Arrays.toString(parsedNames) +
+                            "\n     got: " + result.types);
+            for (int i = 0; i < result.types.size(); ++i) {
+                assertEquals(result.types.get(i), parsedNames[i],
+                        "Input: '" + type + "', checking 'packageName' at index " + i / 2);
+                ++i;
+                assertEquals(result.types.get(i), parsedNames[i],
+                        "Input: '" + type + "', checking 'simpleName' at index " + i / 2);
+            }
+            String reconstructed = SignatureParser.reconstruct(result.formatted, result.types);
+            assertEquals(reconstructed, type, "Input: '" + type + "', checking reconstruction from: "
+                    + result.formatted + " " + result.types);
+            ++passed;
+        } catch (Exception | AssertionError e) {
+            e.printStackTrace();
+            ++failed;
+        }
+    }
+
+    private void assertEquals(Object actual, Object expected, String message) {
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError(message + ": expected: " + expected + ", actual: " + actual);
+        }
+    }
+
+    private String[] parse(String[] classNames) {
+        String[] result = new String[2 * classNames.length];
+        for (int i = 0; i < classNames.length; ++i) {
+            int index = classNames[i].lastIndexOf("/");
+            result[2 * i] = index == -1 ? "" : classNames[i].substring(0, index);
+            result[2 *i + 1] = classNames[i].substring(index + 1);
+        }
+        return result;
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/SorterPluginTest.java b/jdk/test/tools/jlink/plugins/SorterPluginTest.java
new file mode 100644
index 0000000..1e01fa9
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/SorterPluginTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test sorter plugin
+ * @author Jean-Francois Denise
+ * @modules jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ * @run main SorterPluginTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+
+import jdk.tools.jlink.internal.plugins.SortResourcesPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+
+public class SorterPluginTest {
+
+    public static void main(String[] args) throws Exception {
+        new SorterPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        ModuleData[] array = {
+                Pool.newResource("/module1/toto1", new byte[0]),
+                Pool.newResource("/module2/toto1", new byte[0]),
+                Pool.newResource("/module3/toto1", new byte[0]),
+                Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
+                Pool.newResource("/zazou/toto1", new byte[0]),
+                Pool.newResource("/module4/zazou", new byte[0]),
+                Pool.newResource("/module5/toto1", new byte[0]),
+                Pool.newResource("/module6/toto1/module-info.class", new byte[0])
+        };
+
+        ModuleData[] sorted = {
+                Pool.newResource("/zazou/toto1", new byte[0]),
+                Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
+                Pool.newResource("/module6/toto1/module-info.class", new byte[0]),
+                Pool.newResource("/module1/toto1", new byte[0]),
+                Pool.newResource("/module2/toto1", new byte[0]),
+                Pool.newResource("/module3/toto1", new byte[0]),
+                Pool.newResource("/module4/zazou", new byte[0]),
+                Pool.newResource("/module5/toto1", new byte[0]),
+};
+
+        ModuleData[] sorted2 = {
+            Pool.newResource("/module5/toto1", new byte[0]),
+            Pool.newResource("/module6/toto1/module-info.class", new byte[0]),
+            Pool.newResource("/module4/zazou", new byte[0]),
+            Pool.newResource("/module3/toto1", new byte[0]),
+            Pool.newResource("/module3/toto1/module-info.class", new byte[0]),
+            Pool.newResource("/module1/toto1", new byte[0]),
+            Pool.newResource("/module2/toto1", new byte[0]),
+            Pool.newResource("/zazou/toto1", new byte[0]),};
+
+        Pool resources = new PoolImpl();
+        for (ModuleData r : array) {
+            resources.add(r);
+        }
+
+        {
+            Pool out = new PoolImpl();
+            Map<String, String> config = new HashMap<>();
+            config.put(SortResourcesPlugin.NAME, "/zazou/*,*/module-info.class");
+            TransformerPlugin p = new SortResourcesPlugin();
+            p.configure(config);
+            p.visit(resources, out);
+            check(out.getContent(), sorted);
+        }
+
+        {
+            // Order of resources in the file, then un-ordered resources.
+            File order = new File("resources.order");
+            order.createNewFile();
+            StringBuilder builder = new StringBuilder();
+            // 5 first resources come from file
+            for (int i = 0; i < 5; i++) {
+                builder.append(sorted2[i].getPath()).append("\n");
+            }
+            Files.write(order.toPath(), builder.toString().getBytes());
+
+            Pool out = new PoolImpl();
+            Map<String, String> config = new HashMap<>();
+            config.put(SortResourcesPlugin.NAME, order.getAbsolutePath());
+            TransformerPlugin p = new SortResourcesPlugin();
+            p.configure(config);
+            p.visit(resources, out);
+            check(out.getContent(), sorted2);
+
+        }
+    }
+
+    private void check(Collection<ModuleData> outResources,
+            ModuleData[] sorted) {
+        if (outResources.size() != sorted.length) {
+            throw new AssertionError("Wrong number of resources:\n"
+                    + "expected: " + Arrays.toString(sorted) + ",\n"
+                    + "     got: " + outResources);
+        }
+        int i = 0;
+        for (ModuleData r : outResources) {
+            System.err.println("Resource: " + r);
+            if (!sorted[i].getPath().equals(r.getPath())) {
+                throw new AssertionError("Resource not properly sorted, difference at: " + i + "\n"
+                        + "expected: " + Arrays.toString(sorted) + ",\n"
+                        + "     got: " + outResources);
+            }
+            i++;
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
new file mode 100644
index 0000000..786da46
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test StringSharingPluginTest
+ * @author Jean-Francois Denise
+ * @library ../../lib
+ * @modules java.base/jdk.internal.jimage
+ *          java.base/jdk.internal.jimage.decompressor
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.compiler
+ * @run build tests.*
+ * @run main StringSharingPluginTest
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+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.function.Consumer;
+
+import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.internal.jimage.decompressor.StringSharingDecompressor;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.StringTable;
+import jdk.tools.jlink.internal.plugins.StringSharingPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import tests.Helper;
+import tests.JImageValidator;
+
+public class StringSharingPluginTest {
+
+    private static int strID = 1;
+
+    public static void main(String[] args) throws Exception {
+        // JPRT not yet ready for jmods
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run, NO jmods directory");
+            return;
+        }
+
+        List<String> classes = Arrays.asList("toto.Main", "toto.com.foo.bar.X");
+        Path compiledClasses = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), "composite2", classes);
+
+        Map<String, Integer> map = new HashMap<>();
+        Map<Integer, String> reversedMap = new HashMap<>();
+
+        PoolImpl resources = new PoolImpl(ByteOrder.nativeOrder(), new StringTable() {
+            @Override
+            public int addString(String str) {
+                Integer id = map.get(str);
+                if (id == null) {
+                    id = strID;
+                    map.put(str, id);
+                    reversedMap.put(id, str);
+                    strID += 1;
+                }
+                return id;
+            }
+
+            @Override
+            public String getString(int id) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        });
+        Consumer<Path> c = (p) -> {
+            // take only the .class resources.
+            if (Files.isRegularFile(p) && p.toString().endsWith(".class")
+                    && !p.toString().endsWith("module-info.class")) {
+                try {
+                    byte[] content = Files.readAllBytes(p);
+                    String path = p.toString().replace('\\', '/');
+                    path = path.substring("/modules".length());
+                    ModuleData res = Pool.newResource(path, content);
+                    resources.add(res);
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+        };
+        try (java.util.stream.Stream<Path> stream = Files.walk(compiledClasses)) {
+            stream.forEach(c);
+        }
+        TransformerPlugin plugin = new StringSharingPlugin();
+        PoolImpl result = new PoolImpl(resources.getByteOrder(), resources.getStringTable());
+        plugin.visit(resources, result);
+
+        if (result.isEmpty()) {
+            throw new AssertionError("No result");
+        }
+
+        for (ModuleData res : result.getContent()) {
+            if (res.getPath().endsWith(".class")) {
+                byte[] uncompacted = StringSharingDecompressor.normalize(reversedMap::get, res.getBytes(),
+                        CompressedResourceHeader.getSize());
+                JImageValidator.readClass(uncompacted);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
new file mode 100644
index 0000000..fd8acae
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test StripDebugPlugin
+ * @author Jean-Francois Denise
+ * @library ../../lib
+ * @build tests.*
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.jlink/jdk.tools.jlink.internal.plugins
+ *          jdk.jlink/jdk.tools.jimage
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.compiler
+ * @run main StripDebugPluginTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Stream;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Code_attribute;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Method;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.tools.jlink.internal.PoolImpl;
+import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+import jdk.tools.jlink.plugin.Pool;
+import jdk.tools.jlink.plugin.Pool.ModuleData;
+import jdk.tools.jlink.plugin.TransformerPlugin;
+import tests.Helper;
+
+public class StripDebugPluginTest {
+    public static void main(String[] args) throws Exception {
+        new StripDebugPluginTest().test();
+    }
+
+    public void test() throws Exception {
+        // JPRT not yet ready for jmods
+        Helper helper = Helper.newHelper();
+        if (helper == null) {
+            System.err.println("Test not run, NO jmods directory");
+            return;
+        }
+
+        List<String> classes = Arrays.asList("toto.Main", "toto.com.foo.bar.X");
+        Path moduleFile = helper.generateModuleCompiledClasses(
+                helper.getJmodSrcDir(), helper.getJmodClassesDir(), "leaf1", classes);
+        Path moduleInfo = moduleFile.resolve("module-info.class");
+
+        // Classes have been compiled in debug.
+        List<Path> covered = new ArrayList<>();
+        byte[] infoContent = Files.readAllBytes(moduleInfo);
+        try (Stream<Path> stream = Files.walk(moduleFile)) {
+            for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext(); ) {
+                Path p = iterator.next();
+                if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
+                    byte[] content = Files.readAllBytes(p);
+                    String path = "/" + helper.getJmodClassesDir().relativize(p).toString();
+                    String moduleInfoPath = path + "/module-info.class";
+                    check(path, content, moduleInfoPath, infoContent);
+                    covered.add(p);
+                }
+            }
+        }
+        if (covered.isEmpty()) {
+            throw new AssertionError("No class to compress");
+        } else {
+            System.err.println("removed debug attributes from "
+                    + covered.size() + " classes");
+        }
+    }
+
+    private void check(String path, byte[] content, String infoPath, byte[] moduleInfo) throws Exception {
+        path = path.replace('\\', '/');
+        StripDebugPlugin debug = new StripDebugPlugin();
+        debug.configure(new HashMap<>());
+        ModuleData result1 = stripDebug(debug, Pool.newResource(path,content), path, infoPath, moduleInfo);
+
+        if (!path.endsWith("module-info.class")) {
+            if (result1.getLength() >= content.length) {
+                throw new AssertionError("Class size not reduced, debug info not "
+                        + "removed for " + path);
+            }
+            checkDebugAttributes(result1.getBytes());
+        }
+
+        ModuleData result2 = stripDebug(debug, result1, path, infoPath, moduleInfo);
+        if (result1.getLength() != result2.getLength()) {
+            throw new AssertionError("removing debug info twice reduces class size of "
+                    + path);
+        }
+        checkDebugAttributes(result1.getBytes());
+    }
+
+    private ModuleData stripDebug(TransformerPlugin debug, ModuleData classResource,
+            String path, String infoPath, byte[] moduleInfo) throws Exception {
+        Pool resources = new PoolImpl();
+        resources.add(classResource);
+        if (!path.endsWith("module-info.class")) {
+            ModuleData res2 = Pool.newResource(infoPath, moduleInfo);
+            resources.add(res2);
+        }
+        Pool results = new PoolImpl();
+        debug.visit(resources, results);
+        System.out.println(classResource.getPath());
+        return results.get(classResource.getPath());
+    }
+
+    private void checkDebugAttributes(byte[] strippedClassFile) throws IOException, ConstantPoolException {
+        ClassFile classFile = ClassFile.read(new ByteArrayInputStream(strippedClassFile));
+        String[] debugAttributes = new String[]{
+                Attribute.LineNumberTable,
+                Attribute.LocalVariableTable,
+                Attribute.LocalVariableTypeTable
+        };
+        for (Method method : classFile.methods) {
+            String methodName = method.getName(classFile.constant_pool);
+            Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code);
+            for (String attr : debugAttributes) {
+                if (code.attributes.get(attr) != null) {
+                    throw new AssertionError("Debug attribute was not removed: " + attr +
+                            " from method " + classFile.getName() + "#" + methodName);
+                }
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jmod/JmodNegativeTest.java b/jdk/test/tools/jmod/JmodNegativeTest.java
new file mode 100644
index 0000000..5469726
--- /dev/null
+++ b/jdk/test/tools/jmod/JmodNegativeTest.java
@@ -0,0 +1,552 @@
+/**
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build jdk.testlibrary.FileUtils CompilerUtils
+ * @run testng JmodNegativeTest
+ * @summary Negative tests for jmod
+ */
+
+import java.io.*;
+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.function.Consumer;
+import java.util.function.Supplier;
+import java.util.zip.ZipOutputStream;
+import jdk.testlibrary.FileUtils;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static java.io.File.pathSeparator;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertTrue;
+
+public class JmodNegativeTest {
+
+    static final String TEST_SRC = System.getProperty("test.src", ".");
+    static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    static final Path EXPLODED_DIR = Paths.get("build");
+    static final Path MODS_DIR = Paths.get("jmods");
+
+    @BeforeTest
+    public void buildExplodedModules() throws IOException {
+        if (Files.exists(EXPLODED_DIR))
+            FileUtils.deleteFileTreeWithRetry(EXPLODED_DIR);
+
+        for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {
+            Path dir = EXPLODED_DIR.resolve(name);
+            assertTrue(compileModule(name, dir.resolve("classes")));
+        }
+
+        if (Files.exists(MODS_DIR))
+            FileUtils.deleteFileTreeWithRetry(MODS_DIR);
+        Files.createDirectories(MODS_DIR);
+    }
+
+    @Test
+    public void testNoArgs() {
+        jmod()
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: one of create, list, or describe must be specified")
+            );
+    }
+
+    @Test
+    public void testBadAction() {
+        jmod("badAction")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: mode must be one of create, list, or describe")
+            );
+
+        jmod("--badOption")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: 'badOption' is not a recognized option")
+            );
+    }
+
+    @Test
+    public void testTooManyArgs() throws IOException {
+        Path jmod = MODS_DIR.resolve("doesNotExist.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+
+        jmod("create",
+             jmod.toString(),
+             "AAA")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: unknown option(s): [AAA]")
+            );
+    }
+
+    @Test
+    public void testCreateNoArgs() {
+        jmod("create")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: jmod-file must be specified")
+            );
+    }
+
+    @Test
+    public void testListNoArgs() {
+        jmod("list")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: jmod-file must be specified")
+            );
+    }
+
+    @Test
+    public void testListFileDoesNotExist() throws IOException {
+        Path jmod = MODS_DIR.resolve("doesNotExist.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+
+        jmod("list",
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: no jmod file found: "
+                        + jmod.toString())
+            );
+    }
+
+    @Test
+    public void testListJmodIsDir() throws IOException {
+        Path jmod = MODS_DIR.resolve("testListJmodIsDir.jmod");
+        if (Files.notExists(jmod))
+            Files.createDirectory(jmod);
+
+        jmod("list",
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: error opening jmod file")
+            );
+    }
+
+    @Test
+    public void testlistJmodMalformed() throws IOException {
+        Path jmod = MODS_DIR.resolve("testlistJmodMalformed.jmod");
+        if (Files.notExists(jmod))
+            Files.createFile(jmod);
+
+        jmod("list",
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: error opening jmod file")
+            );
+    }
+
+    @Test
+    public void testHashDependenciesModulePathNotSpecified() {
+        jmod("create",
+             "--hash-dependencies", "anyPattern.*",
+             "output.jmod")
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: --module-path must be "
+                        +"specified when hashing dependencies")
+            );
+    }
+
+    @Test
+    public void testCreateJmodAlreadyExists() throws IOException {
+        Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists.jmod");
+        if (Files.notExists(jmod))
+            Files.createFile(jmod);
+
+        jmod("create",
+             "--class-path", Paths.get(".").toString(), // anything that exists
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: file already exists: " + jmod.toString())
+            );
+    }
+
+    @Test
+    public void testCreateJmodIsDir() throws IOException {
+        Path jmod = MODS_DIR.resolve("testCreateJmodAlreadyExists");
+        if (Files.notExists(jmod))
+            Files.createDirectory(jmod);
+
+        jmod("create",
+             "--class-path", Paths.get(".").toString(), // anything that exists
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: file already exists: " + jmod.toString())
+            );
+    }
+
+    @Test
+    public void testInvalidModuleVersion() throws IOException {
+        Path jmod = MODS_DIR.resolve("testEmptyModuleVersion.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        for (String version : new String[] { "", "NOT_A_VALID_VERSION" }) {
+            jmod("create",
+                 "--class-path", cp,
+                 "--module-version", version,
+                 jmod.toString())
+                .assertFailure()
+                .resultChecker(r ->
+                    assertContains(r.output, "Error: invalid module version")
+                );
+        }
+    }
+
+    @Test(enabled = false)  // TODO: jmod should check for duplicates before creating.
+    public void testDuplicates() throws IOException {
+        Path jmod = MODS_DIR.resolve("testDuplicates.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        jmod("create",
+             "--class-path", cp + pathSeparator + cp,
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: duplicate resource found, etc..")
+            );
+    }
+
+    @Test
+    public void testEmptyFileInClasspath() throws IOException {
+        Path jmod = MODS_DIR.resolve("testEmptyFileInClasspath.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path jar = MODS_DIR.resolve("NotARealJar_Empty.jar");
+        FileUtils.deleteFileIfExistsWithRetry(jar);
+        Files.createFile(jar);
+
+        jmod("create",
+             "--class-path", jar.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: module-info.class not found")
+            );
+    }
+
+    @Test
+    public void testEmptyJarInClasspath() throws IOException {
+        Path jmod = MODS_DIR.resolve("testEmptyJarInClasspath.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path jar = MODS_DIR.resolve("empty.jar");
+        FileUtils.deleteFileIfExistsWithRetry(jar);
+        try (FileOutputStream fos = new FileOutputStream(jar.toFile());
+             ZipOutputStream zos = new ZipOutputStream(fos)) {
+            // empty
+        }
+
+        jmod("create",
+             "--class-path", jar.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: module-info.class not found")
+            );
+    }
+
+    @Test
+    public void testModuleInfoNotFound() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path jar = MODS_DIR.resolve("empty");
+        FileUtils.deleteFileIfExistsWithRetry(jar);
+        Files.createDirectory(jar);
+
+        jmod("create",
+             "--class-path", jar.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: module-info.class not found")
+            );
+    }
+
+    @Test
+    public void testModuleInfoIsDir() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = MODS_DIR.resolve("module-info.class");
+        FileUtils.deleteFileIfExistsWithRetry(cp);
+        Files.createDirectory(cp);
+        Files.createFile(cp.resolve("nada.txt"));
+
+        jmod("create",
+             "--class-path", cp.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: module-info.class not found")
+            );
+    }
+
+    @Test
+    public void testDependencyNotFound() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path emptyDir = Paths.get("empty");
+        if (Files.exists(emptyDir))
+            FileUtils.deleteFileTreeWithRetry(emptyDir);
+        Files.createDirectory(emptyDir);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        jmod("create",
+             "--class-path", cp,
+             "--hash-dependencies", ".*",
+             "--modulepath", emptyDir.toString(),
+            jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Hashing module foo dependencies, "
+                        + "unable to find module java.base on module path")
+            );
+    }
+
+    @Test
+    public void testEmptyFileInModulePath() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path empty = MODS_DIR.resolve("emptyFile.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(empty);
+        Files.createFile(empty);
+        try {
+            String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+            jmod("create",
+                 "--class-path", cp,
+                 "--hash-dependencies", ".*",
+                 "--modulepath", MODS_DIR.toString(),
+                 jmod.toString())
+                .assertFailure()
+                .resultChecker(r ->
+                    assertContains(r.output, "Error: error reading module path")
+                );
+        } finally {
+            FileUtils.deleteFileWithRetry(empty);
+        }
+    }
+
+    @Test
+    public void testFileInModulePath() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path file = MODS_DIR.resolve("testFileInModulePath.txt");
+        FileUtils.deleteFileIfExistsWithRetry(file);
+        Files.createFile(file);
+
+        jmod("create",
+             "--hash-dependencies", ".*",
+             "--modulepath", file.toString(),
+             jmod.toString())
+            .assertFailure()
+            .resultChecker(r ->
+                assertContains(r.output, "Error: path must be a directory")
+            );
+    }
+
+    @DataProvider(name = "pathDoesNotExist")
+    public Object[][] pathDoesNotExist() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));
+
+        List<Supplier<JmodResult>> tasks = Arrays.asList(
+                () -> jmod("create",
+                           "--hash-dependencies", "anyPattern",
+                           "--modulepath", "doesNotExist",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--class-path", "doesNotExist",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--class-path", "doesNotExist.jar",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--cmds", "doesNotExist",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--config", "doesNotExist",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--libs", "doesNotExist",
+                           "output.jmod") );
+
+        String errMsg = "Error: path not found: doesNotExist";
+        return tasks.stream().map(t -> new Object[] {t, errMsg} )
+                             .toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "pathDoesNotExist")
+    public void testPathDoesNotExist(Supplier<JmodResult> supplier,
+                                     String errMsg)
+    {
+        supplier.get()
+                .assertFailure()
+                .resultChecker(r -> {
+                    assertContains(r.output, errMsg);
+                });
+    }
+
+    @DataProvider(name = "partOfPathDoesNotExist")
+    public Object[][] partOfPathDoesNotExist() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        FileUtils.deleteFileIfExistsWithRetry(Paths.get("doesNotExist"));
+
+        Path emptyDir = Paths.get("empty");
+        if (Files.exists(emptyDir))
+            FileUtils.deleteFileTreeWithRetry(emptyDir);
+        Files.createDirectory(emptyDir);
+
+        List<Supplier<JmodResult>> tasks = Arrays.asList(
+            () -> jmod("create",
+                       "--hash-dependencies", "anyPattern",
+                       "--modulepath","empty" + pathSeparator + "doesNotExist",
+                       "output.jmod"),
+            () -> jmod("create",
+                       "--class-path", "empty" + pathSeparator + "doesNotExist",
+                       "output.jmod"),
+            () -> jmod("create",
+                       "--class-path", "empty" + pathSeparator + "doesNotExist.jar",
+                       "output.jmod"),
+            () -> jmod("create",
+                       "--cmds", "empty" + pathSeparator + "doesNotExist",
+                       "output.jmod"),
+            () -> jmod("create",
+                       "--config", "empty" + pathSeparator + "doesNotExist",
+                       "output.jmod"),
+            () -> jmod("create",
+                       "--libs", "empty" + pathSeparator + "doesNotExist",
+                       "output.jmod") );
+
+        String errMsg = "Error: path not found: doesNotExist";
+        return tasks.stream().map(t -> new Object[] {t, errMsg} )
+                             .toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "partOfPathDoesNotExist")
+    public void testPartOfPathNotExist(Supplier<JmodResult> supplier,
+                                       String errMsg)
+    {
+        supplier.get()
+                .assertFailure()
+                .resultChecker(r -> {
+                    assertContains(r.output, errMsg);
+                });
+    }
+
+    @DataProvider(name = "pathIsFile")
+    public Object[][] pathIsFile() throws IOException {
+        Path jmod = MODS_DIR.resolve("output.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path aFile = Paths.get("aFile.txt");
+        if (Files.exists(aFile) && !Files.isRegularFile(aFile))
+            throw new InternalError("Unexpected file:" + aFile);
+        else
+            Files.createFile(aFile);
+
+        List<Supplier<JmodResult>> tasks = Arrays.asList(
+                () -> jmod("create",
+                           "--class-path", "aFile.txt",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--modulepath", "aFile.txt",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--cmds", "aFile.txt",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--config", "aFile.txt",
+                           "output.jmod"),
+                () -> jmod("create",
+                           "--libs", "aFile.txt",
+                           "output.jmod") );
+
+        String errMsg = "Error: path must be a directory: aFile.txt";
+        Object[][] a = tasks.stream().map(t -> new Object[] {t, errMsg} )
+                                     .toArray(Object[][]::new);
+        a[0][1] = "invalid class path entry: aFile.txt";  // class path err msg
+        return a;
+    }
+
+    @Test(dataProvider = "pathIsFile")
+    public void testPathIsFile(Supplier<JmodResult> supplier,
+                               String errMsg)
+    {
+        supplier.get()
+                .assertFailure()
+                .resultChecker(r -> {
+                    assertContains(r.output, errMsg);
+                });
+    }
+
+    // ---
+
+    static boolean compileModule(String name, Path dest) throws IOException {
+        return CompilerUtils.compile(SRC_DIR.resolve(name), dest);
+    }
+
+    static void assertContains(String output, String subString) {
+        if (output.contains(subString))
+            assertTrue(true);
+        else
+            assertTrue(false,"Expected to find [" + subString + "], in output ["
+                             + output + "]");
+    }
+
+    static JmodResult jmod(String... args) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        System.out.println("jmod " + Arrays.asList(args));
+        int ec = jdk.tools.jmod.Main.run(args, ps);
+        return new JmodResult(ec, new String(baos.toByteArray(), UTF_8));
+    }
+
+    static class JmodResult {
+        final int exitCode;
+        final String output;
+
+        JmodResult(int exitValue, String output) {
+            this.exitCode = exitValue;
+            this.output = output;
+        }
+        JmodResult assertFailure() { assertTrue(exitCode != 0, output); return this; }
+        JmodResult resultChecker(Consumer<JmodResult> r) { r.accept(this); return this; }
+    }
+}
diff --git a/jdk/test/tools/jmod/JmodTest.java b/jdk/test/tools/jmod/JmodTest.java
new file mode 100644
index 0000000..01f2b23
--- /dev/null
+++ b/jdk/test/tools/jmod/JmodTest.java
@@ -0,0 +1,485 @@
+/**
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build jdk.testlibrary.FileUtils CompilerUtils
+ * @run testng JmodTest
+ * @summary Basic test for jmod
+ */
+
+import java.io.*;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Method;
+import java.nio.file.*;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import jdk.testlibrary.FileUtils;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static java.lang.module.ModuleDescriptor.Version;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.stream.Collectors.toSet;
+import static org.testng.Assert.*;
+
+public class JmodTest {
+
+    static final String TEST_SRC = System.getProperty("test.src", ".");
+    static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    static final Path EXPLODED_DIR = Paths.get("build");
+    static final Path MODS_DIR = Paths.get("jmods");
+
+    static final String CLASSES_PREFIX = "classes/";
+    static final String CMDS_PREFIX = "bin/";
+    static final String LIBS_PREFIX = "native/";
+    static final String CONFIGS_PREFIX = "conf/";
+
+    @BeforeTest
+    public void buildExplodedModules() throws IOException {
+        if (Files.exists(EXPLODED_DIR))
+            FileUtils.deleteFileTreeWithRetry(EXPLODED_DIR);
+
+        for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {
+            Path dir = EXPLODED_DIR.resolve(name);
+            assertTrue(compileModule(name, dir.resolve("classes")));
+            createCmds(dir.resolve("bin"));
+            createLibs(dir.resolve("lib"));
+            createConfigs(dir.resolve("conf"));
+        }
+
+        if (Files.exists(MODS_DIR))
+            FileUtils.deleteFileTreeWithRetry(MODS_DIR);
+        Files.createDirectories(MODS_DIR);
+    }
+
+    @Test
+    public void testList() throws IOException {
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+        jmod("create",
+             "--class-path", cp,
+             MODS_DIR.resolve("foo.jmod").toString())
+            .assertSuccess();
+
+        jmod("list",
+             MODS_DIR.resolve("foo.jmod").toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                // asserts dependent on the exact contents of foo
+                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");
+            });
+    }
+
+    @Test
+    public void testMainClass() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooMainClass.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        jmod("create",
+             "--class-path", cp,
+             "--main-class", "jdk.test.foo.Foo",
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                Optional<String> omc = getModuleDescriptor(jmod).mainClass();
+                assertTrue(omc.isPresent());
+                assertEquals(omc.get(), "jdk.test.foo.Foo");
+            });
+    }
+
+    @Test
+    public void testModuleVersion() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooVersion.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        jmod("create",
+             "--class-path", cp,
+             "--module-version", "5.4.3",
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                Optional<Version> ov = getModuleDescriptor(jmod).version();
+                assertTrue(ov.isPresent());
+                assertEquals(ov.get().toString(), "5.4.3");
+            });
+    }
+
+    @Test
+    public void testConfig() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooConfig.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
+
+        jmod("create",
+             "--class-path", cp.toString(),
+             "--config", cf.toString(),
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                try (Stream<String> s1 = findFiles(cf).map(p -> CONFIGS_PREFIX + p);
+                     Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
+                    Set<String> expectedFilenames = Stream.concat(s1, s2)
+                                                          .collect(toSet());
+                    assertJmodContent(jmod, expectedFilenames);
+                }
+            });
+    }
+
+    @Test
+    public void testCmds() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooCmds.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
+
+        jmod("create",
+             "--cmds", bp.toString(),
+             "--class-path", cp.toString(),
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                try (Stream<String> s1 = findFiles(bp).map(p -> CMDS_PREFIX + p);
+                     Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
+                    Set<String> expectedFilenames = Stream.concat(s1,s2)
+                                                          .collect(toSet());
+                    assertJmodContent(jmod, expectedFilenames);
+                }
+            });
+    }
+
+    @Test
+    public void testLibs() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooLibs.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
+
+        jmod("create",
+             "--libs=", lp.toString(),
+             "--class-path", cp.toString(),
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
+                     Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p)) {
+                    Set<String> expectedFilenames = Stream.concat(s1,s2)
+                                                          .collect(toSet());
+                    assertJmodContent(jmod, expectedFilenames);
+                }
+            });
+    }
+
+    @Test
+    public void testAll() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooAll.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
+        Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
+        Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
+
+        jmod("create",
+             "--conf", cf.toString(),
+             "--cmds=", bp.toString(),
+             "--libs=", lp.toString(),
+             "--class-path", cp.toString(),
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
+                     Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p);
+                     Stream<String> s3 = findFiles(bp).map(p -> CMDS_PREFIX + p);
+                     Stream<String> s4 = findFiles(cf).map(p -> CONFIGS_PREFIX + p)) {
+                    Set<String> expectedFilenames = Stream.concat(Stream.concat(s1,s2),
+                                                                  Stream.concat(s3, s4))
+                                                          .collect(toSet());
+                    assertJmodContent(jmod, expectedFilenames);
+                }
+            });
+    }
+
+    @Test
+    public void testExcludes() throws IOException {
+        Path jmod = MODS_DIR.resolve("fooLibs.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
+
+        jmod("create",
+             "--libs=", lp.toString(),
+             "--class-path", cp.toString(),
+             "--exclude", "**internal**",
+             "--exclude", "first.so",
+             jmod.toString())
+             .assertSuccess()
+             .resultChecker(r -> {
+                 Set<String> expectedFilenames = new HashSet<>();
+                 expectedFilenames.add(CLASSES_PREFIX + "module-info.class");
+                 expectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/Foo.class");
+                 expectedFilenames.add(LIBS_PREFIX + "second.so");
+                 expectedFilenames.add(LIBS_PREFIX + "third/third.so");
+                 assertJmodContent(jmod, expectedFilenames);
+
+                 Set<String> unexpectedFilenames = new HashSet<>();
+                 unexpectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/internal/Message.class");
+                 unexpectedFilenames.add(LIBS_PREFIX + "first.so");
+                 assertJmodDoesNotContain(jmod, unexpectedFilenames);
+             });
+    }
+
+    @Test
+    public void describe() throws IOException {
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+        jmod("create",
+             "--class-path", cp,
+              MODS_DIR.resolve("describeFoo.jmod").toString())
+             .assertSuccess();
+
+        jmod("describe",
+             MODS_DIR.resolve("describeFoo.jmod").toString())
+             .assertSuccess()
+             .resultChecker(r -> {
+                 // Expect similar output: "foo,  requires mandated java.base
+                 // exports jdk.test.foo,  conceals 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");
+                 assertTrue(p.matcher(r.output).find(),
+                           "Expecting to find \"exports ..., conceals ...\"" +
+                                "in output, but did not: [" + r.output + "]");
+             });
+    }
+
+    @Test
+    public void testVersion() {
+        jmod("--version")
+            .assertSuccess()
+            .resultChecker(r -> {
+                assertContains(r.output, System.getProperty("java.version"));
+            });
+    }
+
+    @Test
+    public void testHelp() {
+        jmod("--help")
+            .assertSuccess()
+            .resultChecker(r ->
+                assertTrue(r.output.startsWith("Usage: jmod"), "Help not printed")
+            );
+    }
+
+    @Test
+    public void testTmpFileAlreadyExists() throws IOException {
+        // Implementation detail: jmod tool creates <jmod-file>.tmp
+        // Ensure that there are no problems if existing
+
+        Path jmod = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod");
+        Path tmp = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod.tmp");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        FileUtils.deleteFileIfExistsWithRetry(tmp);
+        Files.createFile(tmp);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        jmod("create",
+             "--class-path", cp,
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r ->
+                assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp)
+            );
+    }
+
+    @Test
+    public void testTmpFileRemoved() throws IOException {
+        // Implementation detail: jmod tool creates <jmod-file>.tmp
+        // Ensure that it is removed in the event of a failure.
+        // The failure in this case is a class in the unnamed package.
+
+        Path jmod = MODS_DIR.resolve("testTmpFileRemoved.jmod");
+        Path tmp = MODS_DIR.resolve("testTmpFileRemoved.jmod.tmp");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        FileUtils.deleteFileIfExistsWithRetry(tmp);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
+                    EXPLODED_DIR.resolve("foo").resolve("classes")
+                                .resolve("jdk").resolve("test").resolve("foo").toString();
+
+        jmod("create",
+             "--class-path", cp,
+             jmod.toString())
+             .assertFailure()
+             .resultChecker(r -> {
+                 assertContains(r.output, "unnamed package");
+                 assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp);
+             });
+    }
+
+    // ---
+
+    static boolean compileModule(String name, Path dest) throws IOException {
+        return CompilerUtils.compile(SRC_DIR.resolve(name), dest);
+    }
+
+    static void assertContains(String output, String subString) {
+        if (output.contains(subString))
+            assertTrue(true);
+        else
+            assertTrue(false,"Expected to find [" + subString + "], in output ["
+                           + output + "]" + "\n");
+    }
+
+    static ModuleDescriptor getModuleDescriptor(Path jmod) {
+        ClassLoader cl = ClassLoader.getSystemClassLoader();
+        try (FileSystem fs = FileSystems.newFileSystem(jmod, cl)) {
+            String p = "/classes/module-info.class";
+            try (InputStream is = Files.newInputStream(fs.getPath(p))) {
+                return ModuleDescriptor.read(is);
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    static Stream<String> findFiles(Path dir) {
+        try {
+            return Files.find(dir, Integer.MAX_VALUE, (p, a) -> a.isRegularFile())
+                        .map(dir::relativize)
+                        .map(Path::toString)
+                        .map(p -> p.replace(File.separator, "/"));
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
+        }
+    }
+
+    static Set<String> getJmodContent(Path jmod) {
+        JmodResult r = jmod("list", jmod.toString()).assertSuccess();
+        return Stream.of(r.output.split("\r?\n")).collect(toSet());
+    }
+
+    static void assertJmodContent(Path jmod, Set<String> expected) {
+        Set<String> actual = getJmodContent(jmod);
+        if (!Objects.equals(actual, expected)) {
+            Set<String> unexpected = new HashSet<>(actual);
+            unexpected.removeAll(expected);
+            Set<String> notFound = new HashSet<>(expected);
+            notFound.removeAll(actual);
+            StringBuilder sb = new StringBuilder();
+            sb.append("Unexpected but found:\n");
+            unexpected.forEach(s -> sb.append("\t" + s + "\n"));
+            sb.append("Expected but not found:\n");
+            notFound.forEach(s -> sb.append("\t" + s + "\n"));
+            assertTrue(false, "Jmod content check failed.\n" + sb.toString());
+        }
+    }
+
+    static void assertJmodDoesNotContain(Path jmod, Set<String> unexpectedNames) {
+        Set<String> actual = getJmodContent(jmod);
+        Set<String> unexpected = new HashSet<>();
+        for (String name : unexpectedNames) {
+            if (actual.contains(name))
+                unexpected.add(name);
+        }
+        if (!unexpected.isEmpty()) {
+            StringBuilder sb = new StringBuilder();
+            for (String s : unexpected)
+                sb.append("Unexpected but found: " + s + "\n");
+            sb.append("In :");
+            for (String s : actual)
+                sb.append("\t" + s + "\n");
+            assertTrue(false, "Jmod content check failed.\n" + sb.toString());
+        }
+    }
+
+    static JmodResult jmod(String... args) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        System.out.println("jmod " + Arrays.asList(args));
+        int ec = jdk.tools.jmod.Main.run(args, ps);
+        return new JmodResult(ec, new String(baos.toByteArray(), UTF_8));
+    }
+
+    static class JmodResult {
+        final int exitCode;
+        final String output;
+
+        JmodResult(int exitValue, String output) {
+            this.exitCode = exitValue;
+            this.output = output;
+        }
+        JmodResult assertSuccess() { assertTrue(exitCode == 0, output); return this; }
+        JmodResult assertFailure() { assertTrue(exitCode != 0, output); return this; }
+        JmodResult resultChecker(Consumer<JmodResult> r) { r.accept(this); return this; }
+    }
+
+    static void createCmds(Path dir) throws IOException {
+        List<String> files = Arrays.asList(
+                "first", "second", "third" + File.separator + "third");
+        createFiles(dir, files);
+    }
+
+    static void createLibs(Path dir) throws IOException {
+        List<String> files = Arrays.asList(
+                "first.so", "second.so", "third" + File.separator + "third.so");
+        createFiles(dir, files);
+    }
+
+    static void createConfigs(Path dir) throws IOException {
+        List<String> files = Arrays.asList(
+                "first.cfg", "second.cfg", "third" + File.separator + "third.cfg");
+        createFiles(dir, files);
+    }
+
+    static void createFiles(Path dir, List<String> filenames) throws IOException {
+        for (String name : filenames) {
+            Path file = dir.resolve(name);
+            Files.createDirectories(file.getParent());
+            Files.createFile(file);
+            try (OutputStream os  = Files.newOutputStream(file)) {
+                os.write("blahblahblah".getBytes(UTF_8));
+            }
+        }
+    }
+
+    // Standalone entry point.
+    public static void main(String[] args) throws Throwable {
+        JmodTest test = new JmodTest();
+        test.buildExplodedModules();
+        for (Method m : JmodTest.class.getDeclaredMethods()) {
+            if (m.getAnnotation(Test.class) != null) {
+                System.out.println("Invoking " + m.getName());
+                m.invoke(test);
+            }
+        }
+    }
+}
diff --git a/jdk/test/tools/jmod/src/foo/jdk/test/foo/Foo.java b/jdk/test/tools/jmod/src/foo/jdk/test/foo/Foo.java
new file mode 100644
index 0000000..2c56159
--- /dev/null
+++ b/jdk/test/tools/jmod/src/foo/jdk/test/foo/Foo.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.foo;
+
+public class Foo { }
diff --git a/jdk/test/tools/jmod/src/foo/jdk/test/foo/internal/Message.java b/jdk/test/tools/jmod/src/foo/jdk/test/foo/internal/Message.java
new file mode 100644
index 0000000..298a4fc
--- /dev/null
+++ b/jdk/test/tools/jmod/src/foo/jdk/test/foo/internal/Message.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.foo.internal;
+
+public class Message  {
+    public static String get() {
+        return "Hello World!!!";
+    }
+}
diff --git a/jdk/test/tools/jmod/src/foo/module-info.java b/jdk/test/tools/jmod/src/foo/module-info.java
new file mode 100644
index 0000000..b46afa0
--- /dev/null
+++ b/jdk/test/tools/jmod/src/foo/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module foo {
+    exports jdk.test.foo;
+}
diff --git a/jdk/test/tools/launcher/MiscTests.java b/jdk/test/tools/launcher/MiscTests.java
index 1a03cc9..c4e1f0b 100644
--- a/jdk/test/tools/launcher/MiscTests.java
+++ b/jdk/test/tools/launcher/MiscTests.java
@@ -31,29 +31,71 @@
 
 
 import java.io.File;
-import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 public class MiscTests extends TestHelper {
 
-    // 6856415: Checks to ensure that proper exceptions are thrown by java
-    static void test6856415() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("public static void main(String... args) {\n");
-        sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11();\n");
-        sb.append("java.security.Security.insertProviderAt(p, 1);\n");
-        sb.append("}");
+    /**
+     * Test with class path set on the command line via -Djava.class.path
+     */
+    static void testWithClassPathSetViaProperty() throws IOException {
+        final String mainClass = "Foo";
+
+        File source = new File(mainClass + ".java");
+
+        List<String> scratch = new ArrayList<>();
+        scratch.add("public class Foo {");
+        scratch.add("public static void main(String... args) {");
+        scratch.add("}");
+        scratch.add("}");
+        createFile(source, scratch);
+
+        compile(mainClass + ".java");
+
+        String dir = new File(mainClass + ".class").getAbsoluteFile().getParent();
+        TestResult tr = doExec(javaCmd, "-Djava.class.path=" + dir, mainClass);
+        for (String s : tr.testOutput) {
+            System.out.println(s);
+        }
+    }
+
+    /**
+     * 6856415: Checks to ensure that proper exceptions are thrown by java
+     */
+    static void test6856415() throws IOException {
+
+        final String mainClass = "Foo6856415";
+        final String exportOpts
+            = "-XaddExports:jdk.crypto.pkcs11/sun.security.pkcs11=ALL-UNNAMED";
+
+        List<String> scratch = new ArrayList<>();
+        scratch.add("public class Foo6856415 {");
+        scratch.add("public static void main(String... args) {");
+        scratch.add("java.security.Provider p = new sun.security.pkcs11.SunPKCS11();");
+        scratch.add("java.security.Security.insertProviderAt(p, 1);");
+        scratch.add("}");
+        scratch.add("}");
+        createFile(new File(mainClass + ".java"), scratch);
+
+        compile(mainClass + ".java", exportOpts);
+
         File testJar = new File("Foo.jar");
         testJar.delete();
-        try {
-            createJar(testJar, sb.toString());
-        } catch (FileNotFoundException fnfe) {
-            throw new RuntimeException(fnfe);
-        }
+        String jarArgs[] = {
+            (debug) ? "cvfe" : "cfe",
+            testJar.getAbsolutePath(),
+            mainClass,
+            mainClass + ".class"
+        };
+        createJar(jarArgs);
+
         TestResult tr = doExec(javaCmd,
                 "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
         for (String s : tr.testOutput) {
             System.out.println(s);
-    }
+        }
         if (!tr.contains("java.security.AccessControlException:" +
                 " access denied (\"java.lang.RuntimePermission\"" +
                 " \"accessClassInPackage.sun.security.pkcs11\")")) {
@@ -61,7 +103,8 @@
         }
     }
 
-    public static void main(String... args) {
+    public static void main(String... args) throws IOException {
+        testWithClassPathSetViaProperty();
         test6856415();
         if (testExitValue != 0) {
             throw new Error(testExitValue + " tests failed");
diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java
index f01931d..bff769a 100644
--- a/jdk/test/tools/launcher/ToolsOpts.java
+++ b/jdk/test/tools/launcher/ToolsOpts.java
@@ -38,8 +38,6 @@
 import java.util.List;
 
 public class ToolsOpts extends TestHelper {
-    static final String JBCP_PREPEND = "-J-Xbootclasspath/p:";
-    private static File testJar = null;
     static String[][] optionPatterns = {
         {"-J-Xmx128m"},
         {"-J-version"},
@@ -75,14 +73,10 @@
         {"option1", "-J-version", "-J-XshowSettings:vm", "option2"},};
 
     static void init() throws IOException {
-        if (testJar != null) {
-            return;
-        }
 
         // A tool which simulates com.sun.tools.javac.Main argument processing,
         // intercepts options passed via the javac launcher.
         final String mainJava = "Main" + JAVA_FILE_EXT;
-        testJar = new File("test" + JAR_FILE_EXT);
         List<String> contents = new ArrayList<>();
         contents.add("package com.sun.tools.javac;");
         contents.add("public class Main {");
@@ -95,10 +89,10 @@
         contents.add("}\n");
         createFile(new File(mainJava), contents);
 
-        // compile and jar Main.java into test.jar
-        compile("-d", ".", mainJava);
-            createJar("cvf", testJar.getAbsolutePath(), "com");
-        }
+        // compile Main.java into directory to override classes in jdk.compiler
+        new File("jdk.compiler").mkdir();
+        compile("-Xmodule:jdk.compiler", "-d", "jdk.compiler", mainJava);
+    }
 
     static void pass(String msg) {
         System.out.println("pass: " + msg);
@@ -156,30 +150,29 @@
     static void runTestOptions() throws IOException {
         init();
         TestResult tr = null;
-        String sTestJar = testJar.getAbsolutePath();
         int jpos = -1;
         for (String arg[] : optionPatterns) {
             jpos = indexOfJoption(arg);
             //Build a cmd string for output in results reporting.
-            String cmdString = javacCmd + " " + JBCP_PREPEND + sTestJar;
+            String cmdString = javacCmd + " -J-Xpatch:.";
             for (String opt : arg) {
                 cmdString = cmdString.concat(" " + opt);
             }
             switch (arg.length) {
                 case 1:
-                    tr = doExec(javacCmd, JBCP_PREPEND + sTestJar,
+                    tr = doExec(javacCmd, "-J-Xpatch:.",
                             arg[0]);
                     break;
                 case 2:
-                    tr = doExec(javacCmd, JBCP_PREPEND + sTestJar,
+                    tr = doExec(javacCmd, "-J-Xpatch:.",
                             arg[0], arg[1]);
                     break;
                 case 3:
-                    tr = doExec(javacCmd, JBCP_PREPEND + sTestJar,
+                    tr = doExec(javacCmd, "-J-Xpatch:.",
                             arg[0], arg[1], arg[2]);
                     break;
                 case 4:
-                    tr = doExec(javacCmd, JBCP_PREPEND + sTestJar,
+                    tr = doExec(javacCmd, "-J-Xpatch:.",
                             arg[0], arg[1], arg[2], arg[3]);
                     break;
                 default:
diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java
index 4fd933c..08a18bd 100644
--- a/jdk/test/tools/launcher/VersionCheck.java
+++ b/jdk/test/tools/launcher/VersionCheck.java
@@ -85,7 +85,9 @@
         "jdeps",
         "jimage",
         "jinfo",
+        "jlink",
         "jmap",
+        "jmod",
         "jmc",
         "jmc.ini",
         "jps",
diff --git a/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java
new file mode 100644
index 0000000..8f92cf2
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java
@@ -0,0 +1,253 @@
+/*
+ * 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
+ * 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 AddExportsTest CompilerUtils jdk.testlibrary.*
+ * @run testng AddExportsTest
+ * @summary Basic tests for java -XaddExports
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class AddExportsTest {
+
+    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 MODS_DIR = Paths.get("mods");
+    private static final Path UPGRADE_MODS_DIRS = Paths.get("upgrademods");
+
+    // test module m1 that uses Unsafe
+    private static final String TEST1_MODULE = "m1";
+    private static final String TEST1_MAIN_CLASS = "jdk.test1.Main";
+
+    // test module m2 uses java.transaction internals
+    private static final String TEST2_MODULE = "m2";
+    private static final String TEST2_MAIN_CLASS = "jdk.test2.Main";
+
+    // test module m3 uses m4 internals
+    private static final String TEST3_MODULE = "m3";
+    private static final String TEST3_MAIN_CLASS = "jdk.test3.Main";
+    private static final String TEST4_MODULE = "m4";
+
+
+    @BeforeTest
+    public void compileTestModules() throws Exception {
+
+        // javac -d mods/m1 src/m1/**
+        boolean compiled = CompilerUtils.compile(
+                SRC_DIR.resolve(TEST1_MODULE),
+                MODS_DIR.resolve(TEST1_MODULE),
+                "-XaddExports:java.base/sun.misc=m1");
+        assertTrue(compiled, "module " + TEST1_MODULE + " did not compile");
+
+        // javac -d upgrademods/java.transaction src/java.transaction/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("java.transaction"),
+                UPGRADE_MODS_DIRS.resolve("java.transaction"));
+        assertTrue(compiled, "module java.transaction did not compile");
+
+        // javac -upgrademodulepath upgrademods -d mods/m2 src/m2/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve(TEST2_MODULE),
+                MODS_DIR.resolve(TEST2_MODULE),
+                "-upgrademodulepath", UPGRADE_MODS_DIRS.toString(),
+                "-XaddExports:java.transaction/javax.transaction.internal=m2");
+        assertTrue(compiled, "module " + TEST2_MODULE + " did not compile");
+
+        // javac -d mods/m3 src/m3/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve(TEST3_MODULE),
+                MODS_DIR.resolve(TEST3_MODULE));
+        assertTrue(compiled, "module " + TEST3_MODULE + " did not compile");
+
+        // javac -d mods/m4 src/m4/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve(TEST4_MODULE),
+                MODS_DIR.resolve(TEST4_MODULE));
+        assertTrue(compiled, "module " + TEST4_MODULE + " did not compile");
+    }
+
+    /**
+     * Sanity check with -version
+     */
+    public void testSanity() throws Exception {
+
+        int exitValue
+            =  executeTestJava("-XaddExports:java.base/sun.reflect=ALL-UNNAMED",
+                               "-version")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Run class path application that uses sun.misc.Unsafe
+     */
+    public void testUnnamedModule() throws Exception {
+
+        // java -XaddExports:java.base/sun.misc=ALL-UNNAMED \
+        //      -cp mods/$TESTMODULE jdk.test.UsesUnsafe
+
+        String classpath = MODS_DIR.resolve(TEST1_MODULE).toString();
+        int exitValue
+            = executeTestJava("-XaddExports:java.base/sun.misc=ALL-UNNAMED",
+                              "-cp", classpath,
+                              TEST1_MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Run named module that uses sun.misc.Unsafe
+     */
+    public void testNamedModule() throws Exception {
+
+        //  java -XaddExports:java.base/sun.misc=test \
+        //       -mp mods -m $TESTMODULE/$MAIN_CLASS
+
+        String mid = TEST1_MODULE + "/" + TEST1_MAIN_CLASS;
+        int exitValue =
+            executeTestJava("-XaddExports:java.base/sun.misc=" + TEST1_MODULE,
+                            "-mp", MODS_DIR.toString(),
+                            "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Test -XaddExports with upgraded module
+     */
+    public void testWithUpgradedModule() throws Exception {
+
+        // java -XaddExports:java.transaction/javax.transaction.internal=m2
+        //      -upgrademodulepath upgrademods -mp mods -m ...
+        String mid = TEST2_MODULE + "/" + TEST2_MAIN_CLASS;
+        int exitValue = executeTestJava(
+                "-XaddExports:java.transaction/javax.transaction.internal=m2",
+                "-upgrademodulepath", UPGRADE_MODS_DIRS.toString(),
+                "-mp", MODS_DIR.toString(),
+                "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Test -XaddExports with module that is added to the set of root modules
+     * with -addmods.
+     */
+    public void testWithAddMods() throws Exception {
+
+        // java -XaddExports:m4/jdk.test4=m3 -mp mods -m ...
+        String mid = TEST3_MODULE + "/" + TEST3_MAIN_CLASS;
+        int exitValue = executeTestJava(
+                "-XaddExports:m4/jdk.test4=m3",
+                "-mp", MODS_DIR.toString(),
+                "-addmods", TEST4_MODULE,
+                "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * -XaddExports can only be specified once
+     */
+    public void testWithDuplicateOption() throws Exception {
+
+        int exitValue
+            =  executeTestJava("-XaddExports:java.base/sun.reflect=ALL-UNNAMED",
+                               "-XaddExports:java.base/sun.reflect=ALL-UNNAMED",
+                               "-version")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .shouldContain("specified more than once")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Exercise -XaddExports with bad values
+     */
+    @Test(dataProvider = "badvalues")
+    public void testWithBadValue(String value, String ignore) throws Exception {
+
+        //  -XaddExports:$VALUE -version
+        int exitValue =
+            executeTestJava("-XaddExports:" + value,
+                            "-version")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+    @DataProvider(name = "badvalues")
+    public Object[][] badValues() {
+        return new Object[][]{
+
+            { "java.base/sun.misc",                  null }, // missing target
+            { "java.base/sun.misc=sun.monkey",       null }, // unknown target
+            { "java.monkey/sun.monkey=ALL-UNNAMED",  null }, // unknown module
+            { "java.base/sun.monkey=ALL-UNNAMED",    null }, // unknown package
+            { "java.monkey/sun.monkey=ALL-UNNAMED",  null }, // unknown module/package
+            { "java.base=ALL-UNNAMED",               null }, // missing package
+            { "java.base/=ALL-UNNAMED",              null }  // missing package
+
+        };
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/Transaction.java b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/Transaction.java
new file mode 100644
index 0000000..44bb019
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/Transaction.java
@@ -0,0 +1,27 @@
+/*
+ * 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 javax.transaction;
+
+public class Transaction {
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/internal/Helper.java b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/internal/Helper.java
new file mode 100644
index 0000000..f7a38cc6b0
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/javax/transaction/internal/Helper.java
@@ -0,0 +1,27 @@
+/*
+ * 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 javax.transaction.internal;
+
+public class Helper {
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/java.transaction/module-info.java b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/module-info.java
new file mode 100644
index 0000000..95ddcb7
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/java.transaction/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 java.transaction {
+    exports javax.transaction;
+}
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
new file mode 100644
index 0000000..a047c91
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java
@@ -0,0 +1,35 @@
+/**
+ * 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 jdk.test1;
+
+import java.lang.reflect.Field;
+import sun.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);
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m1/module-info.java b/jdk/test/tools/launcher/modules/addexports/src/m1/module-info.java
new file mode 100644
index 0000000..16490ed
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+module m1 {
+}
+
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java b/jdk/test/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java
new file mode 100644
index 0000000..9699363
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m2/jdk/test2/Main.java
@@ -0,0 +1,32 @@
+/**
+ * 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 jdk.test2;
+
+import javax.transaction.internal.Helper;
+
+public class Main {
+    public static void main(String[] args) {
+        Helper h = new Helper();
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m2/module-info.java b/jdk/test/tools/launcher/modules/addexports/src/m2/module-info.java
new file mode 100644
index 0000000..527a4db
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    requires java.transaction;
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m3/jdk/test3/Main.java b/jdk/test/tools/launcher/modules/addexports/src/m3/jdk/test3/Main.java
new file mode 100644
index 0000000..068d587
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m3/jdk/test3/Main.java
@@ -0,0 +1,32 @@
+/**
+ * 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 jdk.test3;
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+        Class<?> c = Class.forName("jdk.test4.Type");
+        Main.class.getModule().addReads(c.getModule());
+        Object o = c.newInstance();
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m3/module-info.java b/jdk/test/tools/launcher/modules/addexports/src/m3/module-info.java
new file mode 100644
index 0000000..a92b756
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m3/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 {
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m4/jdk/test4/Type.java b/jdk/test/tools/launcher/modules/addexports/src/m4/jdk/test4/Type.java
new file mode 100644
index 0000000..6d5f414
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m4/jdk/test4/Type.java
@@ -0,0 +1,29 @@
+/*
+ * 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 jdk.test4;
+
+public class Type {
+    public Type() { }
+}
+
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m4/module-info.java b/jdk/test/tools/launcher/modules/addexports/src/m4/module-info.java
new file mode 100644
index 0000000..2544650
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/src/m4/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * 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 m4 {
+}
diff --git a/jdk/test/tools/launcher/modules/addmods/AddModsTest.java b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java
new file mode 100644
index 0000000..a65c3d4
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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
+ * 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.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build AddModsTest CompilerUtils jdk.testlibrary.*
+ * @run testng AddModsTest
+ * @summary Basic test for java -addmods
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class AddModsTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    // the module name of the library module
+    private static final String LIB_MODULE = "lib";
+
+    // application source directory
+    private static final String APP_SRC = "app";
+
+    // application is compiled to classes
+    private static final Path CLASSES_DIR = Paths.get("classes");
+
+    // application main class
+    private static final String MAIN_CLASS = "app.Main";
+
+
+    @BeforeTest
+    public void compile() throws Exception {
+
+        // javac -d mods/$LIB_MODULE src/$LIB_MODULE/**
+        boolean compiled = CompilerUtils.compile(
+            SRC_DIR.resolve(LIB_MODULE),
+            MODS_DIR.resolve(LIB_MODULE)
+        );
+        assertTrue(compiled, "library module did not compile");
+
+        // javac -d classes -mp mods src/$APP_DIR/**
+        compiled = CompilerUtils.compile(
+            SRC_DIR.resolve(APP_SRC),
+            CLASSES_DIR,
+            "-mp", MODS_DIR.toString(),
+            "-addmods", LIB_MODULE
+        );
+        assertTrue(compiled, "app did not compile");
+    }
+
+
+    /**
+     * Basic test of -addmods ALL-SYSTEM, using the output of -listmods to
+     * check that the a sample of the system modules are resolved.
+     */
+    public void testAddSystemModules() throws Exception {
+
+        executeTestJava("-addmods", "ALL-SYSTEM",
+                        "-listmods",
+                        "-m", "java.base")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .shouldContain("java.sql")
+            .shouldContain("java.corba");
+
+        // no exit value to check as -m java.base will likely fail
+    }
+
+
+    /**
+     * Run application on class path that makes use of module on the
+     * application module path. Uses {@code -addmods lib}
+     */
+    public void testRunWithAddMods() throws Exception {
+
+        // java -mp mods -addmods lib -cp classes app.Main
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", LIB_MODULE,
+                              "-cp", CLASSES_DIR.toString(),
+                              MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+    /**
+     * Run application on class path that makes use of module on the
+     * application module path. Uses {@code -addmods ALL-MODULE-PATH}.
+     */
+    public void testAddAllModulePath() throws Exception {
+
+        // java -mp mods -addmods lib -cp classes app.Main
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", "ALL-MODULE-PATH",
+                              "-cp", CLASSES_DIR.toString(),
+                              MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+
+    /**
+     * Run application on class path that makes use of module on the
+     * application module path. Does not use -addmods and so will
+     * fail at run-time.
+     */
+    public void testRunMissingAddMods() throws Exception {
+
+        // java -mp mods -cp classes app.Main
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-cp", CLASSES_DIR.toString(),
+                              MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        // CNFE or other error/exception
+        assertTrue(exitValue != 0);
+
+    }
+
+
+    /**
+     * Attempt to run with a bad module name specified to -addmods
+     */
+    public void testRunWithBadAddMods() throws Exception {
+
+        // java -mp mods -addmods,DoesNotExist lib -cp classes app.Main
+        int exitValue
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-addmods", LIB_MODULE + ",DoesNotExist",
+                              "-cp", CLASSES_DIR.toString(),
+                              MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/addmods/src/app/Main.java b/jdk/test/tools/launcher/modules/addmods/src/app/Main.java
new file mode 100644
index 0000000..be903e5
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addmods/src/app/Main.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package app;
+
+import jdk.lib.Util;
+
+public class Main {
+    public static void main(String[] args) {
+        Object obj = Util.makeObject();
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java b/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java
new file mode 100644
index 0000000..682a229
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package jdk.lib;
+
+public class Util {
+    private Util() { }
+
+    public static Object makeObject() {
+        return new Object();
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java b/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java
new file mode 100644
index 0000000..16dae96
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 lib {
+    exports jdk.lib;
+}
diff --git a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java
new file mode 100644
index 0000000..3bcf4bf
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build AddReadsTest CompilerUtils jdk.testlibrary.*
+ * @run testng AddReadsTest
+ * @summary Basic tests for java -XaddReads
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.testlibrary.OutputAnalyzer;
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * The tests consists of two modules: m1 and junit.
+ * Code in module m1 calls into code in module junit but the module-info.java
+ * does not have a 'requires'. Instead a read edge is added via the command
+ * line option -XaddReads.
+ */
+
+@Test
+public class AddReadsTest {
+
+    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");
+
+    private static final String MAIN = "m1/p.Main";
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+
+        // javac -d classes src/junit/**
+        assertTrue(CompilerUtils
+            .compile(SRC_DIR.resolve("junit"), CLASSES_DIR));
+
+        // javac -d mods/m1 -cp classes/ src/m1/**
+        assertTrue(CompilerUtils
+            .compile(SRC_DIR.resolve("m1"),
+                    MODS_DIR.resolve("m1"),
+                    "-cp", CLASSES_DIR.toString(),
+                    "-XaddReads:m1=ALL-UNNAMED"));
+
+        // jar cf mods/junit.jar -C classes .
+        JarUtils.createJarFile(MODS_DIR.resolve("junit.jar"), CLASSES_DIR);
+
+    }
+
+    private OutputAnalyzer run(String... options) throws Exception {
+        return executeTestJava(options)
+            .outputTo(System.out)
+            .errorTo(System.out);
+    }
+
+
+    /**
+     * Run with junit as a module on the module path.
+     */
+    public void testJUnitOnModulePath() throws Exception {
+
+        // java -mp mods -addmods junit -XaddReads:m1=junit -m ..
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                  "-addmods", "junit",
+                  "-XaddReads:m1=junit",
+                  "-m", MAIN)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Exercise -XaddReads:m1=ALL-UNNAMED by running with junit on the
+     * class path.
+     */
+    public void testJUnitOnClassPath() throws Exception {
+
+        // java -mp mods -cp mods/junit.jar -XaddReads:m1=ALL-UNNAMED -m ..
+        String cp = MODS_DIR.resolve("junit.jar").toString();
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                  "-cp", cp,
+                  "-XaddReads:m1=ALL-UNNAMED",
+                  "-m", MAIN)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Run with junit as a module on the module path but without -XaddReads.
+     */
+    public void testJUnitOnModulePathMissingAddReads() throws Exception {
+        // java -mp mods -addmods junit -m ..
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                  "-addmods", "junit",
+                  "-m", MAIN)
+                .shouldContain("IllegalAccessError")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Run with junit on the class path but without -XaddReads.
+     */
+    public void testJUnitOnClassPathMissingAddReads() throws Exception {
+        // java -mp mods -cp mods/junit.jar -m ..
+        String cp = MODS_DIR.resolve("junit.jar").toString();
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                  "-cp", cp,
+                  "-m", MAIN)
+                .shouldContain("IllegalAccessError")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Exercise -XaddReads with a more than one source module.
+     */
+    public void testJUnitWithMultiValueOption() throws Exception {
+
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                  "-addmods", "java.xml,junit",
+                  "-XaddReads:m1=java.xml,junit",
+                  "-m", MAIN)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Exercise -XaddReads where the target module is specified more than once
+     */
+    public void testWithTargetSpecifiedManyTimes() throws Exception {
+
+        int exitValue
+            = run("-mp", MODS_DIR.toString(),
+                "-addmods", "java.xml,junit",
+                "-XaddReads:m1=java.xml",
+                "-XaddReads:m1=junit",
+                "-m", MAIN)
+                .shouldContain("specified more than once")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Exercise -XaddReads with bad values
+     */
+    @Test(dataProvider = "badvalues")
+    public void testWithBadValue(String value, String ignore) throws Exception {
+
+        //  -XaddExports:$VALUE -version
+        assertTrue(run("-XaddReads:" + value, "-version").getExitValue() != 0);
+    }
+
+    @DataProvider(name = "badvalues")
+    public Object[][] badValues() {
+        return new Object[][]{
+
+            { "java.base",                  null }, // missing source
+            { "java.monkey=java.base",      null }, // unknown module
+            { "java.base=sun.monkey",       null }, // unknown source
+
+        };
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addreads/src/junit/org/junit/Assert.java b/jdk/test/tools/launcher/modules/addreads/src/junit/org/junit/Assert.java
new file mode 100644
index 0000000..a36ce18
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addreads/src/junit/org/junit/Assert.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.junit;
+
+public class Assert {
+    public static void assertEquals(Object o1, Object o2) {
+        if (!o1.equals(o2)) throw new RuntimeException();
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/addreads/src/m1/module-info.java b/jdk/test/tools/launcher/modules/addreads/src/m1/module-info.java
new file mode 100644
index 0000000..1c15fc5
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addreads/src/m1/module-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 { }
diff --git a/jdk/test/tools/launcher/modules/addreads/src/m1/p/Main.java b/jdk/test/tools/launcher/modules/addreads/src/m1/p/Main.java
new file mode 100644
index 0000000..a1bc1fd
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addreads/src/m1/p/Main.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+
+public class Main {
+    public static void main(String[] args) {
+        Object o = new Object();
+        assertEquals(o, o);
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/basic/BasicTest.java b/jdk/test/tools/launcher/modules/basic/BasicTest.java
new file mode 100644
index 0000000..1c2cf23
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/basic/BasicTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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
+ * 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.jartool/sun.tools.jar
+ *          jdk.jlink/jdk.tools.jmod
+ *          jdk.compiler
+ * @build BasicTest CompilerUtils jdk.testlibrary.*
+ * @run testng BasicTest
+ * @summary Basic test of starting an application as a module
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class BasicTest {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    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 MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE = "test";
+
+    // the module main class
+    private static final String MAIN_CLASS = "jdk.test.Main";
+
+
+    @BeforeTest
+    public void compileTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                                    MODS_DIR.resolve(TEST_MODULE));
+
+        assertTrue(compiled, "test module did not compile");
+    }
+
+
+    /**
+     * The initial module is loaded from an exploded module
+     */
+    public void testRunWithExplodedModule() throws Exception {
+        String dir = MODS_DIR.toString();
+        String subdir = MODS_DIR.resolve(TEST_MODULE).toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // java -mp mods -m $TESTMODULE/$MAINCLASS
+        int exitValue
+            = executeTestJava("-mp", dir, "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+
+        // java -mp mods/$TESTMODULE -m $TESTMODULE/$MAINCLASS
+        exitValue
+            = executeTestJava("-mp", subdir, "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * The initial module is loaded from a modular JAR file
+     */
+    public void testRunWithModularJar() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
+        Path jar = dir.resolve("m.jar");
+
+        // jar --create ...
+        String classes = MODS_DIR.resolve(TEST_MODULE).toString();
+        String[] args = {
+            "--create",
+            "--file=" + jar,
+            "--main-class=" + MAIN_CLASS,
+            "-C", classes, "."
+        };
+        boolean success
+            = new sun.tools.jar.Main(System.out, System.out, "jar")
+                .run(args);
+        assertTrue(success);
+
+        // java -mp mlib -m $TESTMODULE
+        int exitValue
+            = executeTestJava("-mp", dir.toString(),
+                              "-m", TEST_MODULE)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+
+        // java -mp mlib/m.jar -m $TESTMODULE
+        exitValue
+            = executeTestJava("-mp", jar.toString(),
+                              "-m", TEST_MODULE)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Attempt to run with the initial module packaged as a JMOD file.
+     */
+    public void testTryRunWithJMod() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
+
+        // jmod create ...
+        String cp = MODS_DIR.resolve(TEST_MODULE).toString();
+        String jmod = dir.resolve("m.jmod").toString();
+        String[] args = {
+            "create",
+            "--class-path", cp,
+            "--main-class", MAIN_CLASS,
+            jmod
+        };
+        jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask();
+        assertEquals(task.run(args), 0);
+
+        // java -mp mods -m $TESTMODULE
+        int exitValue
+            = executeTestJava("-mp", dir.toString(),
+                "-m", TEST_MODULE)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Run the test with a non-existent file on the application module path.
+     * It should be silently ignored.
+     */
+    public void testRunWithNonExistentEntry() throws Exception {
+        String mp = "DoesNotExist" + File.pathSeparator + MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // java -mp mods -m $TESTMODULE/$MAINCLASS
+        int exitValue
+            = executeTestJava("-mp", mp,
+                              "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Attempt to run an unknown initial module
+     */
+    public void testTryRunWithBadModule() throws Exception {
+        String modulepath = MODS_DIR.toString();
+
+        // java -mp mods -m $TESTMODULE
+        int exitValue
+            = executeTestJava("-mp", modulepath,
+                              "-m", "rhubarb")
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .shouldContain("not found")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Attempt to run with -m specifying a main class that does not
+     * exist.
+     */
+    public void testTryRunWithBadMainClass() throws Exception {
+        String modulepath = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/p.rhubarb";
+
+        // java -mp mods -m $TESTMODULE/$MAINCLASS
+        int exitValue
+            = executeTestJava("-mp", modulepath,
+                              "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Attempt to run with -m specifying a modular JAR that does not have
+     * a MainClass attribute
+     */
+    public void testTryRunWithMissingMainClass() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
+
+        // jar --create ...
+        String classes = MODS_DIR.resolve(TEST_MODULE).toString();
+        String jar = dir.resolve("m.jar").toString();
+        String[] args = {
+            "--create",
+            "--file=" + jar,
+            "-C", classes, "."
+        };
+        boolean success
+            = new sun.tools.jar.Main(System.out, System.out, "jar")
+                .run(args);
+        assertTrue(success);
+
+        // java -mp mods -m $TESTMODULE
+        int exitValue
+            = executeTestJava("-mp", dir.toString(),
+                              "-m", TEST_MODULE)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .shouldContain("does not have a MainClass attribute")
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Attempt to run with -m specifying a main class that is a different
+     * module to that specified to -m
+     */
+    public void testTryRunWithMainClassInWrongModule() throws Exception {
+        String modulepath = MODS_DIR.toString();
+        String mid = "java.base/" + MAIN_CLASS;
+
+        // java -mp mods -m $TESTMODULE/$MAINCLASS
+        int exitValue
+            = executeTestJava("-mp", modulepath,
+                              "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/basic/src/test/jdk/test/Main.java b/jdk/test/tools/launcher/modules/basic/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..46f4bb7
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/basic/src/test/jdk/test/Main.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package jdk.test;
+
+public class Main {
+    public static void main(String[] args) {
+        System.out.println("Hello world");
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/basic/src/test/module-info.java b/jdk/test/tools/launcher/modules/basic/src/test/module-info.java
new file mode 100644
index 0000000..779c3c8
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/basic/src/test/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 {
+}
+
diff --git a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java
new file mode 100644
index 0000000..0cafaf4
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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
+ * 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 java.desktop java.compact1 jdk.compiler
+ * @build LimitModsTest CompilerUtils jdk.testlibrary.*
+ * @run testng LimitModsTest
+ * @summary Basic tests for java -limitmods
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class LimitModsTest {
+
+    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 MODS_DIR = Paths.get("mods");
+
+    // the module name / main class of the test module
+    private static final String TEST_MODULE = "test";
+    private static final String MAIN_CLASS = "jdk.test.UseAWT";
+
+
+    @BeforeTest
+    public void compileTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                MODS_DIR.resolve(TEST_MODULE));
+
+        assertTrue(compiled, "test module did not compile");
+    }
+
+
+    /**
+     * Basic test of -limitmods to limit which platform modules are observable.
+     */
+    public void testLimitingPlatformModules() throws Exception {
+        int exitValue;
+
+        // java -limitmods java.base -listmods
+        exitValue = executeTestJava("-limitmods", "java.base", "-listmods")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .shouldContain("java.base")
+            .shouldNotContain("java.logging")
+            .shouldNotContain("java.xml")
+            .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+
+        // java -limitmods java.compact1 -listmods
+        exitValue = executeTestJava("-limitmods", "java.compact1", "-listmods")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .shouldContain("java.base")
+            .shouldContain("java.logging")
+            .shouldContain("java.compact1")
+            .shouldNotContain("java.xml")
+            .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+
+    /**
+     * Test -limitmods with -addmods
+     */
+    public void testWithAddMods() throws Exception {
+        int exitValue;
+
+        // java -limitmods java.base -addmods java.logging -listmods
+        exitValue = executeTestJava("-limitmods", "java.base",
+                                    "-addmods", "java.logging",
+                                    "-listmods")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .shouldContain("java.base")
+            .shouldContain("java.logging")
+            .shouldNotContain("java.xml")
+            .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+
+        // java -limitmods java.base -addmods java.sql -listmods
+        // This should fail because java.sql has dependences beyond java.base
+        exitValue = executeTestJava("-limitmods", "java.base",
+                                    "-addmods", "java.sql",
+                                    "-listmods")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .getExitValue();
+
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Run class path application with -limitmods
+     */
+    public void testUnnamedModule() throws Exception {
+        String classpath = MODS_DIR.resolve(TEST_MODULE).toString();
+
+        // java -limitmods java.base -cp mods/$TESTMODULE ...
+        int exitValue1
+            = executeTestJava("-limitmods", "java.base",
+                              "-cp", classpath,
+                              MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .shouldContain("NoClassDefFoundError")
+                .getExitValue();
+
+        assertTrue(exitValue1 != 0);
+
+
+        // java -limitmods java.base -cp mods/$TESTMODULE ...
+        int exitValue2
+            = executeTestJava("-limitmods", "java.desktop",
+                              "-cp", classpath,
+                             MAIN_CLASS)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue2 == 0);
+    }
+
+
+    /**
+     * Run named module with -limitmods
+     */
+    public void testNamedModule() throws Exception {
+
+        String modulepath = MODS_DIR.toString();
+        String mid = TEST_MODULE + "/" + MAIN_CLASS;
+
+        // java -limitmods java.base -mp mods -m $TESTMODULE/$MAINCLASS
+        int exitValue = executeTestJava("-limitmods", "java.base",
+                                        "-mp", modulepath,
+                                        "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue != 0);
+
+        // java -limitmods java.desktop -mp mods -m $TESTMODULE/$MAINCLASS
+        exitValue = executeTestJava("-limitmods", "java.desktop",
+                                    "-mp", modulepath,
+                                    "-m", mid)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/limitmods/src/test/jdk/test/UseAWT.java b/jdk/test/tools/launcher/modules/limitmods/src/test/jdk/test/UseAWT.java
new file mode 100644
index 0000000..08fa5da
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/limitmods/src/test/jdk/test/UseAWT.java
@@ -0,0 +1,32 @@
+/*
+ * 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 jdk.test;
+
+import java.awt.Component;
+
+public class UseAWT {
+    public static void main(String[] args) {
+        System.out.println(java.awt.Component.class);
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/limitmods/src/test/module-info.java b/jdk/test/tools/launcher/modules/limitmods/src/test/module-info.java
new file mode 100644
index 0000000..5fe0739
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/limitmods/src/test/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.desktop;
+}
diff --git a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java
new file mode 100644
index 0000000..bd57d38
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules java.se
+ * @build ListModsTest CompilerUtils jdk.testlibrary.*
+ * @run testng ListModsTest
+ * @summary Basic test for java -listmods
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.*;
+import jdk.testlibrary.OutputAnalyzer;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * Basic tests for java -listmods
+ */
+
+public class ListModsTest {
+
+    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 MODS_DIR = Paths.get("mods");
+    private static final Path UPGRADEMODS_DIR = Paths.get("upgrademods");
+
+    @BeforeTest
+    public void setup() throws Exception {
+        boolean compiled;
+
+        // javac -d mods/m1 -mp mods src/m1/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("m1"),
+                MODS_DIR.resolve("m1"));
+        assertTrue(compiled);
+
+        // javac -d upgrademods/java.transaction -mp mods src/java.transaction/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("java.transaction"),
+                UPGRADEMODS_DIR.resolve("java.transaction"));
+        assertTrue(compiled);
+
+    }
+
+
+    @Test
+    public void testListAll() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-listmods")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldContain("java.xml");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListOneModule() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-listmods:java.base")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldContain("exports java.lang");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListTwoModules() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-listmods:java.base,java.xml")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldContain("exports java.lang");
+        output.shouldContain("java.xml");
+        output.shouldContain("exports javax.xml");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListUnknownModule() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-listmods:java.rhubarb")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldNotContain("java.base");
+        output.shouldNotContain("java.rhubarb");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListWithModulePath() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-mp", MODS_DIR.toString(), "-listmods")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldContain("m1");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListWithUpgradeModulePath() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-upgrademodulepath", UPGRADEMODS_DIR.toString(),
+                              "-listmods:java.transaction")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("exports javax.transaction.atomic");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListWithLimitMods1() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-limitmods", "java.compact1", "-listmods")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.compact1");
+        output.shouldContain("java.base");
+        output.shouldNotContain("java.xml");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    @Test
+    public void testListWithLimitMods2() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-mp", MODS_DIR.toString(),
+                              "-limitmods", "java.compact1",
+                              "-listmods")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldNotContain("m1");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    /**
+     * java -version -listmods => should print version and exit
+     */
+    @Test
+    public void testListWithPrintVersion1() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-version", "-listmods")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldNotContain("java.base");
+        output.shouldContain("Runtime Environment");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+
+    /**
+     * java -listmods -version => should list modules and exit
+     */
+    @Test
+    public void testListWithPrintVersion2() throws Exception {
+        OutputAnalyzer output
+            = executeTestJava("-listmods", "-version")
+                .outputTo(System.out)
+                .errorTo(System.out);
+        output.shouldContain("java.base");
+        output.shouldNotContain("Runtime Environment");
+        assertTrue(output.getExitValue() == 0);
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/Transaction.java b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/Transaction.java
new file mode 100644
index 0000000..3988d8d
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/Transaction.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.transaction;
+
+public class Transaction {
+
+    public Transaction() { }
+
+}
diff --git a/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/atomic/Atomic.java b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/atomic/Atomic.java
new file mode 100644
index 0000000..f4974e3
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/javax/transaction/atomic/Atomic.java
@@ -0,0 +1,28 @@
+/*
+ * 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 javax.transaction.atomic;
+
+public interface Atomic {
+
+}
diff --git a/jdk/test/tools/launcher/modules/listmods/src/java.transaction/module-info.java b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/module-info.java
new file mode 100644
index 0000000..d1a268c
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/listmods/src/java.transaction/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.transaction {
+    exports javax.transaction;
+    exports javax.transaction.atomic;
+}
diff --git a/jdk/test/tools/launcher/modules/listmods/src/m1/module-info.java b/jdk/test/tools/launcher/modules/listmods/src/m1/module-info.java
new file mode 100644
index 0000000..967d553
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/listmods/src/m1/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+}
diff --git a/jdk/test/tools/launcher/modules/patch/PatchTest.java b/jdk/test/tools/launcher/modules/patch/PatchTest.java
new file mode 100644
index 0000000..215882f
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/PatchTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build PatchTest CompilerUtils jdk.testlibrary.*
+ * @run testng PatchTest
+ * @summary Basic test for -Xpatch
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+/**
+ * Compiles and launches a test that uses -Xpatch with two directories of
+ * classes to override existing and add new classes to modules in the
+ * boot layer.
+ *
+ * The classes overridden or added via -Xpatch all define a public no-arg
+ * constructor and override toString to return "hi". This allows the launched
+ * test to check that the overridden classes are loaded.
+ */
+
+@Test
+public class PatchTest {
+
+    // top-level source directory
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    // source/destination tree for the test module
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // source/destination tree for patch tree 1
+    private static final Path SRC1_DIR = Paths.get(TEST_SRC, "src1");
+    private static final Path PATCHES1_DIR = Paths.get("patches1");
+
+    // source/destination tree for patch tree 2
+    private static final Path SRC2_DIR = Paths.get(TEST_SRC, "src2");
+    private static final Path PATCHES2_DIR = Paths.get("patches2");
+
+
+    // the classes overridden or added with -Xpatch
+    private static final String[] CLASSES = {
+
+        // java.base = boot loader
+        "java.base/java.text.Annotation",           // override class
+        "java.base/java.text.AnnotationBuddy",      // add class to package
+        "java.base/java.lang2.Object",              // new package
+
+        // jdk.naming.dns = platform class loader
+        "jdk.naming.dns/com.sun.jndi.dns.DnsClient",
+        "jdk.naming.dns/com.sun.jndi.dns.DnsClientBuddy",
+        "jdk.naming.dns/com.sun.jndi.dns2.Zone",
+
+        // jdk.compiler = application class loaded
+        "jdk.compiler/com.sun.tools.javac.Main",
+        "jdk.compiler/com.sun.tools.javac.MainBuddy",
+        "jdk.compiler/com.sun.tools.javac2.Main",
+
+    };
+
+
+    @BeforeTest
+    public void compile() throws Exception {
+
+        // javac -d mods/test src/test/**
+        boolean compiled= CompilerUtils.compile(SRC_DIR.resolve("test"),
+                                                MODS_DIR.resolve("test"));
+        assertTrue(compiled, "classes did not compile");
+
+        // javac -Xmodule:$MODULE -d patches1/$MODULE patches1/$MODULE/**
+        for (Path src : Files.newDirectoryStream(SRC1_DIR)) {
+            Path output = PATCHES1_DIR.resolve(src.getFileName());
+            String mn = src.getFileName().toString();
+            compiled  = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
+            assertTrue(compiled, "classes did not compile");
+        }
+
+        // javac -Xmodule:$MODULE -d patches2/$MODULE patches2/$MODULE/**
+        for (Path src : Files.newDirectoryStream(SRC2_DIR)) {
+            Path output = PATCHES2_DIR.resolve(src.getFileName());
+            String mn = src.getFileName().toString();
+            compiled  = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
+            assertTrue(compiled, "classes did not compile");
+        }
+
+    }
+
+    /**
+     * Run the test with -Xpatch
+     */
+    public void testRunWithXPatch() throws Exception {
+
+        // value for -Xpatch
+        String patchPath = PATCHES1_DIR + File.pathSeparator + PATCHES2_DIR;
+
+        // value for -XaddExports
+        String addExportsValue = "java.base/java.lang2=test"
+                + ",jdk.naming.dns/com.sun.jndi.dns=test"
+                + ",jdk.naming.dns/com.sun.jndi.dns2=test"
+                + ",jdk.compiler/com.sun.tools.javac2=test";
+
+        // the argument to the test is the list of classes overridden or added
+        String arg = Stream.of(CLASSES).collect(Collectors.joining(","));
+
+        int exitValue
+            =  executeTestJava("-Xpatch:" + patchPath,
+                               "-XaddExports:" + addExportsValue,
+                               "-addmods", "jdk.naming.dns,jdk.compiler",
+                               "-mp", MODS_DIR.toString(),
+                               "-m", "test/jdk.test.Main", arg)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src/test/jdk/test/Main.java b/jdk/test/tools/launcher/modules/patch/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..88e0985
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src/test/jdk/test/Main.java
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+/**
+ * Used with -Xpatch to exercise the replacement or addition of classes
+ * in modules that are linked into the runtime image.
+ */
+
+package jdk.test;
+
+import java.lang.reflect.Module;
+
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+
+        for (String moduleAndClass : args[0].split(",")) {
+            String mn = moduleAndClass.split("/")[0];
+            String cn = moduleAndClass.split("/")[1];
+
+            // load class
+            Class<?> c = Class.forName(cn);
+
+            // check in expected module
+            Module m = c.getModule();
+            assertEquals(m.getName(), mn);
+
+            // instantiate object
+            Main.class.getModule().addReads(m);
+            Object obj = c.newInstance();
+
+            // check that the expected version of the class is loaded
+            System.out.print(moduleAndClass);
+            String s = obj.toString();
+            System.out.println(" says " + s);
+            assertEquals(s, "hi");
+
+            // check Module getResourceAsStream
+            String rn = cn.replace('.', '/') + ".class";
+            assertNotNull(m.getResourceAsStream(rn));
+        }
+    }
+
+
+    static void assertEquals(Object o1, Object o2) {
+        if (!o1.equals(o2))
+            throw new RuntimeException("assertion failed");
+    }
+
+    static void assertNotNull(Object o) {
+        if (o == null)
+            throw new RuntimeException("unexpected null");
+    }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src/test/module-info.java b/jdk/test/tools/launcher/modules/patch/src/test/module-info.java
new file mode 100644
index 0000000..2ac3cbe
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src/test/module-info.java
@@ -0,0 +1,25 @@
+/**
+ * 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 test {
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/Annotation.java b/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/Annotation.java
new file mode 100644
index 0000000..1e1ab62
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/Annotation.java
@@ -0,0 +1,28 @@
+/*
+ * 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 java.text;
+
+public class Annotation {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/AnnotationBuddy.java b/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/AnnotationBuddy.java
new file mode 100644
index 0000000..5ef445d
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/java.base/java/text/AnnotationBuddy.java
@@ -0,0 +1,28 @@
+/*
+ * 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 java.text;
+
+public class AnnotationBuddy {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/Main.java b/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/Main.java
new file mode 100644
index 0000000..a1f7aa6
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/Main.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.sun.tools.javac;
+
+public class Main {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java b/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java
new file mode 100644
index 0000000..8fcd6b6
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/jdk.compiler/com/sun/tools/javac/MainBuddy.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.sun.tools.javac;
+
+public class MainBuddy {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java b/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java
new file mode 100644
index 0000000..c87cc45
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClient.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.sun.jndi.dns;
+
+public class DnsClient {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java b/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java
new file mode 100644
index 0000000..b173a22
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src1/jdk.naming.dns/com/sun/jndi/dns/DnsClientBuddy.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.sun.jndi.dns;
+
+public class DnsClientBuddy {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src2/java.base/java/lang2/Object.java b/jdk/test/tools/launcher/modules/patch/src2/java.base/java/lang2/Object.java
new file mode 100644
index 0000000..9808894
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src2/java.base/java/lang2/Object.java
@@ -0,0 +1,28 @@
+/**
+ * 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 java.lang2;
+
+public class Object {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src2/jdk.compiler/com/sun/tools/javac2/Main.java b/jdk/test/tools/launcher/modules/patch/src2/jdk.compiler/com/sun/tools/javac2/Main.java
new file mode 100644
index 0000000..c5ee7db
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src2/jdk.compiler/com/sun/tools/javac2/Main.java
@@ -0,0 +1,28 @@
+/**
+ * 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 com.sun.tools.javac2;
+
+public class Main {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/patch/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java b/jdk/test/tools/launcher/modules/patch/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java
new file mode 100644
index 0000000..0ef3ac3
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/patch/src2/jdk.naming.dns/com/sun/jndi/dns2/Zone.java
@@ -0,0 +1,28 @@
+/**
+ * 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 com.sun.jndi.dns2;
+
+public class Zone {
+    public String toString() { return "hi"; }
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/UpgradeModulePathTest.java b/jdk/test/tools/launcher/modules/upgrademodulepath/UpgradeModulePathTest.java
new file mode 100644
index 0000000..31351b5
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/UpgradeModulePathTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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
+ * 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 UpgradeModulePathTest CompilerUtils jdk.testlibrary.*
+ * @run testng UpgradeModulePathTest
+ * @summary Basic test for java -upgrademodulepath
+ */
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.testlibrary.ProcessTools.executeTestJava;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * This test upgrades module java.transaction. The upgraded module has a
+ * dependency on module java.enterprise that is deployed on the application
+ * modue path.
+ */
+
+
+@Test
+public class UpgradeModulePathTest {
+
+    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 MODS_DIR = Paths.get("mods");
+    private static final Path UPGRADEDMODS_DIR = Paths.get("upgradedmods");
+
+
+    @BeforeTest
+    public void setup() throws Exception {
+
+        // javac -d mods/java.enterprise src/java.enterprise/**
+        boolean compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("java.enterprise"),
+                MODS_DIR.resolve("java.enterprise"));
+        assertTrue(compiled);
+
+        // javac -d upgrademods/java.transaction -mp mods src/java.transaction/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("java.transaction"),
+                UPGRADEDMODS_DIR.resolve("java.transaction"),
+                "-mp", MODS_DIR.toString());
+        assertTrue(compiled);
+
+        // javac -d mods -upgrademodulepath upgrademods -mp mods src/test/**
+        compiled = CompilerUtils.compile(
+                SRC_DIR.resolve("test"),
+                MODS_DIR.resolve("test"),
+                "-upgrademodulepath", UPGRADEDMODS_DIR.toString(),
+                "-mp", MODS_DIR.toString());
+        assertTrue(compiled);
+
+    }
+
+
+    /**
+     * Run the test with an upgraded java.transaction module.
+     */
+    public void testWithUpgradedModule() throws Exception {
+
+        String mid = "test/jdk.test.Main";
+
+        int exitValue
+            = executeTestJava(
+                "-upgrademodulepath", UPGRADEDMODS_DIR.toString(),
+                "-mp", MODS_DIR.toString(),
+                "-m", mid)
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+
+    /**
+     * Run the test with a non-existent file on the upgrade module path.
+     * It should be silently ignored.
+     */
+    public void testRunWithNonExistentEntry() throws Exception {
+
+        String upgrademodulepath
+            = "DoesNotExit" + File.pathSeparator + UPGRADEDMODS_DIR.toString();
+        String mid = "test/jdk.test.Main";
+
+        int exitValue
+            = executeTestJava(
+                "-upgrademodulepath", upgrademodulepath,
+                "-mp", MODS_DIR.toString(),
+                "-m", mid)
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .getExitValue();
+
+        assertTrue(exitValue == 0);
+
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/javax/enterprise/context/Scope.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/javax/enterprise/context/Scope.java
new file mode 100644
index 0000000..9062665
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/javax/enterprise/context/Scope.java
@@ -0,0 +1,28 @@
+/*
+ * 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 javax.enterprise.context;
+
+public class Scope {
+    public Scope() { }
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/module-info.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/module-info.java
new file mode 100644
index 0000000..aa96112
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.enterprise/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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 java.enterprise {
+    exports javax.enterprise.context;
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/javax/transaction/Transaction.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/javax/transaction/Transaction.java
new file mode 100644
index 0000000..27350fd
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/javax/transaction/Transaction.java
@@ -0,0 +1,36 @@
+/*
+ * 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 javax.transaction;
+
+import javax.enterprise.context.Scope;
+
+public class Transaction {
+
+    public Transaction() { }
+
+    public Scope getScope() {
+        return new Scope();
+    }
+
+}
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
new file mode 100644
index 0000000..746ce3f
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 java.transaction {
+    requires public java.enterprise;
+    exports javax.transaction;
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/jdk/test/Main.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/jdk/test/Main.java
new file mode 100644
index 0000000..9f87f53
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/jdk/test/Main.java
@@ -0,0 +1,59 @@
+/*
+ * 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 jdk.test;
+
+import javax.transaction.Transaction;
+import javax.enterprise.context.Scope;
+
+/**
+ * Uses an upgraded version of module java.transaction.
+ */
+
+public class Main {
+
+    public static void main(String[] args) {
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        ClassLoader pcl = ClassLoader.getPlatformClassLoader();
+        assertTrue(pcl.getParent() == null);
+
+        Transaction transaction = new Transaction();
+        Scope scope = transaction.getScope();
+
+        // javax.transaction.Transaction should be in module java.transaction
+        // and defined by the platform class loader
+        assertTrue(Transaction.class.getModule().getName().equals("java.transaction"));
+        assertTrue(Transaction.class.getClassLoader() == pcl);
+
+        // javax.enterprise.context.Scope should be in module java.enterprise
+        // and defined by the application class loader
+        assertTrue(Scope.class.getModule().getName().equals("java.enterprise"));
+        assertTrue(Scope.class.getClassLoader() == scl);
+    }
+
+    static void assertTrue(boolean e) {
+        if (!e) throw new RuntimeException();
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/module-info.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/module-info.java
new file mode 100644
index 0000000..e4087ea
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/test/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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 test {
+    requires java.transaction;
+}
+
diff --git a/jdk/test/tools/lib/tests/Helper.java b/jdk/test/tools/lib/tests/Helper.java
new file mode 100644
index 0000000..c134cef
--- /dev/null
+++ b/jdk/test/tools/lib/tests/Helper.java
@@ -0,0 +1,405 @@
+/*
+ * 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 tests;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+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.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import tests.JImageGenerator.JLinkTask;
+import tests.JImageGenerator.JModTask;
+
+/**
+ * JLink tests helper.
+ */
+public class Helper {
+
+    private final Path explodedmodssrc;
+    private final Path jmodssrc;
+    private final Path jarssrc;
+    private final Path explodedmodsclasses;
+    private final Path jmodsclasses;
+    private final Path jarsclasses;
+    private final Path jmods;
+    private final Path jars;
+    private final Path images;
+    private final Path explodedmods;
+    private final Path stdjmods;
+    private final Path extracted;
+    private final Path recreated;
+
+    private final Map<String, List<String>> moduleClassDependencies = new HashMap<>();
+    private final Map<String, List<String>> moduleDependencies = new HashMap<>();
+    private final List<String> bootClasses;
+    private final FileSystem fs;
+
+    public static Helper newHelper() throws IOException {
+        Path jdkHome = Paths.get(System.getProperty("test.jdk"));
+        // JPRT not yet ready for jmods
+        if (!Files.exists(jdkHome.resolve("jmods"))) {
+            System.err.println("Test not run, NO jmods directory");
+            return null;
+        }
+        return new Helper(jdkHome);
+    }
+
+    private Helper(Path jdkHome) throws IOException {
+        this.stdjmods = jdkHome.resolve("jmods").normalize();
+        if (!Files.exists(stdjmods)) {
+            throw new IOException("Standard jMods do not exist.");
+        }
+        this.fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+
+        Path javabase = fs.getPath("/modules/java.base");
+        this.bootClasses = Files.find(javabase, Integer.MAX_VALUE,
+                (file, attrs) -> file.toString().endsWith(".class"))
+                .map(Object::toString)
+                .map(s -> s.substring("/modules".length()))
+                .collect(Collectors.toList());
+
+        if (bootClasses.isEmpty()) {
+            throw new AssertionError("No boot class to check against");
+        }
+
+        this.jmods = Paths.get("jmods").toAbsolutePath();
+        Files.createDirectories(jmods);
+        this.jars = Paths.get("jars").toAbsolutePath();
+        Files.createDirectories(jars);
+        this.explodedmods = Paths.get("explodedmods").toAbsolutePath();
+        Files.createDirectories(explodedmods);
+        this.explodedmodssrc = explodedmods.resolve("src");
+        Files.createDirectories(explodedmodssrc);
+        this.jarssrc = jars.resolve("src");
+        Files.createDirectories(jarssrc);
+        this.jmodssrc = jmods.resolve("src");
+        Files.createDirectories(jmodssrc);
+        this.explodedmodsclasses = explodedmods.resolve("classes");
+        Files.createDirectories(explodedmodsclasses);
+        this.jmodsclasses = jmods.resolve("classes");
+        Files.createDirectories(jmodsclasses);
+        this.jarsclasses = jars.resolve("classes");
+        Files.createDirectories(jarsclasses);
+        this.images = Paths.get("images").toAbsolutePath();
+        Files.createDirectories(images);
+        this.extracted = Paths.get("extracted").toAbsolutePath();
+        Files.createDirectories(extracted);
+        this.recreated = Paths.get("recreated").toAbsolutePath();
+        Files.createDirectories(recreated);
+    }
+
+    public void generateDefaultModules() throws IOException {
+        generateDefaultJModule("leaf1");
+        generateDefaultJModule("leaf2");
+        generateDefaultJModule("leaf3");
+
+        generateDefaultJarModule("leaf4");
+        generateDefaultJarModule("leaf5");
+
+        generateDefaultExplodedModule("leaf6");
+        generateDefaultExplodedModule("leaf7");
+
+        generateDefaultJarModule("composite1", "leaf1", "leaf2", "leaf4", "leaf6");
+        generateDefaultJModule("composite2", "composite1", "leaf3", "leaf5", "leaf7",
+                "java.management");
+    }
+
+    public String defaultModulePath() {
+        return stdjmods.toAbsolutePath().toString() + File.pathSeparator
+                + jmods.toAbsolutePath().toString() + File.pathSeparator
+                + jars.toAbsolutePath().toString() + File.pathSeparator
+                + explodedmodsclasses.toAbsolutePath().toString();
+    }
+
+    public Path generateModuleCompiledClasses(
+            Path src, Path classes, String moduleName, String... dependencies) throws IOException {
+        return generateModuleCompiledClasses(src, classes, moduleName, getDefaultClasses(moduleName), dependencies);
+    }
+
+    public Path generateModuleCompiledClasses(
+            Path src, Path classes, String moduleName,
+            List<String> classNames, String... dependencies) throws IOException {
+        if (classNames == null) {
+            classNames = getDefaultClasses(moduleName);
+        }
+        putAppClasses(moduleName, classNames);
+        moduleDependencies.put(moduleName, Arrays.asList(dependencies));
+        String modulePath = defaultModulePath();
+        JImageGenerator.generateSourcesFromTemplate(src, moduleName, classNames.toArray(new String[classNames.size()]));
+        List<String> packages = classNames.stream()
+                .map(JImageGenerator::getPackageName)
+                .distinct()
+                .collect(Collectors.toList());
+        Path srcMod = src.resolve(moduleName);
+        JImageGenerator.generateModuleInfo(srcMod, packages, dependencies);
+        Path destination = classes.resolve(moduleName);
+        if (!JImageGenerator.compile(srcMod, destination, "-modulepath", modulePath, "-g")) {
+            throw new AssertionError("Compilation failure");
+        }
+        return destination;
+    }
+
+    public Result generateDefaultJModule(String moduleName, String... dependencies) throws IOException {
+        return generateDefaultJModule(moduleName, getDefaultClasses(moduleName), dependencies);
+    }
+
+    public Result generateDefaultJModule(String moduleName, List<String> classNames,
+                                             String... dependencies) throws IOException {
+        generateModuleCompiledClasses(jmodssrc, jmodsclasses, moduleName, classNames, dependencies);
+        generateGarbage(jmodsclasses.resolve(moduleName));
+
+        Path jmodFile = jmods.resolve(moduleName + ".jmod");
+        JModTask task = JImageGenerator.getJModTask()
+                .jmod(jmodFile)
+                .addJmods(stdjmods)
+                .addJmods(jmods.toAbsolutePath())
+                .addJars(jars.toAbsolutePath())
+                .addClassPath(jmodsclasses.resolve(moduleName));
+        if (!classNames.isEmpty()) {
+            task.mainClass(classNames.get(0));
+        }
+        return task.create();
+    }
+
+    public Result generateDefaultJarModule(String moduleName, String... dependencies) throws IOException {
+        return generateDefaultJarModule(moduleName, getDefaultClasses(moduleName), dependencies);
+    }
+
+    public Result generateDefaultJarModule(String moduleName, List<String> classNames,
+                                         String... dependencies) throws IOException {
+        generateModuleCompiledClasses(jarssrc, jarsclasses, moduleName, classNames, dependencies);
+        generateGarbage(jarsclasses.resolve(moduleName));
+
+        Path jarFile = jars.resolve(moduleName + ".jar");
+        JImageGenerator.createJarFile(jarFile, jarsclasses.resolve(moduleName));
+        return new Result(0, "", jarFile);
+    }
+
+    public Result generateDefaultExplodedModule(String moduleName, String... dependencies) throws IOException {
+        return generateDefaultExplodedModule(moduleName, getDefaultClasses(moduleName), dependencies);
+    }
+
+    public Result generateDefaultExplodedModule(String moduleName, List<String> classNames,
+            String... dependencies) throws IOException {
+        generateModuleCompiledClasses(explodedmodssrc, explodedmodsclasses,
+                moduleName, classNames, dependencies);
+
+        Path dir = explodedmods.resolve(moduleName);
+        return new Result(0, "", dir);
+    }
+
+    private void generateGarbage(Path compiled) throws IOException {
+        Path metaInf = compiled.resolve("META-INF").resolve("services");
+        Files.createDirectories(metaInf);
+        Path provider = metaInf.resolve("MyProvider");
+        Files.createFile(provider);
+        Files.createFile(compiled.resolve("toto.jcov"));
+    }
+
+    public static Path createNewFile(Path root, String pathName, String extension) {
+        Path out = root.resolve(pathName + extension);
+        int i = 1;
+        while (Files.exists(out)) {
+            out = root.resolve(pathName + "-" + (++i) + extension);
+        }
+        return out;
+    }
+
+    public Result generateDefaultImage(String module) {
+        return generateDefaultImage(new String[0], module);
+    }
+
+    public Result generateDefaultImage(String[] options, String module) {
+        Path output = createNewFile(images, module, ".image");
+        JLinkTask jLinkTask = JImageGenerator.getJLinkTask()
+                .modulePath(defaultModulePath())
+                .output(output)
+                .addMods(module)
+                .limitMods(module);
+        for (String option : options) {
+            jLinkTask.option(option);
+        }
+        return jLinkTask.call();
+    }
+
+    public Result postProcessImage(Path root, String[] options) {
+        JLinkTask jLinkTask = JImageGenerator.getJLinkTask()
+                .existing(root);
+        for (String option : options) {
+            jLinkTask.option(option);
+        }
+        return jLinkTask.callPostProcess();
+    }
+
+    private List<String> getDefaultClasses(String module) {
+        return Arrays.asList(module + ".Main", module + ".com.foo.bar.X");
+    }
+
+    private void putAppClasses(String module, List<String> classes) {
+        List<String> appClasses = toLocation(module, classes).stream().collect(Collectors.toList());
+        appClasses.add(toLocation(module, "module-info"));
+        moduleClassDependencies.put(module, appClasses);
+    }
+
+    private static String toLocation(String module, String className) {
+        return "/" + module + "/" + className.replaceAll("\\.", "/") + ".class";
+    }
+
+    public static List<String> toLocation(String module, List<String> classNames) {
+        return classNames.stream()
+                .map(clazz -> toLocation(module, clazz))
+                .collect(Collectors.toList());
+    }
+
+    public void checkImage(Path imageDir, String module, String[] paths, String[] files) throws IOException {
+        checkImage(imageDir, module, paths, files, null);
+    }
+
+    public void checkImage(Path imageDir, String module, String[] paths, String[] files, String[] expectedFiles) throws IOException {
+        List<String> unexpectedPaths = new ArrayList<>();
+        if (paths != null) {
+            Collections.addAll(unexpectedPaths, paths);
+        }
+        List<String> unexpectedFiles = new ArrayList<>();
+        if (files != null) {
+            Collections.addAll(unexpectedFiles, files);
+        }
+
+        JImageValidator validator = new JImageValidator(module, gatherExpectedLocations(module),
+                imageDir.toFile(),
+                unexpectedPaths,
+                unexpectedFiles,
+                expectedFiles);
+        System.out.println("*** Validate Image " + module);
+        validator.validate();
+        long moduleExecutionTime = validator.getModuleLauncherExecutionTime();
+        if (moduleExecutionTime != 0) {
+            System.out.println("Module launcher execution time " + moduleExecutionTime);
+        }
+        System.out.println("Java launcher execution time "
+                + validator.getJavaLauncherExecutionTime());
+        System.out.println("***");
+    }
+
+    private List<String> gatherExpectedLocations(String module) throws IOException {
+        List<String> expectedLocations = new ArrayList<>();
+        expectedLocations.addAll(bootClasses);
+        List<String> modules = moduleDependencies.get(module);
+        for (String dep : modules) {
+            Path path = fs.getPath("/modules/" + dep);
+            if (Files.exists(path)) {
+                List<String> locations = Files.find(path, Integer.MAX_VALUE,
+                        (p, attrs) -> Files.isRegularFile(p) && p.toString().endsWith(".class")
+                                && !p.toString().endsWith("module-info.class"))
+                        .map(p -> p.toString().substring("/modules".length()))
+                        .collect(Collectors.toList());
+                expectedLocations.addAll(locations);
+            }
+        }
+
+        List<String> appClasses = moduleClassDependencies.get(module);
+        if (appClasses != null) {
+            expectedLocations.addAll(appClasses);
+        }
+        return expectedLocations;
+    }
+
+    public static String getDebugSymbolsExtension() {
+        return ".diz";
+    }
+
+    public Path createNewImageDir(String moduleName) {
+        return createNewFile(getImageDir(), moduleName, ".image");
+    }
+
+    public Path createNewExtractedDir(String name) {
+        return createNewFile(getExtractedDir(), name, ".extracted");
+    }
+
+    public Path createNewRecreatedDir(String name) {
+        return createNewFile(getRecreatedDir(), name, ".jimage");
+    }
+
+    public Path createNewJmodFile(String moduleName) {
+        return createNewFile(getJmodDir(), moduleName, ".jmod");
+    }
+
+    public Path createNewJarFile(String moduleName) {
+        return createNewFile(getJarDir(), moduleName, ".jar");
+    }
+
+    public Path getJmodSrcDir() {
+        return jmodssrc;
+    }
+
+    public Path getJarSrcDir() {
+        return jarssrc;
+    }
+
+    public Path getJmodClassesDir() {
+        return jmodsclasses;
+    }
+
+    public Path getJarClassesDir() {
+        return jarsclasses;
+    }
+
+    public Path getJmodDir() {
+        return jmods;
+    }
+
+    public Path getExplodedModsDir() {
+        return explodedmods;
+    }
+
+    public Path getJarDir() {
+        return jars;
+    }
+
+    public Path getImageDir() {
+        return images;
+    }
+
+    public Path getStdJmodsDir() {
+        return stdjmods;
+    }
+
+    public Path getExtractedDir() {
+        return extracted;
+    }
+
+    public Path getRecreatedDir() {
+        return recreated;
+    }
+}
diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java
new file mode 100644
index 0000000..77366aa
--- /dev/null
+++ b/jdk/test/tools/lib/tests/JImageGenerator.java
@@ -0,0 +1,735 @@
+/*
+ * 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 tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ *
+ * A generator for jmods, jars and images.
+ */
+public class JImageGenerator {
+
+    public static final String LOAD_ALL_CLASSES_TEMPLATE = "package PACKAGE;\n"
+            + "\n"
+            + "import java.net.URI;\n"
+            + "import java.nio.file.FileSystems;\n"
+            + "import java.nio.file.Files;\n"
+            + "import java.nio.file.Path;\n"
+            + "import java.util.function.Function;\n"
+            + "\n"
+            + "public class CLASS {\n"
+            + "    private static long total_time;\n"
+            + "    private static long num_classes;\n"
+            + "    public static void main(String[] args) throws Exception {\n"
+            + "        Function<Path, String> formatter = (path) -> {\n"
+            + "            String clazz = path.toString().substring(\"modules/\".length()+1, path.toString().lastIndexOf(\".\"));\n"
+            + "            clazz = clazz.substring(clazz.indexOf(\"/\") + 1);\n"
+            + "            return clazz.replaceAll(\"/\", \"\\\\.\");\n"
+            + "        };\n"
+            + "        Files.walk(FileSystems.getFileSystem(URI.create(\"jrt:/\")).getPath(\"/modules/\")).\n"
+            + "                filter((p) -> {\n"
+            + "                    return Files.isRegularFile(p) && p.toString().endsWith(\".class\")\n"
+            + "                    && !p.toString().endsWith(\"module-info.class\");\n"
+            + "                }).\n"
+            + "                map(formatter).forEach((clazz) -> {\n"
+            + "                    try {\n"
+            + "                        long t = System.currentTimeMillis();\n"
+            + "                        Class.forName(clazz, false, Thread.currentThread().getContextClassLoader());\n"
+            + "                        total_time+= System.currentTimeMillis()-t;\n"
+            + "                        num_classes+=1;\n"
+            + "                    } catch (IllegalAccessError ex) {\n"
+            + "                        // Security exceptions can occur, this is not what we are testing\n"
+            + "                        System.err.println(\"Access error, OK \" + clazz);\n"
+            + "                    } catch (Exception ex) {\n"
+            + "                        System.err.println(\"ERROR \" + clazz);\n"
+            + "                        throw new RuntimeException(ex);\n"
+            + "                    }\n"
+            + "                });\n"
+            + "    double res = (double) total_time / num_classes;\n"
+            + "    // System.out.println(\"Total time \" + total_time + \" num classes \" + num_classes + \" average \" + res);\n"
+            + "    }\n"
+            + "}\n";
+
+    private static final String OUTPUT_OPTION = "--output";
+    private static final String POST_PROCESS_OPTION = "--post-process-path";
+    private static final String MAIN_CLASS_OPTION = "--main-class";
+    private static final String CLASS_PATH_OPTION = "--class-path";
+    private static final String MODULE_PATH_OPTION = "--modulepath";
+    private static final String ADD_MODS_OPTION = "--addmods";
+    private static final String LIMIT_MODS_OPTION = "--limitmods";
+    private static final String PLUGINS_MODULE_PATH = "--plugin-module-path";
+
+    private static final String CMDS_OPTION = "--cmds";
+    private static final String CONFIG_OPTION = "--config";
+    private static final String HASH_DEPENDENCIES_OPTION = "--hash-dependencies";
+    private static final String LIBS_OPTION = "--libs";
+    private static final String MODULE_VERSION_OPTION = "--module-version";
+
+    private JImageGenerator() {}
+
+    private static String optionsPrettyPrint(String... args) {
+        return Stream.of(args).collect(Collectors.joining(" "));
+    }
+
+    public static File getJModsDir(File jdkHome) {
+        File jdkjmods = new File(jdkHome, "jmods");
+        if (!jdkjmods.exists()) {
+            return null;
+        }
+        return jdkjmods;
+    }
+
+    public static Path addFiles(Path module, InMemoryFile... resources) throws IOException {
+        Path tempFile = Files.createTempFile("jlink-test", "");
+        try (JarInputStream in = new JarInputStream(Files.newInputStream(module));
+             JarOutputStream out = new JarOutputStream(new FileOutputStream(tempFile.toFile()))) {
+            ZipEntry entry;
+            while ((entry = in.getNextEntry()) != null) {
+                String name = entry.getName();
+                out.putNextEntry(new ZipEntry(name));
+                copy(in, out);
+                out.closeEntry();
+            }
+            for (InMemoryFile r : resources) {
+                addFile(r, out);
+            }
+        }
+        Files.move(tempFile, module, StandardCopyOption.REPLACE_EXISTING);
+        return module;
+    }
+
+    private static void copy(InputStream in, OutputStream out) throws IOException {
+        int len;
+        byte[] buf = new byte[4096];
+        while ((len = in.read(buf)) > 0) {
+            out.write(buf, 0, len);
+        }
+    }
+
+    public static JModTask getJModTask() {
+        return new JModTask();
+    }
+
+    public static JLinkTask getJLinkTask() {
+        return new JLinkTask();
+    }
+
+    public static JImageTask getJImageTask() {
+        return new JImageTask();
+    }
+
+    private static void addFile(InMemoryFile resource, JarOutputStream target) throws IOException {
+        String fileName = resource.getPath();
+        fileName = fileName.replace("\\", "/");
+        String[] ss = fileName.split("/");
+        Path p = Paths.get("");
+        for (int i = 0; i < ss.length; ++i) {
+            if (i < ss.length - 1) {
+                if (!ss[i].isEmpty()) {
+                    p = p.resolve(ss[i]);
+                    JarEntry entry = new JarEntry(p.toString() + "/");
+                    target.putNextEntry(entry);
+                    target.closeEntry();
+                }
+            } else {
+                p = p.resolve(ss[i]);
+                JarEntry entry = new JarEntry(p.toString());
+                target.putNextEntry(entry);
+                copy(resource.getBytes(), target);
+                target.closeEntry();
+            }
+        }
+    }
+
+    public static Path createNewFile(Path root, String pathName, String extension) {
+        Path out = root.resolve(pathName + extension);
+        int i = 1;
+        while (Files.exists(out)) {
+            out = root.resolve(pathName + "-" + (++i) + extension);
+        }
+        return out;
+    }
+
+    public static Path generateSources(Path output, String moduleName, List<InMemorySourceFile> sources) throws IOException {
+        Path moduleDir = output.resolve(moduleName);
+        Files.createDirectory(moduleDir);
+        for (InMemorySourceFile source : sources) {
+            Path fileDir = moduleDir;
+            if (!source.packageName.isEmpty()) {
+                String dir = source.packageName.replace('.', File.separatorChar);
+                fileDir = moduleDir.resolve(dir);
+                Files.createDirectories(fileDir);
+            }
+            Files.write(fileDir.resolve(source.className + ".java"), source.source.getBytes());
+        }
+        return moduleDir;
+    }
+
+    public static Path generateSourcesFromTemplate(Path output, String moduleName, String... classNames) throws IOException {
+        List<InMemorySourceFile> sources = new ArrayList<>();
+        for (String className : classNames) {
+            String packageName = getPackageName(className);
+            String simpleName = getSimpleName(className);
+            String content = LOAD_ALL_CLASSES_TEMPLATE
+                    .replace("CLASS", simpleName);
+            if (packageName.isEmpty()) {
+                content = content.replace("package PACKAGE;", packageName);
+            } else {
+                content = content.replace("PACKAGE", packageName);
+            }
+            sources.add(new InMemorySourceFile(packageName, simpleName, content));
+        }
+        return generateSources(output, moduleName, sources);
+    }
+
+    public static void generateModuleInfo(Path moduleDir, List<String> packages, String... dependencies) throws IOException {
+        StringBuilder moduleInfoBuilder = new StringBuilder();
+        Path file = moduleDir.resolve("module-info.java");
+        String moduleName = moduleDir.getFileName().toString();
+        moduleInfoBuilder.append("module ").append(moduleName).append("{\n");
+        for (String dep : dependencies) {
+            moduleInfoBuilder.append("requires ").append(dep).append(";\n");
+        }
+        for (String pkg : packages) {
+            if (!pkg.trim().isEmpty()) {
+                moduleInfoBuilder.append("exports ").append(pkg).append(";\n");
+            }
+        }
+        moduleInfoBuilder.append("}");
+        Files.write(file, moduleInfoBuilder.toString().getBytes());
+    }
+
+    public static void compileSuccess(Path source, Path destination, String... options) throws IOException {
+        if (!compile(source, destination, options)) {
+            throw new AssertionError("Compilation failed.");
+        }
+    }
+
+    public static boolean compile(Path source, Path destination, String... options) throws IOException {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null)) {
+            List<Path> sources
+                    = Files.find(source, Integer.MAX_VALUE,
+                    (file, attrs) -> file.toString().endsWith(".java"))
+                    .collect(Collectors.toList());
+
+            Files.createDirectories(destination);
+            jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singleton(destination));
+
+            List<String> opts = Arrays.asList(options);
+            JavaCompiler.CompilationTask task
+                    = compiler.getTask(null, jfm, null, opts, null,
+                    jfm.getJavaFileObjectsFromPaths(sources));
+            List<String> list = new ArrayList<>(opts);
+            list.addAll(sources.stream()
+                    .map(Path::toString)
+                    .collect(Collectors.toList()));
+            System.err.println("javac options: " + optionsPrettyPrint(list.toArray(new String[list.size()])));
+            return task.call();
+        }
+    }
+
+    public static Path createJarFile(Path jarfile, Path dir) throws IOException {
+        return createJarFile(jarfile, dir, Paths.get("."));
+    }
+
+    public static Path createJarFile(Path jarfile, Path dir, Path file) throws IOException {
+        // create the target directory
+        Path parent = jarfile.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+
+        List<Path> entries = Files.find(dir.resolve(file), Integer.MAX_VALUE,
+                (p, attrs) -> attrs.isRegularFile())
+                .map(dir::relativize)
+                .collect(Collectors.toList());
+
+        try (OutputStream out = Files.newOutputStream(jarfile);
+             JarOutputStream jos = new JarOutputStream(out)) {
+            for (Path entry : entries) {
+                // map the file path to a name in the JAR file
+                Path normalized = entry.normalize();
+                String name = normalized
+                        .subpath(0, normalized.getNameCount())  // drop root
+                        .toString()
+                        .replace(File.separatorChar, '/');
+
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+            }
+        }
+        return jarfile;
+    }
+
+    public static Set<String> getModuleContent(Path module) {
+        Result result = JImageGenerator.getJModTask()
+                .jmod(module)
+                .list();
+        result.assertSuccess();
+        return Stream.of(result.getMessage().split("\r?\n"))
+                .collect(Collectors.toSet());
+    }
+
+    public static void checkModule(Path module, Set<String> expected) throws IOException {
+        Set<String> actual = getModuleContent(module);
+        if (!Objects.equals(actual, expected)) {
+            Set<String> unexpected = new HashSet<>(actual);
+            unexpected.removeAll(expected);
+            Set<String> notFound = new HashSet<>(expected);
+            notFound.removeAll(actual);
+            System.err.println("Unexpected files:");
+            unexpected.forEach(s -> System.err.println("\t" + s));
+            System.err.println("Not found files:");
+            notFound.forEach(s -> System.err.println("\t" + s));
+            throw new AssertionError("Module check failed.");
+        }
+    }
+
+    public static class JModTask {
+
+        private final List<Path> classpath = new ArrayList<>();
+        private final List<Path> libs = new ArrayList<>();
+        private final List<Path> cmds = new ArrayList<>();
+        private final List<Path> config = new ArrayList<>();
+        private final List<Path> jars = new ArrayList<>();
+        private final List<Path> jmods = new ArrayList<>();
+        private final List<String> options = new ArrayList<>();
+        private Path output;
+        private String hashDependencies;
+        private String mainClass;
+        private String moduleVersion;
+
+        public JModTask addNativeLibraries(Path cp) {
+            this.libs.add(cp);
+            return this;
+        }
+
+        public JModTask hashDependencies(String hash) {
+            this.hashDependencies = hash;
+            return this;
+        }
+
+        public JModTask addCmds(Path cp) {
+            this.cmds.add(cp);
+            return this;
+        }
+
+        public JModTask addClassPath(Path cp) {
+            this.classpath.add(cp);
+            return this;
+        }
+
+        public JModTask addConfig(Path cp) {
+            this.config.add(cp);
+            return this;
+        }
+
+        public JModTask addJars(Path jars) {
+            this.jars.add(jars);
+            return this;
+        }
+
+        public JModTask addJmods(Path jmods) {
+            this.jmods.add(jmods);
+            return this;
+        }
+
+        public JModTask jmod(Path output) {
+            this.output = output;
+            return this;
+        }
+
+        public JModTask moduleVersion(String moduleVersion) {
+            this.moduleVersion = moduleVersion;
+            return this;
+        }
+
+        public JModTask mainClass(String mainClass) {
+            this.mainClass = mainClass;
+            return this;
+        }
+
+        public JModTask option(String o) {
+            this.options.add(o);
+            return this;
+        }
+
+        private String modulePath() {
+            // This is expect FIRST jmods THEN jars, if you change this, some tests could fail
+            String jmods = toPath(this.jmods);
+            String jars = toPath(this.jars);
+            return jmods + File.pathSeparator + jars;
+        }
+
+        private String toPath(List<Path> paths) {
+            return paths.stream()
+                    .map(Path::toString)
+                    .collect(Collectors.joining(File.pathSeparator));
+        }
+
+        private String[] optionsJMod(String cmd) {
+            List<String> options = new ArrayList<>();
+            options.add(cmd);
+            if (!cmds.isEmpty()) {
+                options.add(CMDS_OPTION);
+                options.add(toPath(cmds));
+            }
+            if (!config.isEmpty()) {
+                options.add(CONFIG_OPTION);
+                options.add(toPath(config));
+            }
+            if (hashDependencies != null) {
+                options.add(HASH_DEPENDENCIES_OPTION);
+                options.add(hashDependencies);
+            }
+            if (mainClass != null) {
+                options.add(MAIN_CLASS_OPTION);
+                options.add(mainClass);
+            }
+            if (!libs.isEmpty()) {
+                options.add(LIBS_OPTION);
+                options.add(toPath(libs));
+            }
+            if (!classpath.isEmpty()) {
+                options.add(CLASS_PATH_OPTION);
+                options.add(toPath(classpath));
+            }
+            if (!jars.isEmpty() || !jmods.isEmpty()) {
+                options.add(MODULE_PATH_OPTION);
+                options.add(modulePath());
+            }
+            if (moduleVersion != null) {
+                options.add(MODULE_VERSION_OPTION);
+                options.add(moduleVersion);
+            }
+            options.addAll(this.options);
+            if (output != null) {
+                options.add(output.toString());
+            }
+            return options.toArray(new String[options.size()]);
+        }
+
+        public Result create() {
+            return cmd("create");
+        }
+
+        public Result list() {
+            return cmd("list");
+        }
+
+        public Result call() {
+            return cmd("");
+        }
+
+        private Result cmd(String cmd) {
+            String[] args = optionsJMod(cmd);
+            System.err.println("jmod options: " + optionsPrettyPrint(args));
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            int exitCode = jdk.tools.jmod.Main.run(args, new PrintStream(baos));
+            String msg = new String(baos.toByteArray());
+            return new Result(exitCode, msg, output);
+        }
+    }
+
+    public static String getPackageName(String canonicalName) {
+        int index = canonicalName.lastIndexOf('.');
+        return index > 0 ? canonicalName.substring(0, index) : "";
+    }
+
+    public static String getSimpleName(String canonicalName) {
+        int index = canonicalName.lastIndexOf('.');
+        return canonicalName.substring(index + 1);
+    }
+
+    public static class JImageTask {
+
+        private final List<Path> pluginModulePath = new ArrayList<>();
+        private final List<String> options = new ArrayList<>();
+        private Path dir;
+        private Path image;
+
+        public JImageTask pluginModulePath(Path p) {
+            this.pluginModulePath.add(p);
+            return this;
+        }
+
+        public JImageTask image(Path image) {
+            this.image = image;
+            return this;
+        }
+
+        public JImageTask dir(Path dir) {
+            this.dir = dir;
+            return this;
+        }
+
+        public JImageTask option(String o) {
+            this.options.add(o);
+            return this;
+        }
+
+        private String toPath(List<Path> paths) {
+            return paths.stream()
+                    .map(Path::toString)
+                    .collect(Collectors.joining(File.pathSeparator));
+        }
+
+        private String[] optionsJImage(String cmd) {
+            List<String> options = new ArrayList<>();
+            options.add(cmd);
+            if (dir != null) {
+                options.add("--dir");
+                options.add(dir.toString());
+            }
+            if (!pluginModulePath.isEmpty()) {
+                options.add(PLUGINS_MODULE_PATH);
+                options.add(toPath(pluginModulePath));
+            }
+            options.addAll(this.options);
+            options.add(image.toString());
+            return options.toArray(new String[options.size()]);
+        }
+
+        private Result cmd(String cmd, Path returnPath) {
+            String[] args = optionsJImage(cmd);
+            System.err.println("jimage options: " + optionsPrettyPrint(args));
+            StringWriter writer = new StringWriter();
+            int exitCode = jdk.tools.jimage.Main.run(args, new PrintWriter(writer));
+            return new Result(exitCode, writer.toString(), returnPath);
+        }
+
+        public Result extract() {
+            return cmd("extract", dir);
+        }
+
+        public Result recreate() {
+            return cmd("recreate", image);
+        }
+    }
+
+    public static class JLinkTask {
+
+        private final List<Path> jars = new ArrayList<>();
+        private final List<Path> jmods = new ArrayList<>();
+        private final List<Path> pluginModulePath = new ArrayList<>();
+        private final List<String> addMods = new ArrayList<>();
+        private final List<String> limitMods = new ArrayList<>();
+        private final List<String> options = new ArrayList<>();
+        private String modulePath;
+        private Path output;
+        private Path existing;
+
+        public JLinkTask modulePath(String modulePath) {
+            this.modulePath = modulePath;
+            return this;
+        }
+
+        public JLinkTask addJars(Path jars) {
+            this.jars.add(jars);
+            return this;
+        }
+
+        public JLinkTask addJmods(Path jmods) {
+            this.jmods.add(jmods);
+            return this;
+        }
+
+        public JLinkTask pluginModulePath(Path p) {
+            this.pluginModulePath.add(p);
+            return this;
+        }
+
+        public JLinkTask addMods(String moduleName) {
+            this.addMods.add(moduleName);
+            return this;
+        }
+
+        public JLinkTask limitMods(String moduleName) {
+            this.limitMods.add(moduleName);
+            return this;
+        }
+
+        public JLinkTask output(Path output) {
+            this.output = output;
+            return this;
+        }
+
+        public JLinkTask existing(Path existing) {
+            this.existing = existing;
+            return this;
+        }
+
+        public JLinkTask option(String o) {
+            this.options.add(o);
+            return this;
+        }
+
+        private String modulePath() {
+            // This is expect FIRST jmods THEN jars, if you change this, some tests could fail
+            String jmods = toPath(this.jmods);
+            String jars = toPath(this.jars);
+            return jmods + File.pathSeparator + jars;
+        }
+
+        private String toPath(List<Path> paths) {
+            return paths.stream()
+                    .map(Path::toString)
+                    .collect(Collectors.joining(File.pathSeparator));
+        }
+
+        private String[] optionsJLink() {
+            List<String> options = new ArrayList<>();
+            if (output != null) {
+                options.add(OUTPUT_OPTION);
+                options.add(output.toString());
+            }
+            if (!addMods.isEmpty()) {
+                options.add(ADD_MODS_OPTION);
+                options.add(addMods.stream().collect(Collectors.joining(",")));
+            }
+            if (!limitMods.isEmpty()) {
+                options.add(LIMIT_MODS_OPTION);
+                options.add(limitMods.stream().collect(Collectors.joining(",")));
+            }
+            if (!jars.isEmpty() || !jmods.isEmpty()) {
+                options.add(MODULE_PATH_OPTION);
+                options.add(modulePath());
+            }
+            if (modulePath != null) {
+                options.add(MODULE_PATH_OPTION);
+                options.add(modulePath);
+            }
+            if (!pluginModulePath.isEmpty()) {
+                options.add(PLUGINS_MODULE_PATH);
+                options.add(toPath(pluginModulePath));
+            }
+            options.addAll(this.options);
+            return options.toArray(new String[options.size()]);
+        }
+
+        private String[] optionsPostProcessJLink() {
+            List<String> options = new ArrayList<>();
+            if (existing != null) {
+                options.add(POST_PROCESS_OPTION);
+                options.add(existing.toString());
+            }
+            options.addAll(this.options);
+            return options.toArray(new String[options.size()]);
+        }
+
+        public Result call() {
+            String[] args = optionsJLink();
+            System.err.println("jlink options: " + optionsPrettyPrint(args));
+            StringWriter writer = new StringWriter();
+            int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer));
+            return new Result(exitCode, writer.toString(), output);
+        }
+
+        public Result callPostProcess() {
+            String[] args = optionsPostProcessJLink();
+            System.err.println("jlink options: " + optionsPrettyPrint(args));
+            StringWriter writer = new StringWriter();
+            int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer));
+            return new Result(exitCode, writer.toString(), output);
+        }
+    }
+
+    public static class InMemorySourceFile {
+        public final String packageName;
+        public final String className;
+        public final String source;
+
+        public InMemorySourceFile(String packageName, String simpleName, String source) {
+            this.packageName = packageName;
+            this.className = simpleName;
+            this.source = source;
+        }
+    }
+
+    public static class InMemoryFile {
+        private final String path;
+        private final byte[] bytes;
+
+        public String getPath() {
+            return path;
+        }
+
+        public InputStream getBytes() {
+            return new ByteArrayInputStream(bytes);
+        }
+
+        public InMemoryFile(String path, byte[] bytes) {
+            this.path = path;
+            this.bytes = bytes;
+        }
+
+        public InMemoryFile(String path, InputStream is) throws IOException {
+            this(path, readAllBytes(is));
+        }
+    }
+
+    public static byte[] readAllBytes(InputStream is) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buf = new byte[1024];
+        while (true) {
+            int n = is.read(buf);
+            if (n < 0) {
+                break;
+            }
+            baos.write(buf, 0, n);
+        }
+        return baos.toByteArray();
+    }
+}
diff --git a/jdk/test/tools/lib/tests/JImageValidator.java b/jdk/test/tools/lib/tests/JImageValidator.java
new file mode 100644
index 0000000..69c6761
--- /dev/null
+++ b/jdk/test/tools/lib/tests/JImageValidator.java
@@ -0,0 +1,234 @@
+/*
+ * 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 tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import jdk.internal.jimage.BasicImageReader;
+import jdk.internal.jimage.ImageLocation;
+
+/**
+ *
+ * JDK Modular image validator
+ */
+public class JImageValidator {
+
+    private static final String[] dirs = {"bin", "lib"};
+
+    private final File rootDir;
+    private final List<String> expectedLocations;
+    private final String module;
+    private long moduleExecutionTime;
+    private long javaExecutionTime;
+    private final List<String> unexpectedPaths;
+    private final List<String> unexpectedFiles;
+    private final String[] expectedFiles;
+
+    public JImageValidator(String module, List<String> expectedLocations,
+            File rootDir,
+            List<String> unexpectedPaths,
+            List<String> unexpectedFiles) throws Exception {
+        this(module, expectedLocations, rootDir, unexpectedPaths, unexpectedFiles, null);
+    }
+
+    public JImageValidator(String module, List<String> expectedLocations,
+            File rootDir,
+            List<String> unexpectedPaths,
+            List<String> unexpectedFiles,
+            String[] expectedFiles) throws IOException {
+        if (!rootDir.exists()) {
+            throw new IOException("Image root dir not found " +
+                    rootDir.getAbsolutePath());
+        }
+        this.expectedLocations = expectedLocations;
+        this.rootDir = rootDir;
+        this.module = module;
+        this.unexpectedPaths = unexpectedPaths;
+        this.unexpectedFiles = unexpectedFiles;
+        this.expectedFiles = expectedFiles == null ? new String[0] : expectedFiles;
+    }
+
+    public void validate() throws IOException {
+        for (String d : dirs) {
+            File dir = new File(rootDir, d);
+            if (!dir.isDirectory()) {
+                throw new IOException("Invalid directory " + d);
+            }
+        }
+
+        //check jimage file
+        Path path = rootDir.toPath().resolve("lib").resolve("modules");
+        if (!Files.isRegularFile(path)) {
+            throw new IOException(path + " No jimage file generated");
+        }
+
+        // Check binary file
+        File launcher = new File(rootDir, "bin" + File.separator + module);
+        if (launcher.exists()) {
+            ProcessBuilder builder = new ProcessBuilder("sh", launcher.getAbsolutePath());
+            long t = System.currentTimeMillis();
+            Process process = builder.inheritIO().start();
+            int ret = waitFor(process);
+            moduleExecutionTime += System.currentTimeMillis() - t;
+            if (ret != 0) {
+                throw new IOException("Image " + module + " execution failed, check logs.");
+            }
+        }
+
+        for (String f : expectedFiles) {
+            File dd = new File(rootDir, f);
+            if (!dd.exists()) {
+                throw new IOException("Expected File " + f + " not found");
+            }
+        }
+
+        //Walk and check that unexpected files are not there
+        try (java.util.stream.Stream<Path> stream = Files.walk(rootDir.toPath())) {
+            stream.forEach((p) -> {
+                for (String u : unexpectedFiles) {
+                    if (p.toString().equals(u)) {
+                        throw new RuntimeException("Seen unexpected path " + p);
+                    }
+                }
+            });
+        }
+
+        File javaLauncher = new File(rootDir, "bin" + File.separator +
+                (isWindows() ? "java.exe" : "java"));
+        if (javaLauncher.exists()) {
+            ProcessBuilder builder = new ProcessBuilder(javaLauncher.getAbsolutePath(),
+                    "-version");
+            long t = System.currentTimeMillis();
+            Process process = builder.start();
+            int ret = waitFor(process);
+            javaExecutionTime += System.currentTimeMillis() - t;
+            if (ret != 0) {
+                throw new RuntimeException("java launcher execution failed, check logs.");
+            }
+        } else {
+            throw new IOException("java launcher not found.");
+        }
+
+        // Check release file
+        File release = new File(rootDir, "release");
+        if (!release.exists()) {
+            throw new IOException("Release file not generated");
+        } else {
+            Properties props = new Properties();
+            try (FileInputStream fs = new FileInputStream(release)) {
+                props.load(fs);
+                String s = props.getProperty("MODULES");
+                if (s == null) {
+                    throw new IOException("No MODULES property in release");
+                }
+                if (!s.contains(module)) {
+                    throw new IOException("Module not found in release file " + s);
+                }
+            }
+        }
+
+    }
+
+    private int waitFor(Process process) {
+        try {
+            return process.waitFor();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").startsWith("Windows");
+    }
+
+    public static void validate(Path jimage, List<String> expectedLocations,
+            List<String> unexpectedPaths) throws IOException {
+        BasicImageReader reader = BasicImageReader.open(jimage);
+        // Validate expected locations
+        List<String> seenLocations = new ArrayList<>();
+        for (String loc : expectedLocations) {
+            ImageLocation il = reader.findLocation(loc);
+            if (il == null) {
+                throw new IOException("Location " + loc + " not present in " + jimage);
+            }
+        }
+        seenLocations.addAll(expectedLocations);
+
+        for (String s : reader.getEntryNames()) {
+            if (s.endsWith(".class") && !s.endsWith("module-info.class")) {
+                ImageLocation il = reader.findLocation(s);
+                try {
+                    byte[] r = reader.getResource(il);
+                    if(r == null) {
+                        System.out.println("IL, compressed " +
+                                il.getCompressedSize() + " uncompressed " +
+                                il.getUncompressedSize());
+                        throw new IOException("NULL RESOURCE " + s);
+                    }
+                    readClass(r);
+                } catch (IOException ex) {
+                    System.err.println(s + " ERROR " + ex);
+                    throw ex;
+                }
+            }
+            if (seenLocations.contains(s)) {
+                seenLocations.remove(s);
+            }
+            for(String p : unexpectedPaths) {
+                if (s.equals(p)) {
+                    throw new IOException("Seen unexpected path " + s);
+                }
+            }
+        }
+        if (!seenLocations.isEmpty()) {
+            throw new IOException("ImageReader did not return " + seenLocations);
+        }
+    }
+
+    public long getJavaLauncherExecutionTime() {
+        return javaExecutionTime;
+    }
+
+    public long getModuleLauncherExecutionTime() {
+        return moduleExecutionTime;
+    }
+
+    public static void readClass(byte[] clazz) throws IOException {
+        try (InputStream stream = new ByteArrayInputStream(clazz)) {
+            ClassFile.read(stream);
+        } catch (ConstantPoolException e) {
+            throw new IOException(e);
+        }
+    }
+}
diff --git a/jdk/test/tools/lib/tests/Result.java b/jdk/test/tools/lib/tests/Result.java
new file mode 100644
index 0000000..0854fff
--- /dev/null
+++ b/jdk/test/tools/lib/tests/Result.java
@@ -0,0 +1,84 @@
+/*
+ * 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 tests;
+
+import java.nio.file.Path;
+
+public class Result {
+    private final int exitCode;
+    private final String message;
+    private final Path imageFile;
+
+    public Result(int exitCode, String message, Path imageFile) {
+        this.exitCode = exitCode;
+        this.message = message;
+        this.imageFile = imageFile;
+    }
+
+    public int getExitCode() {
+        return exitCode;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public Path getFile() {
+        return imageFile;
+    }
+
+    public void assertFailure() {
+        assertFailure(null);
+    }
+
+    public void assertFailure(String expected) {
+        if (getExitCode() == 0) {
+            System.err.println(getMessage());
+            throw new AssertionError("Failure expected: " + getFile());
+        }
+        if (getExitCode() != 1 && getExitCode() != 2) {
+            System.err.println(getMessage());
+            throw new AssertionError("Abnormal exit: " + getFile());
+        }
+        if (expected != null) {
+            if (expected.isEmpty()) {
+                throw new AssertionError("Expected error is empty");
+            }
+            if (!getMessage().matches(expected) && !getMessage().contains(expected)) {
+                System.err.println(getMessage());
+                throw new AssertionError("Output does not fit regexp: " + expected);
+            }
+        }
+        System.err.println("Failed as expected. " + (expected != null ? expected : ""));
+        System.err.println(getMessage());
+    }
+
+    public Path assertSuccess() {
+        if (getExitCode() != 0) {
+            System.err.println(getMessage());
+            throw new AssertionError("Unexpected failure: " + getExitCode());
+        }
+        return getFile();
+    }
+}
diff --git a/jdk/test/tools/pack200/ModuleAttributes.java b/jdk/test/tools/pack200/ModuleAttributes.java
new file mode 100644
index 0000000..a3df72b
--- /dev/null
+++ b/jdk/test/tools/pack200/ModuleAttributes.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+/*
+ * @test
+ * @bug 8048100
+ * @summary test the new Module attributes
+ * @compile -XDignore.symbol.file Utils.java ModuleAttributes.java
+ * @run main ModuleAttributes
+ */
+public class ModuleAttributes {
+
+    public static void main(String... args) throws Exception {
+        new ModuleAttributes().run();
+    }
+
+    public void run() throws Exception {
+        File file = createModuleJar();
+        Utils.testWithRepack(file,
+                "--effort=1",
+                "--unknown-attribute=error");
+    }
+
+    File createModuleJar() throws IOException {
+        File libDir = new File(Utils.JavaHome, "lib");
+        File modules = new File(libDir, "modules");
+        File outDir = new File("out");
+
+        List<String> cmdList = new ArrayList<>();
+        cmdList.add(Utils.getJimageCmd());
+        cmdList.add("extract");
+        cmdList.add(modules.getAbsolutePath());
+        cmdList.add("--dir");
+        cmdList.add(outDir.getName());
+        Utils.runExec(cmdList);
+
+        FileFilter filter = (File file) -> file.getName().equals("module-info.class");
+        List<File> mfiles = Utils.findFiles(outDir, filter);
+
+        List<String> contents = new ArrayList<>(mfiles.size());
+        mfiles.stream().forEach((f) -> {
+            contents.add(f.getAbsolutePath());
+        });
+
+        File listFile = new File("mfiles.list");
+        Utils.createFile(listFile, contents);
+        File testFile = new File("test.jar");
+        Utils.jar("cvf", testFile.getName(), "@" + listFile.getName());
+        Utils.recursiveDelete(outDir);
+        return testFile;
+    }
+}
diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java
index 60f2d0c..663cdc3 100644
--- a/jdk/test/tools/pack200/Utils.java
+++ b/jdk/test/tools/pack200/Utils.java
@@ -101,6 +101,7 @@
 
         compiler("-d",
                 XCLASSES.getName(),
+                "-XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED",
                 "@" + tmpFile.getAbsolutePath());
 
         jar("cvfe",
@@ -137,6 +138,7 @@
         init();
         List<String> cmds = new ArrayList<String>();
         cmds.add(getJavaCmd());
+        cmds.add("-XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED");
         cmds.add("-cp");
         cmds.add(VerifierJar.getName());
         cmds.add("sun.tools.pack.verify.Main");
@@ -561,13 +563,12 @@
     }
 
     static File createRtJar() throws IOException {
-        File LibDir = new File(JavaHome, "lib");
-        File ModuleDir = new File(LibDir, "modules");
-        File BootModules = new File(ModuleDir, "bootmodules.jimage");
+        File libDir = new File(JavaHome, "lib");
+        File modules = new File(libDir, "modules");
         List<String> cmdList = new ArrayList<>();
         cmdList.add(getJimageCmd());
         cmdList.add("extract");
-        cmdList.add(BootModules.getAbsolutePath());
+        cmdList.add(modules.getAbsolutePath());
         cmdList.add("--dir");
         cmdList.add("out");
         runExec(cmdList);
diff --git a/jdk/test/tools/pack200/pack200-verifier/make/build.xml b/jdk/test/tools/pack200/pack200-verifier/make/build.xml
index b783ffd..2bb786b 100644
--- a/jdk/test/tools/pack200/pack200-verifier/make/build.xml
+++ b/jdk/test/tools/pack200/pack200-verifier/make/build.xml
@@ -1,4 +1,4 @@
-<project name="PackageVerify" default="dist" basedir="..">
+<project name="PackageVerify" default="jar-file" basedir="..">
   <!-- Requires ant 1.6.1+ and JDK 1.7+-->
 
   <!-- set global properties for this build -->
@@ -21,30 +21,35 @@
 
   <target name="compile" depends="init">
     <!-- Compile the java code from ${src} into ${build} -->
-    <javac 
-	source="1.7"
-	srcdir="${src}"
-	destdir="${build}/classes"
-	verbose="no"
-	debug="on"
-    />
+     <javac 
+	   source="1.8"
+	   srcdir="${src}"
+	   destdir="${build}/classes"
+	   verbose="no"
+	   debug="on">
+       <compilerarg value="-XaddExports:jdk.jdeps/com.sun.tools.classfile"/>
+     </javac>
   </target>
 
   <target name="doc" depends="init, compile">
       <javadoc
-        source="1.7"
+        source="1.8"
         sourcepath="${src}"
         destdir="${api}"
       />
   </target>
-  <target name="dist" depends="compile, doc">
-    <!-- Put everything in jar file -->
+  
+  <target name="jar-file" depends="compile">
+  <!-- Put everything in jar file -->
     <jar destfile="${dist}/pack200-verifier.jar">
-	<manifest>
-	   <attribute name="Main-Class" value="sun.tools.pack.verify.Main"/>
-	</manifest>
-	<fileset dir="${classes}"/>
+      <manifest>
+        <attribute name="Main-Class" value="sun.tools.pack.verify.Main"/>
+      </manifest>
+      <fileset dir="${classes}"/>
     </jar>
+</target>
+  
+  <target name="all" depends="jar-file">
     <zip destfile="dist/pack200-verifier-doc.zip">
         <fileset dir="${api}"/>
     </zip>
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 02b0a7e..ac54c14 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, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -26,7 +26,11 @@
 
 import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.Annotation;
-import com.sun.tools.classfile.Annotation.*;
+import com.sun.tools.classfile.Annotation.Annotation_element_value;
+import com.sun.tools.classfile.Annotation.Array_element_value;
+import com.sun.tools.classfile.Annotation.Class_element_value;
+import com.sun.tools.classfile.Annotation.Enum_element_value;
+import com.sun.tools.classfile.Annotation.Primitive_element_value;
 import com.sun.tools.classfile.AnnotationDefault_attribute;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.Attributes;
@@ -35,8 +39,24 @@
 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.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+import com.sun.tools.classfile.ConstantPool.InvalidIndex;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.ConstantValue_attribute;
 import com.sun.tools.classfile.DefaultAttribute;
@@ -45,6 +65,8 @@
 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;
@@ -52,8 +74,13 @@
 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.Opcode;
 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
@@ -66,14 +93,22 @@
 import com.sun.tools.classfile.SourceFile_attribute;
 import com.sun.tools.classfile.SourceID_attribute;
 import com.sun.tools.classfile.StackMapTable_attribute;
-import com.sun.tools.classfile.StackMapTable_attribute.*;
+import com.sun.tools.classfile.StackMapTable_attribute.append_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.chop_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.full_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.same_frame;
+import com.sun.tools.classfile.StackMapTable_attribute.same_frame_extended;
+import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame;
+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 java.util.*;
+import com.sun.tools.classfile.Version_attribute;
 import java.io.*;
+import java.util.*;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import xmlkit.XMLKit.Element;
@@ -383,7 +418,9 @@
         AccessFlags af = new AccessFlags(c.access_flags.flags);
         klass.setAttr("flags", flagString(af, klass));
         if (!"java/lang/Object".equals(thisk)) {
-            klass.setAttr("super", c.getSuperclassName());
+            if (c.super_class != 0) {
+                klass.setAttr("super", c.getSuperclassName());
+            }
         }
         for (int i : c.interfaces) {
             klass.add(new Element("Interface", "name", getCpString(i)));
@@ -854,7 +891,6 @@
     }
 }
 
-
 class AttributeVisitor implements Attribute.Visitor<Element, Element> {
     final ClassFile cf;
     final ClassReader x;
@@ -981,6 +1017,21 @@
     }
 
     @Override
+    public Element visitConcealedPackages(ConcealedPackages_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");
+            String pkg = x.getCpString(i);
+            ee.setAttr("package", pkg);
+            e.add(ee);
+        }
+        e.trimToSize();
+        e.sort();
+        p.add(e);
+        return null;
+    }
+
+    @Override
     public Element visitConstantValue(ConstantValue_attribute cv, Element p) {
         Element e = new Element(x.getCpString(cv.attribute_name_index));
         e.add(x.getCpString(cv.constantvalue_index));
@@ -1063,6 +1114,52 @@
         return null; // already added to parent
     }
 
+    private void parseModuleRequires(RequiresEntry[] res, Element p) {
+        for (RequiresEntry re : res) {
+            Element er = new Element("Requires");
+            er.setAttr("module", x.getCpString(re.requires_index));
+            er.setAttr("flags", Integer.toString(re.requires_flags));
+            p.add(er);
+        }
+    }
+
+    private void parseModuleExports(ExportsEntry[] exports, Element p) {
+        Element ex = new Element("Exports");
+        for (ExportsEntry export : exports) {
+            Element exto = new Element("exports");
+            exto.setAttr("package", x.getCpString(export.exports_index));
+            for ( int idx : export.exports_to_index) {
+                exto.setAttr("module", x.getCpString(idx));
+            }
+            ex.add(exto);
+        }
+        p.add(ex);
+    }
+
+    private void parseModuleProvides(ProvidesEntry[] provides, Element p) {
+        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));
+        }
+        p.add(ex);
+    }
+
+    @Override
+    public Element visitModule(Module_attribute m, Element p) {
+        Element e = new Element(x.getCpString(m.attribute_name_index));
+        parseModuleRequires(m.requires, e);
+        parseModuleExports(m.exports, e);
+        for (int idx : m.uses_index) {
+            Element ei = new Element("Uses");
+            ei.setAttr("used_class", x.getCpString(idx));
+            e.add(ei);
+        }
+        parseModuleProvides(m.provides, e);
+        p.add(e);
+        return null;
+    }
+
     @Override
     public Element visitLocalVariableTypeTable(LocalVariableTypeTable_attribute lvtt,
                                                     Element p) {
@@ -1362,6 +1459,52 @@
         p.add(e);
         return null;
     }
+
+    @Override
+    public Element visitHashes(Hashes_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);
+            e.add(ee);
+        }
+        e.trimToSize();
+        e.sort();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitMainClass(MainClass_attribute attr, Element p) {
+        Element e = new Element(x.getCpString(attr.attribute_name_index));
+        e.add(x.getCpString(attr.main_class_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitTargetPlatform(TargetPlatform_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));
+        e.add(x.getCpString(attr.os_version_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
+
+    @Override
+    public Element visitVersion(Version_attribute attr, Element p) {
+        Element e = new Element(x.getCpString(attr.attribute_name_index));
+        e.add(x.getCpString(attr.version_index));
+        e.trimToSize();
+        p.add(e);
+        return null;
+    }
 }
 
 class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor<Element, Void> {
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 5fb34d8..a0b1130 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -352,3 +352,4 @@
 7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107
 fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108
 f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109
+9b4c916633f8d61509a3dc6175efdf185b421343 jdk-9+110
diff --git a/langtools/make/CompileInterim.gmk b/langtools/make/CompileInterim.gmk
index 2ccd58f..06a13d9 100644
--- a/langtools/make/CompileInterim.gmk
+++ b/langtools/make/CompileInterim.gmk
@@ -32,23 +32,35 @@
 include SetupJavaCompilers.gmk
 
 ################################################################################
-# Setup the rules to build the interim langtools jar, which is compiled by
-# the boot javac and can be run on the boot jdk. This will be used to compile
-# the rest of the product. Include the Genstubs build tool in this compilation
-# as it will be used together with the interim javac.
-$(eval $(call SetupJavaCompilation,BUILD_INTERIM_LANGTOOLS, \
-    SETUP := BOOT_JAVAC, \
-    DISABLE_SJAVAC := true, \
-    SRC := $(LANGTOOLS_TOPDIR)/src/java.compiler/share/classes \
-      $(LANGTOOLS_TOPDIR)/src/jdk.compiler/share/classes \
-      $(LANGTOOLS_TOPDIR)/src/jdk.javadoc/share/classes \
-      $(LANGTOOLS_TOPDIR)/src/jdk.jdeps/share/classes \
-      $(SUPPORT_OUTPUTDIR)/gensrc/jdk.compiler \
-      $(SUPPORT_OUTPUTDIR)/gensrc/jdk.javadoc \
-      $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdeps, \
-    EXCLUDES := sun, \
-    COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \
-    BIN := $(BUILDTOOLS_OUTPUTDIR)/langtools_interim_classes, \
-    JAR := $(INTERIM_LANGTOOLS_JAR)))
+# Setup the rules to build interim langtools, which is compiled by the boot 
+# javac and can be run on the boot jdk. This will be used to compile
+# the rest of the product. Each module is compiled separately to allow a modular
+# boot jdk to override system classes using -Xoverride:.
 
-all: $(BUILD_INTERIM_LANGTOOLS)
+# Param 1 - Name of module to compile
+# Param 2 - Name of modules to depend on
+define SetupInterimModule
+  $$(eval $$(call SetupJavaCompilation,BUILD_INTERIM_$(strip $1), \
+      SETUP := BOOT_JAVAC, \
+      DISABLE_SJAVAC := true, \
+      SRC := $(LANGTOOLS_TOPDIR)/src/$(strip $1)/share/classes \
+          $$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1)), \
+      EXCLUDES := sun com/sun/tools/jdeps com/sun/tools/javap, \
+      EXCLUDE_FILES := module-info.java, \
+      COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \
+      BIN := $(BUILDTOOLS_OUTPUTDIR)/override_modules/$(strip $1), \
+      ADD_JAVAC_FLAGS := -Xbootclasspath/p:$$(call PathList, \
+          $$(foreach m, $2, $(BUILDTOOLS_OUTPUTDIR)/override_modules/$$m)), \
+  ))
+
+  $$(BUILD_INTERIM_$(strip $1)): $$(foreach m, $2, $$(BUILD_INTERIM_$(strip $$m)))
+
+  TARGETS += $$(BUILD_INTERIM_$(strip $1))
+endef
+
+$(eval $(call SetupInterimModule, java.compiler))
+$(eval $(call SetupInterimModule, jdk.compiler, java.compiler))
+$(eval $(call SetupInterimModule, jdk.jdeps, jdk.compiler java.compiler))
+$(eval $(call SetupInterimModule, jdk.javadoc, java.compiler jdk.compiler))
+
+all: $(TARGETS)
diff --git a/langtools/make/build.properties b/langtools/make/build.properties
index fdc1aa0..38939fa 100644
--- a/langtools/make/build.properties
+++ b/langtools/make/build.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -24,58 +24,13 @@
 #
 
 #javac configuration for "normal build" (these will be passed to the bootstrap compiler):
-javac.debug = true
-javac.debuglevel = source,lines,vars
-javac.extra.opts=-XDignore.symbol.file=true
-javac.includes=
-javac.lint.opts = -Xlint:all,-deprecation -Werror
-javac.source = 8
-javac.target = 8
+javac.opts = -XDignore.symbol.file=true -Xlint:all,-deprecation,-options -Werror -g:source,lines,vars
+javac.source = 9
+javac.target = 9
 
-#javac configuration for bootstrap build (these will be passed to the compiler from the given boot JDK):
-boot.javac.extra.opts=-XDignore.symbol.file=true
-boot.javac.includes = \
-        javax/annotation/processing/ \
-        javax/lang/model/ \
-        javax/tools/ \
-        jdk/ \
-        com/sun/source/ \
-        com/sun/tools/javac/ \
-        com/sun/tools/doclint/
-boot.javac.lint.opts=
-boot.javac.source = 8
-boot.javac.target = 8
-
-#configuration of submodules (share by both the bootstrap and normal compilation):
-langtools.modules=java.compiler:jdk.compiler:jdk.jdeps:jdk.javadoc:jdk.jshell:jdk.internal.le:jdk.jdi
-java.compiler.dependencies=
-jdk.compiler.dependencies=java.compiler
-jdk.javadoc.dependencies=java.compiler:jdk.compiler
-jdk.jdeps.dependencies=java.compiler:jdk.compiler
-jdk.internal.le.dependencies=
-jdk.jdi.dependencies=
-jdk.jshell.dependencies=java.compiler:jdk.internal.le:jdk.compiler:jdk.jdi
-
-tool.javac.main.class=com.sun.tools.javac.Main
-tool.javadoc.main.class=com.sun.tools.javadoc.Main
-tool.javap.main.class=com.sun.tools.javap.Main
-tool.javah.main.class=com.sun.tools.javah.Main
-tool.sjavac.main.class=com.sun.tools.sjavac.Main
-tool.jshell.main.class=jdk.internal.jshell.tool.JShellTool
-
-javac.resource.includes = \
+langtools.resource.includes = \
         com/sun/tools/javac/resources/compiler.properties
 
-#test configuration:
-jtreg.tests=
-boot.javac.tests = tools/javac
-crules.tests = ../make/test/crules
-
-#javadoc configuration
-javadoc.jls.cite=The Java&trade; Language Specification
-javadoc.jls.option=-tag "jls:a:See &lt;cite&gt;${javadoc.jls.cite}&lt;/cite&gt;:" \
-    -tag "implNote:a:Implementation Note:"
-
 # Version info -- override as needed
 jdk.version = 9
 build.number = b00
@@ -89,3 +44,14 @@
 # FIXME -- need to include openjdk as needed
 release = ${jdk.version}-${milestone}
 full.version = ${release}+${build.number}
+
+#tools configuration:
+tool.javac.main.class=com.sun.tools.javac.Main
+tool.javadoc.main.class=jdk.javadoc.internal.tool.Main
+tool.javap.main.class=com.sun.tools.javap.Main
+tool.javah.main.class=com.sun.tools.javah.Main
+tool.sjavac.main.class=com.sun.tools.sjavac.Main
+tool.jshell.main.class=jdk.internal.jshell.tool.JShellTool
+
+#test configuration:
+jtreg.tests=
diff --git a/langtools/make/build.xml b/langtools/make/build.xml
index 051eae5..ee0c328 100644
--- a/langtools/make/build.xml
+++ b/langtools/make/build.xml
@@ -1,28 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.  Oracle designates this
- particular file as subject to the "Classpath" exception as provided
- by Oracle in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
--->
+  ~ 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
+  ~ under the terms of the GNU General Public License version 2 only, as
+  ~ published by the Free Software Foundation.  Oracle designates this
+  ~ particular file as subject to the "Classpath" exception as provided
+  ~ by Oracle in the LICENSE file that accompanied this code.
+  ~
+  ~ This code is distributed in the hope that it will be useful, but WITHOUT
+  ~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  ~ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  ~ version 2 for more details (a copy is included in the LICENSE file that
+  ~ accompanied this code).
+  ~
+  ~ You should have received a copy of the GNU General Public License version
+  ~ 2 along with this work; if not, write to the Free Software Foundation,
+  ~ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  ~
+  ~ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+  ~ or visit www.oracle.com if you need additional information or have any
+  ~ questions.
+  -->
 
 <!--
  This is a convenience build file supporting development in the langtools
@@ -33,33 +33,23 @@
  External dependencies are specified via properties. These can be given
  on the command line, or by providing a local build.properties file.
  (They can also be edited into make/build.properties, although that is not
- recommended.)  At a minimum, boot.java.home must be set to the installed
+ recommended.)  At a minimum, langtools.jdk.home must be set to the installed
  location of the version of JDK used to build this repository. Additional
  properties may be required, depending on the targets that are built.
- For example, to run any of the jtreg tests you must set jtreg.home,
- to run findbugs on the code you must set findbugs.home, and so on.
+ For example, to run any of the jtreg tests you must set jtreg.home.
 
- The main build happens in two phases:
- - First, javac is built using ${boot.java.home}. (This implies a constraint
-   on the source code that they can be compiled with the previous version of JDK.
- - Second, all required classes are compiled with the latest javac, created
-   in the previous step.
- The build generally builds one module at time.
+ The output of the build is as follows:
 
- For more details on the stub generator, see
-    http://blogs.sun.com/jjg/entry/building_javac_for_jdk7
-
- Internal details ...
-
- Bootstrap classes are built into the build/bootstrap/<module-name>/classes directory.
- Final classes are built into the build/<module-name>/classes directory.
- Final runnable javac is in dist/bin and dist/lib. Bootstrap javac (if requested by
- using the build-bootstrap-javac target) is built into dist/bootstrap.
+ build
+   |-bin (scripts to invoke various tools, javac, javah etc.)
+   |-genrsc (generated sources - i.e. properties)
+   |-modules (compiled classes in a modular layout)
+   |-jtreg (test work/results)
+   |-toolclasses (tools used for building - like the property compiler)
 
  This file is organized into sections as follows:
  - global property definitions
- - primary top level targets (cleaning, building, testing, producing javac)
- - secondary top level targets (code analysis, diagnostics, extra documentation, etc.)
+ - primary top level targets (cleaning, building)
  - utility definitions
  -->
 
@@ -80,25 +70,19 @@
     <property file="${user.home}/.openjdk/build.properties"/>
 
     <!-- Convenient shorthands for standard locations within the workspace. -->
-    <property name="build.dir" location="build"/>
-    <property name="build.crules.dir" location="${build.dir}/crules"/>
-    <property name="build.jtreg.dir" location="${build.dir}/jtreg"/>
-    <property name="build.toolclasses.dir" location="${build.dir}/toolclasses"/>
-    <property name="build.javadoc.dir" location="${build.dir}/javadoc"/>
-    <property name="dist.dir" location="dist"/>
-    <property name="dist.bin.dir" location="${dist.dir}/bin"/>
-    <property name="dist.lib.dir" location="${dist.dir}/lib"/>
-    <property name="dist.findbugs.dir" location="${dist.dir}/findbugs"/>
-    <property name="dist.checkstyle.dir" location="${dist.dir}/checkstyle"/>
+    <property name="src.dir" location="src"/>
+    <property name="test.dir" location="test"/>
     <property name="make.dir" location="make"/>
     <property name="make.conf.dir" location="${make.dir}/conf"/>
     <property name="make.tools.dir" location="${make.dir}/tools"/>
-    <property name="test.dir" location="test"/>
+    <property name="build.dir" location="build"/>
+    <property name="build.modules" location="${build.dir}/modules"/>
+    <property name="build.gensrc" location="${build.dir}/gensrc"/>
+    <property name="build.tools" location="${build.dir}/toolclasses"/>
+    <property name="build.bin" location="${build.dir}/bin"/>
+    <property name="build.jtreg" location="${build.dir}/jtreg"/>
+    <property name="build.prevsrc" location="${build.dir}/prevsrc"/>
 
-    <property name="boot.build.dir" location="${build.dir}/bootstrap"/>
-    <property name="boot.dist.dir" location="${dist.dir}/bootstrap"/>
-    <property name="boot.dist.bin.dir" location="${boot.dist.dir}/bin"/>
-    <property name="boot.dist.lib.dir" location="${boot.dist.dir}/lib"/>
 
     <!-- java.marker is set to a marker file to check for within a Java install dir.
          The best file to check for across Solaris/Linux/Windows/MacOS is one of the
@@ -113,786 +97,28 @@
     <!-- Standard property values, if not overriden by earlier settings. -->
     <property file="${make.dir}/build.properties"/>
 
-    <!-- launcher.java is used in the launcher scripts provided to run
-        the tools' jar files.  If it has not already been set, then
-        default it to use ${target.java.home}, if available, otherwise
-        quietly default to simply use "java". -->
-    <condition property="launcher.java"
-        value="${target.java.home}/bin/java" else="java">
-        <isset property="target.java.home"/>
+    <condition property="langtools.jdk.home" value="${jdk.home}">
+        <isset property="jdk.home" />
     </condition>
 
-    <!-- setup basic properties holding paths to all sources, generated source and class directories
-         (both boot and non-boot) -->
-    <pathconvert property="langtools.sources">
-        <path>
-            <pathelement path="${langtools.modules}" />
-        </path>
-        <map from="${basedir}/" to="${basedir}/src/" />
-        <mapper type="glob" from="*" to="*/share/classes"/>
-    </pathconvert>
-    <pathconvert property="langtools.gensrc">
-        <path>
-            <pathelement path="${langtools.modules}" />
-        </path>
-        <map from="${basedir}/" to="${build.dir}/" />
-        <mapper type="glob" from="*" to="*/gensrc"/>
-    </pathconvert>
-    <pathconvert property="langtools.boot.classes">
-        <path>
-            <pathelement path="${langtools.modules}" />
-        </path>
-        <map from="${basedir}/" to="${boot.build.dir}/" />
-        <mapper type="glob" from="*" to="*/classes"/>
-    </pathconvert>
-    <pathconvert property="langtools.classes">
-        <path>
-            <pathelement path="${langtools.modules}" />
-        </path>
-        <map from="${basedir}/" to="${build.dir}/" />
-        <mapper type="glob" from="*" to="*/classes"/>
-    </pathconvert>
+    <!-- launcher.java is used in the launcher scripts provided to run
+        the tools' jar files.  If it has not already been set, then
+        default it to use ${langtools.jdk.home}, if available, otherwise
+        quietly default to simply use "java". -->
+    <condition property="launcher.java"
+        value="${langtools.jdk.home}/bin/java" else="java">
+        <isset property="langtools.jdk.home"/>
+    </condition>
 
     <!--
-        **** Primary targets
+        **** Check targets
     -->
 
-    <target name="clean" description="Delete all generated files">
-        <delete dir="${build.dir}"/>
-        <delete dir="${dist.dir}"/>
-    </target>
-
-    <target name="build" depends="build-all-tools">
-    </target>
-
-    <target name="build-all-tools" depends="build-all-classes,-def-build-all-module-jars,-def-build-tool">
-        <build-all-module-jars />
-        <build-tool name="javac"/>
-        <build-tool name="javadoc"/>
-        <build-tool name="javap"/>
-        <build-tool name="javah"/>
-        <build-tool name="sjavac"/>
-        <build-tool name="jshell"/>
-    </target>
-
-    <target name="build-all-classes" depends="-def-build-all-module-classes,build-bootstrap-javac-classes">
-        <build-all-module-classes />
-    </target>
-
-    <target name="jtreg" depends="build-all-tools,-def-jtreg">
-        <jtreg-tool name="all" tests="${jtreg.tests}"/>
-    </target>
-
-    <target name="javadoc" depends="build-all-classes,-def-javadoc-tool">
-        <javadoc-tool options="${javadoc.jls.option}"/>
-    </target>
-
-    <target name="build-bootstrap-javac-classes" depends="-check-boot.java.home,-def-build-all-module-classes">
-        <build-all-module-classes compilation.kind="boot." />
-    </target>
-
-    <!--
-        **** Extra targets
-    -->
-
-    <target name="build-bootstrap-javac" depends="build-bootstrap-javac-classes,-def-build-all-module-jars,-def-build-tool">
-        <build-all-module-jars compilation.kind="boot." />
-        <build-tool name="javac" compilation.kind="boot." />
-    </target>
-
-    <target name="jtreg-bootstrap-javac" depends="build-bootstrap-javac,-def-jtreg">
-        <jtreg-tool name="bootstrap-javac"
-                    tests="${boot.javac.tests}"
-                    langtools.classes="${langtools.boot.classes}"/>
-    </target>
-
-    <target name="checkstyle" depends="-def-checkstyle"
-        description="Generates reports for code convention violations.">
-        <mkdir dir="${dist.checkstyle.dir}"/>
-        <checkstyle config="${make.conf.dir}/checkstyle-langtools.xml"
-              failureProperty="checkstyle.failure"
-              failOnViolation="false">
-            <formatter type="xml" tofile="${dist.checkstyle.dir}/checkstyle_report.xml"/>
-            <fileset dir="src" includes="**/*.java, **/*.properties"/>
-        </checkstyle>
-        <!-- transform the output to a simple html -->
-        <xslt  in="${dist.checkstyle.dir}/checkstyle_report.xml"
-               out="${dist.checkstyle.dir}/checkstyle_report.html"
-               style="${checkstyle.home}/contrib/checkstyle-simple.xsl"/>
-        <!-- transform the output to a very simple emacs friendly text file -->
-        <xslt  in="${dist.checkstyle.dir}/checkstyle_report.xml"
-               out="${dist.checkstyle.dir}/checkstyle_report.tmp"
-               style="${make.conf.dir}/checkstyle-emacs.xsl"/>
-        <!-- beautify remove extra lines -->
-        <move file="${dist.checkstyle.dir}/checkstyle_report.tmp"
-             toFile="${dist.checkstyle.dir}/checkstyle_report.emacs.txt">
-            <filterchain>
-                <ignoreblank/>
-                <replaceregex byline="true" pattern="^File:" replace="${line.separator}File:"/>
-            </filterchain>
-        </move>
-    </target>
-    <!-- target can be invoked from an ide, the output of which can be used
-         to access and fix the errors directly.
-     -->
-    <target name="checkstyle-ide" depends="checkstyle">
-        <concat>
-            <fileset file="${dist.checkstyle.dir}/checkstyle_report.emacs.txt"/>
-        </concat>
-    </target>
-
-    <target name="findbugs" depends="-def-findbugs,build-all-tools">
-        <property name="findbugs.reportLevel" value="medium"/>
-        <mkdir dir="${dist.findbugs.dir}"/>
-        <findbugs
-            home="${findbugs.home}"
-            projectName="JDK langtools ${full.version}"
-            output="xml"
-            outputFile="${dist.findbugs.dir}/findbugs.xml"
-            reportLevel="${findbugs.reportLevel}"
-            failOnError="false"
-            errorProperty="findbugs.all.errors"
-            warningsProperty="findbugs.all.warnings"
-            jvm="${target.java.home}/bin/java"
-            jvmargs="-Xmx512M">
-            <class location="${build.dir}/java.compiler/classes"/>
-            <class location="${build.dir}/jdk.compiler/classes"/>
-            <class location="${build.dir}/jdk.javadoc/classes"/>
-            <class location="${build.dir}/jdk.jdeps/classes"/>
-            <sourcePath>
-                <pathelement path="${langtools.sources}"/>
-            </sourcePath>
-        </findbugs>
-        <exec executable="sh">
-            <arg value="${findbugs.home}/bin/convertXmlToText"/>
-            <arg value="-longBugCodes"/>
-            <arg value="-html:${findbugs.home}/src/xsl/fancy.xsl"/>
-            <arg value="${dist.findbugs.dir}/findbugs.xml"/>
-            <redirector output="${dist.findbugs.dir}/findbugs.html"/>
-        </exec>
-    </target>
-
-    <target name="diags-examples" depends="build-all-tools">
-        <!-- can override the following on the command line if desired. -->
-        <property name="diags.examples.out" location="${build.dir}/diag-examples/diags-examples.html"/>
-        <mkdir dir="${build.dir}/diag-examples/classes"/>
-        <javac fork="true"
-            executable="${dist.bin.dir}/javac"
-            srcdir="test/tools/javac/diags"
-            destdir="${build.dir}/diag-examples/classes"
-            includes="ArgTypeCompilerFactory.java,Example.java,FileManager.java,HTMLWriter.java,RunExamples.java,DocCommentProcessor.java"
-            sourcepath=""
-            classpath="${langtools.classes}"
-            includeAntRuntime="no"
-            debug="${javac.debug}"
-            debuglevel="${javac.debuglevel}">
-            <compilerarg line="${javac.lint.opts}"/>
-        </javac>
-        <java fork="true"
-            jvm="${target.java.home}/bin/java"
-            dir="test/tools/javac/diags"
-            classpath="${build.dir}/diag-examples/classes;${langtools.classes}"
-            classname="RunExamples">
-            <jvmarg value="-Dtest.classes=${build.dir}/diag-examples/classes"/>
-            <arg value="-examples"/>
-            <arg value="examples"/>
-            <arg value="-o"/>
-            <arg file="${diags.examples.out}"/>
-            <arg value="-showFiles"/>
-            <arg value="-title"/>
-            <arg value="Examples of javac diagnostics"/>
-        </java>
-    </target>
-
-    <target name="doclint-api" depends="build-all-classes">
-        <delete dir="${build.dir}/doclint/classes"/>
-        <mkdir dir="${build.dir}/doclint/classes"/>
-        <javac fork="true"
-               executable="${boot.java.home}/bin/javac"
-               destdir="${build.dir}/doclint/classes"
-               includes="javax/lang/model/** com/sun/javadoc/** com/sun/source/**"
-               excludes=""
-               sourcepath=""
-               classpath="${langtools.classes}"
-               includeAntRuntime="no"
-               source="${javac.source}"
-               target="${javac.target}"
-               debug="${javac.debug}"
-               debuglevel="${javac.debuglevel}">
-            <compilerarg value="-implicit:none"/>
-            <compilerarg value="-Xprefer:source"/>
-            <compilerarg value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
-            <compilerarg line="${javac.extra.opts}"/>
-            <compilerarg line="-Xdoclint:all/protected,-missing"/>
-            <src>
-                <pathelement path="${langtools.sources}"/>
-                <pathelement path="${langtools.gensrc}"/>
-            </src>
-        </javac>
-    </target>
-
-    <!-- Generate API docs for "important" test classes that are used by
-         multiple tests.
-    -->
-    <target name="test-framework-docs" depends="build-all-classes">
-        <javadoc executable="${target.java.home}/bin/javadoc"
-                destdir="${build.dir}/testframeworkdocs">
-            <!-- disable doclint for now; it might be good to enable -Xdoclint:missing -->
-            <arg value="-Xdoclint:none"/>
-            <!-- source files to be documented -->
-            <sourcefiles>
-                <fileset dir="${test.dir}">
-                    <include name="**/ToolBox.java"/>
-                    <include name="**/*Tester.java"/>
-                    <include name="**/*TestBase.java"/>
-                    <include name="**/*Testing*.java"/>
-                </fileset>
-            </sourcefiles>
-            <!-- source path used for documentation -->
-            <sourcepath>
-                <pathelement path="${test.dir}/lib"/>
-                <pathelement path="${test.dir}/lib/combo"/>
-                <pathelement path="${test.dir}/tools/javac/lib"/>
-                <pathelement path="${test.dir}/tools/javac/classfiles/attributes/LocalVariableTable"/>
-            </sourcepath>
-            <!-- exclude the following "packages" found by <javadoc>
-                on the sourcepath -->
-            <excludepackage name="combo.tools.javac.combo"/>
-            <excludepackage name="tools.javac.combo"/>
-            <!-- library classes used for documentation -->
-            <classpath>
-                <pathelement path="${jtreg.home}/lib/testng.jar"/>
-            </classpath>
-            <!-- platform classes used for documentation -->
-            <bootclasspath>
-                <pathelement path="${langtools.classes}"/>
-                <pathelement path="${target.java.home}/jre/lib/rt.jar"/>
-            </bootclasspath>
-        </javadoc>
-    </target>
-
-    <target name="sanity"
-        description="display settings of configuration values">
-        <echo level="info">ant.home = ${ant.home}</echo>
-        <echo level="info">boot.java.home = ${boot.java.home}</echo>
-        <echo level="info">target.java.home = ${target.java.home}</echo>
-        <echo level="info">jtreg.home = ${jtreg.home}</echo>
-        <echo level="info">findbugs.home = ${findbugs.home}</echo>
-        <echo level="info">checkstyle.home = ${checkstyle.home}</echo>
-    </target>
-
-    <target name="diagnostics">
-        <diagnostics/>
-    </target>
-
-    <target name="jtreg-crules" depends="build-all-classes,-def-jtreg">
-        <mkdir dir="${build.crules.dir}/classes"/>
-        <javac fork="true"
-               source="${boot.javac.source}"
-               target="${boot.javac.target}"
-               executable="${boot.java.home}/bin/javac"
-               srcdir="${make.tools.dir}"
-               includes="crules/*"
-               destdir="${build.crules.dir}/classes"
-               includeantruntime="false">
-            <compilerarg value="-Xbootclasspath/p:${langtools.classes}"/>
-            <compilerarg line="${javac.lint.opts}"/>
-        </javac>
-        <copy todir="${build.crules.dir}/classes" includeemptydirs="false">
-            <fileset dir="${make.tools.dir}">
-                <include name="**/*.properties"/>
-            </fileset>
-        </copy>
-        <echo file="${build.crules.dir}/classes/META-INF/services/com.sun.source.util.Plugin">crules.CodingRulesAnalyzerPlugin</echo>
-        <jtreg-tool name="crules"
-                    tests="${crules.tests}"
-                    extra.jvmargs="-Xbootclasspath/a:${build.crules.dir}/classes" />
-    </target>
-
-    <!--
-    **** IDE support
-    -->
-
-    <target name="idea">
-        <mkdir dir=".idea"/>
-        <copy todir=".idea" >
-            <fileset dir="make/intellij" excludes="**/src/**"/>
-        </copy>
-        <condition property="idea.jtreg.home" value="${jtreg.home}" else = "[jtreg.home]">
-            <isset property="jtreg.home"/>
-        </condition>
-        <condition property="idea.target.jdk" value="${target.java.home}" else = "$JDKPath$">
-            <isset property="target.java.home"/>
-        </condition>
-        <replace file=".idea/ant.xml" token="@IDEA_JTREG_HOME@" value="${idea.jtreg.home}"/>
-        <replace file=".idea/ant.xml" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
-        <replace file=".idea/workspace.xml" token="@FILE_SEP@" value="${file.separator}"/>
-        <replace file=".idea/workspace.xml" token="@PATH_SEP@" value="${path.separator}"/>
-        <mkdir dir=".idea/classes"/>
-        <javac srcdir="make/intellij/src"
-               destdir=".idea/classes"/>
-    </target>
-
-    <!--
-    **** Check targets.
-    **** "-check-*" targets check that a required property is set, and set to a reasonable value.
-    **** A user friendly message is generated if not, and the build exits.
-    -->
-
-    <target name="-check-boot.java.home" depends="-def-check">
-        <check name="bootstrap java" property="boot.java.home" marker="${java.marker}"/>
-    </target>
-
-    <target name="-check-target.java.home" depends="-def-check">
-        <check name="target java" property="target.java.home" marker="${java.marker}"/>
-    </target>
-
-    <target name="-check-jtreg.home" depends="-def-check">
-        <check name="jtreg" property="jtreg.home" marker="lib/jtreg.jar"/>
-    </target>
-
-    <target name="-check-findbugs.home" depends="-def-check">
-        <check name="findbugs" property="findbugs.home" marker="lib/findbugs.jar"/>
-    </target>
-
-    <target name="-check-checkstyle.home" depends="-def-check">
-        <check name="checkstyle" property="checkstyle.home" marker=""/> <!--TODO: better checkstyle verification-->
-    </target>
-
-    <!-- Definitions -->
-
-    <target name="-def-build-all-module-jars" depends="-def-build-module-jar">
-        <macrodef name="build-all-module-jars">
-            <attribute name="compilation.kind" default=""/>
-            <sequential>
-                <build-module-jar module.name="java.compiler" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.compiler" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.javadoc" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.jdeps" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.internal.le" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.jdi" compilation.kind="@{compilation.kind}" />
-                <build-module-jar module.name="jdk.jshell" compilation.kind="@{compilation.kind}" />
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-build-module-jar">
-        <macrodef name="build-module-jar">
-            <attribute name="module.name"/>
-            <attribute name="compilation.kind"/>
-            <attribute name="dependencies" default="${@{compilation.kind}@{module.name}.dependencies}"/>
-            <attribute name="build.dir" default="${@{compilation.kind}build.dir}"/>
-            <attribute name="lib.dir" default="${@{compilation.kind}dist.lib.dir}"/>
-            <attribute name="classes.dir" default="@{build.dir}/@{module.name}/classes"/>
-            <sequential>
-                <mkdir dir="@{lib.dir}"/>
-                <local name="jarclasspath" />
-                <pathconvert property="jarclasspath">
-                    <path>
-                        <pathelement path="@{dependencies}" />
-                    </path>
-                    <map from="${basedir}/" to="" />
-                    <mapper type="glob" from="*" to="*.jar"/>
-                </pathconvert>
-                <jar destfile="@{lib.dir}/@{module.name}.jar"
-                     basedir="@{classes.dir}">
-                    <manifest>
-                        <attribute name="Class-Path" value="@{jarclasspath}"/>
-                    </manifest>
-                </jar>
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-build-tool">
-        <macrodef name="build-tool">
-            <attribute name="name"/>
-            <attribute name="compilation.kind" default=""/>
-            <attribute name="bin.dir" default="${@{compilation.kind}dist.bin.dir}"/>
-            <attribute name="java" default="${launcher.java}"/>
-            <attribute name="main.class" default="${tool.@{name}.main.class}"/>
-            <sequential>
-                <mkdir dir="@{bin.dir}"/>
-                <copy file="${make.dir}/launcher.sh-template" tofile="@{bin.dir}/@{name}">
-                    <filterset begintoken="#" endtoken="#">
-                        <filter token="PROGRAM" value="@{main.class}"/>
-                        <filter token="TARGET_JAVA" value="@{java}"/>
-                        <filter token="PS" value="${path.separator}"/>
-                    </filterset>
-                </copy>
-                <chmod file="@{bin.dir}/@{name}" perm="ugo+rx"/>
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-build-all-module-classes" depends="-def-build-module-classes">
-        <macrodef name="build-all-module-classes">
-            <attribute name="compilation.kind" default=""/>
-            <sequential>
-                <build-module-classes module.name="java.compiler"
-                                      compilation.kind="@{compilation.kind}" />
-                <build-module-classes module.name="jdk.compiler"
-                                      compilation.kind="@{compilation.kind}"
-                                      resource.includes="${javac.resource.includes}" />
-                <build-module-classes module.name="jdk.javadoc"
-                                      compilation.kind="@{compilation.kind}" />
-                <build-module-classes module.name="jdk.jdeps"
-                                      compilation.kind="@{compilation.kind}" />
-                <copy-module-classes  module.name="jdk.internal.le"
-                                      compilation.kind="@{compilation.kind}" />
-                <copy-module-classes  module.name="jdk.jdi"
-                                      compilation.kind="@{compilation.kind}" />
-                <build-module-classes module.name="jdk.jshell"
-                                      compilation.kind="@{compilation.kind}" />
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-build-module-classes" depends="-def-pcompile,-def-pparse,-def-cdumper">
-        <macrodef name="build-module-classes">
-            <attribute name="module.name"/>
-            <attribute name="compilation.kind" default=""/>
-            <attribute name="resource.includes" default="nonExistent" />
-            <attribute name="dependencies" default="${@{module.name}.dependencies}"/>
-            <attribute name="includes" default="${@{compilation.kind}javac.includes}"/>
-            <attribute name="javac.lint.opts" default="${@{compilation.kind}javac.lint.opts}"/>
-            <attribute name="javac.extra.opts" default="${@{compilation.kind}javac.extra.opts}"/>
-            <attribute name="build.dir" default="${@{compilation.kind}build.dir}"/>
-            <attribute name="excludes" default="${exclude.files} **/package-info.java"/>
-            <attribute name="classes.dir" default="@{build.dir}/@{module.name}/classes"/>
-            <attribute name="gensrc.dir" default="@{build.dir}/@{module.name}/gensrc"/>
-            <attribute name="depcache.dir" default="@{build.dir}/@{module.name}/depcache"/>
-            <attribute name="java.home" default="${boot.java.home}"/>
-            <attribute name="source" default="${@{compilation.kind}javac.source}"/>
-            <attribute name="target" default="${@{compilation.kind}javac.target}"/>
-            <attribute name="release" default="${release}"/>
-            <attribute name="full.version" default="${full.version}"/>
-            <attribute name="plugin.options" default=""/>
-            <sequential>
-                <echo level="verbose" message="build-classes: excludes=@{excludes}"/>
-                <echo level="verbose" message="build-classes: classpath=@{classpath}"/>
-                <echo level="verbose" message="build-classes: sourcepath=@{sourcepath}"/>
-                <echo level="verbose" message="build-classes: dependencies=@{dependencies}"/>
-                <local name="src.dir" />
-                <property name="src.dir" location="${basedir}/src/@{module.name}/share/classes"/>
-                <local name="classpath" />
-                <pathconvert property="classpath">
-                    <path>
-                        <pathelement path="@{dependencies}" />
-                    </path>
-                    <map from="${basedir}/" to="@{build.dir}/" />
-                    <mapper type="glob" from="*" to="*/classes"/>
-                </pathconvert>
-                <local name="bootclasspath.prepend"/>
-                <condition property="bootclasspath.prepend" value="" else="${langtools.boot.classes}">
-                    <equals arg1="@{compilation.kind}" arg2="boot."/>
-                </condition>
-                <mkdir dir="@{classes.dir}"/>
-                <mkdir dir="@{gensrc.dir}"/>
-                <mkdir dir="@{depcache.dir}"/>
-                <pcompile destdir="@{gensrc.dir}"
-                          includes="@{includes}">
-                    <src>
-                        <path location="${src.dir}"/>
-                    </src>
-                </pcompile>
-                <pparse destdir="@{gensrc.dir}"
-                        includes="@{resource.includes}">
-                    <src>
-                        <path location="${src.dir}"/>
-                    </src>
-                </pparse>
-                <copy todir="@{gensrc.dir}">
-                    <fileset dir="${src.dir}" includes="@{includes}" />
-                    <globmapper from="*.properties-template" to="*.properties"/>
-                    <filterset begintoken="$(" endtoken=")">
-                        <filter token="JDK_VERSION" value="${jdk.version}"/>
-                        <filter token="RELEASE" value="@{release}"/>
-                        <filter token="FULL_VERSION" value="@{full.version}"/>
-                    </filterset>
-                </copy>
-                <pcompile destdir="@{gensrc.dir}"
-                          includes="**/*.properties">
-                    <src>
-                        <pathelement location="@{gensrc.dir}"/>
-                    </src>
-                </pcompile>
-                <antcall target="-do-depend">
-                    <param name="src.dir" value="${src.dir}" />
-                    <param name="classes.dir" value="@{classes.dir}" />
-                    <param name="gensrc.dir" value="@{gensrc.dir}" />
-                    <param name="depcache.dir" value="@{depcache.dir}" />
-                    <param name="classpath" value="${classpath}" />
-                </antcall>
-                <javac fork="true"
-                       executable="@{java.home}/bin/javac"
-                       destdir="@{classes.dir}"
-                       includes="@{includes}"
-                       excludes="@{excludes}"
-                       sourcepath="${src.dir}:@{gensrc.dir}"
-                       classpath="${classpath}"
-                       includeAntRuntime="no"
-                       source="@{source}"
-                       target="@{target}"
-                       debug="${javac.debug}"
-                       debuglevel="${javac.debuglevel}">
-                    <compilerarg value="-implicit:none"/>
-                    <compilerarg value="-Xprefer:source"/>
-                    <compilerarg value="-J-Xbootclasspath/p:${bootclasspath.prepend}"/>
-                    <compilerarg value="-Xbootclasspath/p:${classpath}"/>
-                    <compilerarg line="@{javac.extra.opts}"/>
-                    <compilerarg line="@{javac.lint.opts}"/>
-                    <compilerarg line="@{plugin.options}"/>
-                    <src>
-                        <path location="${src.dir}"/>
-                        <path location="@{gensrc.dir}"/>
-                    </src>
-                </javac>
-                <copy todir="@{classes.dir}" includeemptydirs="false">
-                    <fileset dir="${src.dir}" includes="@{includes}" excludes="@{excludes}">
-                        <exclude name="**/*.java"/>
-                        <exclude name="**/*.properties"/>
-                        <exclude name="**/*-template"/>
-                        <exclude name="**/*.rej"/>
-                        <exclude name="**/*.orig"/>
-                        <exclude name="**/overview.html"/>
-                        <exclude name="**/package.html"/>
-                    </fileset>
-                </copy>
-            </sequential>
-        </macrodef>
-        <macrodef name="copy-module-classes">
-            <attribute name="module.name"/>
-            <attribute name="compilation.kind" default=""/>
-            <attribute name="build.dir" default="${@{compilation.kind}build.dir}"/>
-            <attribute name="classes.dir" default="@{build.dir}/@{module.name}/classes"/>
-            <attribute name="java.home" default="${boot.java.home}"/>
-            <sequential>
-                <property name="classes.origin.dir" location="${target.java.home}/../../jdk/modules/@{module.name}"/>
-                <mkdir dir="@{classes.dir}"/>
-                <dumpclasses moduleName="@{module.name}" destDir="@{classes.dir}" />
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-pparse">
-        <mkdir dir="${build.toolclasses.dir}"/>
-        <copy todir="${build.toolclasses.dir}/propertiesparser" >
-            <fileset dir="make/tools/propertiesparser" includes="**/resources/**"/>
-        </copy>
-        <javac fork="true"
-               source="${boot.javac.source}"
-               target="${boot.javac.target}"
-               executable="${boot.java.home}/bin/javac"
-               srcdir="${make.tools.dir}"
-               includes="propertiesparser/* anttasks/PropertiesParser* anttasks/PathFileSet*"
-               destdir="${build.toolclasses.dir}/"
-               classpath="${ant.core.lib}"
-               bootclasspath="${boot.java.home}/jre/lib/rt.jar"
-               includeantruntime="false">
-            <compilerarg line="${javac.lint.opts}"/>
-        </javac>
-        <taskdef name="pparse"
-                 classname="anttasks.PropertiesParserTask"
-                 classpath="${build.toolclasses.dir}/"/>
-    </target>
-
-    <target name="-def-cdumper">
-        <mkdir dir="${build.toolclasses.dir}"/>
-        <javac fork="true"
-               source="${boot.javac.source}"
-               target="${boot.javac.target}"
-               executable="${boot.java.home}/bin/javac"
-               srcdir="${make.tools.dir}"
-               includes="anttasks/DumpClass*"
-               destdir="${build.toolclasses.dir}/"
-               classpath="${ant.core.lib}"
-               bootclasspath="${boot.java.home}/jre/lib/rt.jar"
-               includeantruntime="false">
-            <compilerarg line="${javac.lint.opts}"/>
-        </javac>
-        <taskdef name="dumpclasses"
-                 classname="anttasks.DumpClassesTask"
-                 classpath="${build.toolclasses.dir}/:${target.java.home}/jrt-fs.jar"/>
-    </target>
-
-    <target name="-do-depend" if="do.depend">
-        <depend srcdir="${src.dir}:${gensrc.dir}" destdir="${classes.dir}" classpath="${classpath}"
-                cache="${depcache.dir}"/>
-    </target>
-
-    <target name="-def-pcompile">
-        <mkdir dir="${build.toolclasses.dir}"/>
-        <javac fork="true"
-               source="${boot.javac.source}"
-               target="${boot.javac.target}"
-               executable="${boot.java.home}/bin/javac"
-               srcdir="${make.tools.dir}"
-               includes="compileproperties/* anttasks/CompileProperties* anttasks/PathFileSet*"
-               destdir="${build.toolclasses.dir}/"
-               classpath="${ant.core.lib}"
-               bootclasspath="${boot.java.home}/jre/lib/rt.jar"
-               includeantruntime="false">
-            <compilerarg line="${javac.lint.opts}"/>
-        </javac>
-        <taskdef name="pcompile"
-                 classname="anttasks.CompilePropertiesTask"
-                 classpath="${build.toolclasses.dir}/"/>
-    </target>
-
-    <target name="-def-javadoc-tool" depends="-check-target.java.home">
-        <macrodef name="javadoc-tool">
-            <attribute name="includes" default="${javac.includes}"/>
-            <attribute name="options" default=""/>
-            <attribute name="source" default="${javac.source}"/>
-            <sequential>
-                <property name="javadoc.options" value=""/> <!-- default, can be overridden per user or per project -->
-                <!-- Note: even with this default value, includes
-                from source directories get javadoc'd; see packageset below -->
-                <property name="javadoc.packagenames" value="none"/> <!-- default, can be overridden per user or per project -->
-                <javadoc
-                    executable="${target.java.home}/bin/javadoc"
-                    destdir="${build.javadoc.dir}"
-                    source="@{source}"
-                    windowtitle="UNOFFICIAL"
-                    failonerror="true"
-                    use="true"
-                    author="false"
-                    version="false"
-                    packagenames="${javadoc.packagenames}" >
-                    <header><![CDATA[<strong>Unofficial Javadoc</strong> generated from developer sources for preview purposes only]]></header>
-                    <arg line="@{options}"/>
-                    <bootclasspath>
-                        <pathelement path="${langtools.classes}"/>
-                        <path location="${target.java.home}/jre/lib/rt.jar"/>
-                    </bootclasspath>
-                    <sourcepath>
-                        <pathelement path="${langtools.sources}"/>
-                    </sourcepath>
-                    <!-- XXX just <fileset> (restricted further to **/*.java) and no <packageset> -->
-                    <!-- means that {@link some.package} will not work, which is no good. -->
-                    <!-- (It correctly skips excluded single classes, but not if packageset is also included, -->
-                    <!-- which also causes duplicates in the class index for included files.) -->
-                    <packageset dir="${basedir}/src/java.compiler/share/classes" includes="@{includes}">
-                        <or>
-                            <filename name="javax/"/>
-                        </or>
-                    </packageset>
-                    <packageset dir="${basedir}/src/jdk.compiler/share/classes" includes="@{includes}">
-                        <or>
-                            <filename name="com/sun/source/"/>
-                        </or>
-                    </packageset>
-                    <packageset dir="${basedir}/src/jdk.javadoc/share/classes" includes="@{includes}">
-                        <or>
-                            <filename name="com/sun/javadoc/"/>
-                        </or>
-                    </packageset>
-                </javadoc>
-            </sequential>
-        </macrodef>
-    </target>
-
-    <target name="-def-jtreg" unless="jtreg.defined" depends="-check-jtreg.home,-check-target.java.home">
-        <taskdef name="jtreg" classname="com.sun.javatest.regtest.Main$$Ant">
-            <classpath>
-                <pathelement location="${jtreg.home}/lib/jtreg.jar"/>
-                <pathelement location="${jtreg.home}/lib/javatest.jar"/>
-            </classpath>
-        </taskdef>
-        <macrodef name="jtreg-tool">
-            <attribute name="name"/>
-            <attribute name="tests"/>
-            <attribute name="langtools.classes" default="${langtools.classes}"/>
-            <attribute name="jdk" default="${target.java.home}"/>
-            <attribute name="samevm" default="true"/>
-            <attribute name="verbose" default="${default.jtreg.verbose}"/>
-            <attribute name="options" default="${other.jtreg.options}"/>
-            <attribute name="keywords" default="-keywords:!ignore"/>
-            <attribute name="jpda.jvmargs" default=""/>
-            <attribute name="extra.jvmargs" default=""/>
-            <attribute name="build.dir" default="${build.dir}"/>
-            <sequential>
-                <property name="coverage.options" value=""/>              <!-- default -->
-                <property name="coverage.classpath" value=""/>            <!-- default -->
-                <property name="default.jtreg.verbose" value="summary"/>  <!-- default -->
-                <property name="other.jtreg.options" value=""/>           <!-- default -->
-                <jtreg
-                    dir="${test.dir}"
-                    workDir="${build.jtreg.dir}/@{name}/work"
-                    reportDir="${build.jtreg.dir}/@{name}/report"
-                    jdk="@{jdk}"
-                    samevm="@{samevm}" verbose="@{verbose}"
-                    failonerror="false" resultproperty="jtreg.@{name}.result"
-                    javacoptions="-g"
-                    vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}@{langtools.classes} @{jpda.jvmargs} @{extra.jvmargs}">
-                    <arg line="@{keywords}"/>
-                    <arg line="@{options}"/>
-                    <arg line="@{tests}"/>
-                </jtreg>
-                <!-- the next two properties are for convenience, when only
-                     a single instance of jtreg will be invoked. -->
-                <condition property="jtreg.passed">
-                    <equals arg1="${jtreg.@{name}.result}" arg2="0"/>
-                </condition>
-                <property name="jtreg.report" value="${build.jtreg.dir}/@{name}/report"/>
-            </sequential>
-        </macrodef>
-        <property name="jtreg.defined" value="true"/>
-    </target>
-
-    <target name="-def-checkstyle" unless="checkstyle.defined" depends="-check-checkstyle.home">
-        <taskdef resource="checkstyletask.properties">
-            <classpath>
-              <fileset dir="${checkstyle.home}">
-                <include name="checkstyle-*-all.jar"/>
-              </fileset>
-            </classpath>
-        </taskdef>
-        <property name="checkstyle.defined" value="true"/>
-    </target>
-
-    <target name="-def-findbugs" unless="findbugs.defined"
-        depends="-check-findbugs.home,-check-target.java.home">
-        <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
-            <classpath>
-                <pathelement location="${findbugs.home}/lib/findbugs.jar"/>
-            </classpath>
-        </taskdef>
-        <macrodef name="findbugs-tool">
-            <attribute name="name"/>
-            <attribute name="output" default="emacs"/>
-            <attribute name="outputFile" default=""/>
-            <attribute name="reportLevel" default="high"/>
-            <sequential>
-                <findbugs
-                    home="${findbugs.home}"
-                    output="@{output}"
-                    outputFile="@{outputFile}"
-                    reportLevel="@{reportLevel}"
-                    failOnError="false"
-                    errorProperty="findbugs.@{name}.errors"
-                    warningsProperty="findbugs.@{name}.warnings"
-                    jvm="${target.java.home}/bin/java"
-                    jvmargs="-Xmx512M" >
-                    <class location="${dist.dir}/lib/@{name}.jar"/>
-                    <auxClasspath>
-                        <pathelement location="${langtools.classes}"/>
-                    </auxClasspath>
-                    <sourcePath>
-                        <path refid="src.dirs"/>
-                    </sourcePath>
-                </findbugs>
-            </sequential>
-        </macrodef>
-        <property name="findbugs.defined" value="true"/>
-    </target>
-
     <target name="-def-check">
-        <macrodef name="check">
-            <attribute name="name"/>
-            <attribute name="property"/>
-            <attribute name="marker" default=""/>
+      <macrodef name="check">
+          <attribute name="name"/>
+          <attribute name="property"/>
+          <attribute name="marker" default=""/>
             <sequential>
                 <fail message="Cannot locate @{name}: please set @{property} to its location">
                     <condition>
@@ -917,5 +143,207 @@
         </macrodef>
     </target>
 
-</project>
+    <target name="-check-langtools.jdk.home" depends="-def-check">
+        <check name="target java" property="langtools.jdk.home" marker="${java.marker}"/>
+    </target>
 
+    <target name="-check-jtreg.home" depends="-def-check">
+        <check name="jtreg" property="jtreg.home" marker="lib/jtreg.jar"/>
+    </target>
+
+    <!--
+        **** Primary targets
+    -->
+
+    <target name="clean" description="Delete all generated files">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="build" depends="build-all-tools"/>
+
+    <target name="-prepare-build" depends="-check-langtools.jdk.home">
+        <mkdir dir="${build.modules}"/>
+        <mkdir dir="${build.tools}"/>
+        <mkdir dir="${build.gensrc}"/>
+        <mkdir dir="${build.bin}"/>
+        <mkdir dir="${build.prevsrc}"/>
+    </target>
+
+    <target name="generate-sources-internal">
+        <basename property="module.name" file="${basedir}"/>
+        <pparse destdir="${build.gensrc}/${module.name}" includes="${langtools.resource.includes}">
+            <src path="./share/classes"/>
+        </pparse>
+        <pcompile destdir="${build.gensrc}/${module.name}" includes="**/*.properties">
+            <src path="./share/classes"/>
+        </pcompile>
+    </target>
+
+    <target name="generate-sources"  depends="-prepare-build,-def-pparse,-def-pcompile">
+        <subant inheritall="true" target="generate-sources-internal" genericantfile="${make.dir}/build.xml">
+              <dirset dir="${src.dir}" includes="*.*"/>
+        </subant>
+    </target>
+
+    <target name="build-all-classes" depends="generate-sources">
+        <exec executable="${langtools.jdk.home}/bin/javac" failonerror="true">
+            <arg line="-source ${javac.source} -target ${javac.target}" />
+            <arg value="-d" />
+            <arg value="${build.modules}" />
+            <arg line="${javac.opts} -modulesourcepath ${src.dir}${file.separator}*${file.separator}share${file.separator}classes:${build.gensrc} -m java.compiler,jdk.compiler,jdk.javadoc,jdk.jdeps,jdk.jshell" />
+        </exec>
+        <delete>
+            <fileset dir="${build.modules}" includes="**/module-info.class"/>
+        </delete>
+    </target>
+
+    <target name="build-all-tools" depends="build-all-classes, -def-build-tool">
+        <build-tool name="javac"/>
+        <build-tool name="javadoc"/>
+        <build-tool name="javap"/>
+        <build-tool name="javah"/>
+        <build-tool name="jdeps"/>
+        <build-tool name="sjavac"/>
+        <build-tool name="jshell"/>
+    </target>
+
+    <target name="jtreg" depends="build-all-tools,-def-jtreg">
+        <jtreg-tool name="all" tests="${jtreg.tests}"/>
+    </target>
+
+    <!--
+    **** IDE support
+    -->
+
+    <target name="idea" depends="-check-langtools.jdk.home">
+        <mkdir dir=".idea"/>
+        <copy todir=".idea" >
+            <fileset dir="make/intellij" excludes="**/src/**"/>
+        </copy>
+        <condition property="idea.jtreg.home" value="${jtreg.home}" else = "[jtreg.home]">
+            <isset property="jtreg.home"/>
+        </condition>
+        <condition property="idea.target.jdk" value="${langtools.jdk.home}" else = "$JDKPath$">
+            <isset property="langtools.jdk.home"/>
+        </condition>
+        <replace file=".idea/ant.xml" token="@IDEA_JTREG_HOME@" value="${idea.jtreg.home}"/>
+        <replace file=".idea/ant.xml" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
+        <replace file=".idea/workspace.xml" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
+        <replace file=".idea/workspace.xml" token="@FILE_SEP@" value="${file.separator}"/>
+        <replace file=".idea/workspace.xml" token="@PATH_SEP@" value="${path.separator}"/>
+        <mkdir dir=".idea/classes"/>
+        <javac srcdir="make/intellij/src"
+               destdir=".idea/classes"/>
+    </target>
+
+    <!--
+        **** Utility definitions
+    -->
+
+    <target name="-def-pparse">
+        <copy todir="${build.tools}/propertiesparser" >
+            <fileset dir="${make.tools.dir}/propertiesparser" includes="**/resources/**"/>
+        </copy>
+        <javac fork="true"
+               source="${javac.source}"
+               target="${javac.target}"
+               executable="${langtools.jdk.home}/bin/javac"
+               srcdir="${make.tools.dir}"
+               includes="propertiesparser/* anttasks/PropertiesParser* anttasks/PathFileSet*"
+               destdir="${build.tools}"
+               classpath="${ant.core.lib}"
+               bootclasspath="${langtools.jdk.home}/jre/lib/rt.jar"
+               includeantruntime="false">
+            <compilerarg line="${javac.opts} -XDstringConcat=inline"/>
+        </javac>
+        <taskdef name="pparse"
+                 classname="anttasks.PropertiesParserTask"
+                 classpath="${build.tools}"/>
+    </target>
+
+     <target name="-def-pcompile">
+        <javac fork="true"
+               source="${javac.source}"
+               target="${javac.target}"
+               executable="${langtools.jdk.home}/bin/javac"
+               srcdir="${make.tools.dir}"
+               includes="compileproperties/* anttasks/CompileProperties* anttasks/PathFileSet*"
+               destdir="${build.dir}/toolclasses/"
+               classpath="${ant.core.lib}"
+               includeantruntime="false">
+            <compilerarg line="${javac.opts} -XDstringConcat=inline"/>
+        </javac>
+        <taskdef name="pcompile"
+                 classname="anttasks.CompilePropertiesTask"
+                 classpath="${build.tools}"/>
+    </target>
+
+    <target name="-def-build-tool">
+        <macrodef name="build-tool">
+            <attribute name="name"/>
+            <attribute name="compilation.kind" default=""/>
+            <attribute name="bin.dir" default="${build.bin}"/>
+            <attribute name="java" default="${launcher.java}"/>
+            <attribute name="main.class" default="${tool.@{name}.main.class}"/>
+            <sequential>
+                <mkdir dir="@{bin.dir}"/>
+                <copy file="${make.dir}/launcher.sh-template" tofile="@{bin.dir}/@{name}">
+                    <filterset begintoken="#" endtoken="#">
+                        <filter token="PROGRAM" value="@{main.class}"/>
+                        <filter token="TARGET_JAVA" value="@{java}"/>
+                        <filter token="PS" value="${path.separator}"/>
+                    </filterset>
+                </copy>
+                <chmod file="@{bin.dir}/@{name}" perm="ugo+rx"/>
+            </sequential>
+        </macrodef>
+    </target>
+
+    <target name="-def-jtreg" unless="jtreg.defined" depends="-check-jtreg.home,-check-langtools.jdk.home">
+        <taskdef name="jtreg" classname="com.sun.javatest.regtest.Main$$Ant">
+            <classpath>
+                <pathelement location="${jtreg.home}/lib/jtreg.jar"/>
+                <pathelement location="${jtreg.home}/lib/javatest.jar"/>
+            </classpath>
+        </taskdef>
+        <macrodef name="jtreg-tool">
+            <attribute name="name"/>
+            <attribute name="tests"/>
+            <attribute name="jdk" default="${langtools.jdk.home}"/>
+            <attribute name="agentvm" default="true"/>
+            <attribute name="verbose" default="${default.jtreg.verbose}"/>
+            <attribute name="options" default="${other.jtreg.options}"/>
+            <attribute name="keywords" default="-keywords:!ignore"/>
+            <attribute name="jpda.jvmargs" default=""/>
+            <attribute name="extra.jvmargs" default=""/>
+            <attribute name="build.modules" default="${build.modules}"/>
+            <sequential>
+                <property name="coverage.options" value=""/>              <!-- default -->
+                <property name="coverage.classpath" value=""/>            <!-- default -->
+                <property name="default.jtreg.verbose" value="summary"/>  <!-- default -->
+                <property name="other.jtreg.options" value=""/>           <!-- default -->
+                <property name="jtreg.classfiles.to.modules" value="@{agentvm}"/>
+                <jtreg
+                    dir="${test.dir}"
+                    workDir="${build.jtreg}/@{name}/work"
+                    reportDir="${build.jtreg}/@{name}/report"
+                    jdk="@{jdk}"
+                    agentvm="@{agentvm}" verbose="@{verbose}"
+                    failonerror="false" resultproperty="jtreg.@{name}.result"
+                    vmoptions="${coverage.options} @{extra.jvmargs} -Xpatch:@{build.modules}">
+                    <arg value="-debug:@{jpda.jvmargs}"/>
+                    <arg line="@{keywords}"/>
+                    <arg line="@{options}"/>
+                    <arg line="@{tests}"/>
+                </jtreg>
+                <!-- the next two properties are for convenience, when only
+                     a single instance of jtreg will be invoked. -->
+                <condition property="jtreg.passed">
+                    <equals arg1="${jtreg.@{name}.result}" arg2="0"/>
+                </condition>
+                <property name="jtreg.report" value="${build.jtreg}/@{name}/report"/>
+            </sequential>
+        </macrodef>
+        <property name="jtreg.defined" value="true"/>
+    </target>
+</project>
diff --git a/langtools/make/gendata/Gendata-jdk.compiler.gmk b/langtools/make/gendata/Gendata-jdk.compiler.gmk
index 2e89ce7..613e713 100644
--- a/langtools/make/gendata/Gendata-jdk.compiler.gmk
+++ b/langtools/make/gendata/Gendata-jdk.compiler.gmk
@@ -39,6 +39,10 @@
     BIN := $(BUILDTOOLS_OUTPUTDIR)/create_symbols, \
 ))
 
+ifeq ($(BOOT_JDK_MODULAR), true)
+  COMPILECREATESYMBOLS_ADD_EXPORTS := -XaddExports:jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED,jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED,jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
+endif
+
 $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files/_the.symbols: \
     $(COMPILE_CREATE_SYMBOLS) \
     $(wildcard $(LANGTOOLS_TOPDIR)/make/data/symbols/*)
@@ -46,6 +50,7 @@
 	$(MKDIR) -p $(@D)
 	$(ECHO) Creating ct.sym classes
 	$(JAVA) $(INTERIM_LANGTOOLS_ARGS) \
+	    $(COMPILECREATESYMBOLS_ADD_EXPORTS) \
 	    -classpath $(BUILDTOOLS_OUTPUTDIR)/create_symbols \
 	    build.tools.symbolgenerator.CreateSymbols \
 	    build-ctsym \
diff --git a/langtools/make/intellij/ant.xml b/langtools/make/intellij/ant.xml
index a0570d2..e052d8b 100644
--- a/langtools/make/intellij/ant.xml
+++ b/langtools/make/intellij/ant.xml
@@ -3,16 +3,12 @@
   <component name="AntConfiguration">
     <buildFile url="file://$PROJECT_DIR$/.idea/build.xml">
       <properties>
-        <property name="boot.java.home" value="$JDKPath$" />
         <property name="jtreg.tests" value="$FilePath$" />
-        <property name="target.java.home" value="@IDEA_TARGET_JDK@" />
+        <property name="langtools.jdk.home" value="@IDEA_TARGET_JDK@" />
         <property name="jtreg.home" value="@IDEA_JTREG_HOME@" />
-        <property name="javac.debuglevel" value="source,lines,vars" />
-        <property name="jtreg.jpda.jvmargs" value="-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5900,suspend=y" />
+        <property name="jtreg.jpda.jvmargs" value="-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=5900" />
       </properties>
       <executeOn event="afterCompilation" target="post-make" />
     </buildFile>
   </component>
 </project>
-
-
diff --git a/langtools/make/intellij/build.xml b/langtools/make/intellij/build.xml
index 2be2b30..a6f1bd2 100644
--- a/langtools/make/intellij/build.xml
+++ b/langtools/make/intellij/build.xml
@@ -15,8 +15,7 @@
             <java classname="org.apache.tools.ant.Main" fork="true" spawn="true">
                 <arg value="-f"/>
                 <arg value="@{antfile}"/>
-                <arg value="-Dboot.java.home=${boot.java.home}"/>
-                <arg value="-Dtarget.java.home=${target.java.home}"/>
+                <arg value="-Dlangtools.jdk.home=${langtools.jdk.home}"/>
                 <arg value="-Djtreg.home=${jtreg.home}"/>
                 <arg value="-Djtreg.tests=${jtreg.tests}"/>
                 <arg value="-Djtreg.jpda.jvmargs=${jtreg.jpda.jvmargs}"/>
@@ -28,18 +27,13 @@
         </sequential>
     </macrodef>
 
-    <target name="crules" depends="build-all-tools,-def-jtreg">
-        <jtreg-tool name="all" tests="tools/all/RunCodingRules.java"/>
-    </target>
-
     <target name="post-make" depends="clean, build-all-tools"/>
 
-    <target name="jtreg-debug" depends="build-all-tools,-def-jtreg">
+    <target name="jtreg-debug" depends="build-all-tools, -def-jtreg">
         <exec-target target="jtreg-debug-internal"/>
     </target>
 
     <target name="jtreg-debug-internal" depends="-def-jtreg">
-        <jtreg-tool name="all" tests="${jtreg.tests}" jpda.jvmargs="${jtreg.jpda.jvmargs}"/>
+        <jtreg-tool name="all" tests="${jtreg.tests}" options="-conc:1" jpda.jvmargs="${jtreg.jpda.jvmargs}"/>
     </target>
 </project>
-
diff --git a/langtools/make/intellij/langtools.iml b/langtools/make/intellij/langtools.iml
index 582abf1..29ff589 100644
--- a/langtools/make/intellij/langtools.iml
+++ b/langtools/make/intellij/langtools.iml
@@ -8,12 +8,11 @@
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.compiler/share/classes" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.javadoc/share/classes" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.jdeps/share/classes" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/build/bootstrap/java.compiler/gensrc" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build/bootstrap/jdk.compiler/gensrc" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build/bootstrap/jdk.javadoc/gensrc" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/build/bootstrap/jdk.jdeps/gensrc" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.jshell/share/classes" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/gensrc/jdk.compiler" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build/gensrc/jdk.javadoc" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/build/gensrc/jdk.jdeps" isTestSource="false" />
     </content>
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="inheritedJdk" />
diff --git a/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java b/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java
index 759e5bf..ba4ce95 100644
--- a/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java
+++ b/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java
@@ -124,8 +124,8 @@
      * This enum is used to represent the list of tasks we need to keep track of during logging.
      */
     enum Task {
-        /** javac task - invoked during compilation */
-        JAVAC("javac", MessageKind.JAVAC_ERROR, MessageKind.JAVAC_WARNING, MessageKind.JAVAC_NOTE,
+        /** exec task - invoked during compilation */
+        JAVAC("exec", MessageKind.JAVAC_ERROR, MessageKind.JAVAC_WARNING, MessageKind.JAVAC_NOTE,
                        MessageKind.JAVAC_NESTED_DIAG, MessageKind.JAVAC_CRASH),
         /** jtreg task - invoked during test execution */
         JTREG("jtreg", MessageKind.JTREG_TEST_PASSED, MessageKind.JTREG_TEST_FAILED, MessageKind.JTREG_TEST_ERROR, MessageKind.JTREG_TEST_REPORT),
diff --git a/langtools/make/intellij/workspace.xml b/langtools/make/intellij/workspace.xml
index c2d0742..dc21405 100644
--- a/langtools/make/intellij/workspace.xml
+++ b/langtools/make/intellij/workspace.xml
@@ -7,14 +7,14 @@
     <option name="MAKE_PROJECT_ON_SAVE" value="true" />
   </component>
   <component name="RunManager" selected="Application.javac">
-    <!-- standard tools -->
+    <!-- javac -->
     <configuration default="false" name="javac" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -27,13 +27,14 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
+    <!-- javadoc -->
     <configuration default="false" name="javadoc" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="com.sun.tools.javadoc.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -46,13 +47,14 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
+    <!-- javap -->
     <configuration default="false" name="javap" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="com.sun.tools.javap.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -65,13 +67,14 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
+    <!-- javah -->
     <configuration default="false" name="javah" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="com.sun.tools.javah.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -84,13 +87,14 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
+    <!-- sjavac -->
     <configuration default="false" name="sjavac" type="Application" factoryName="Application">
       <option name="MAIN_CLASS_NAME" value="com.sun.tools.sjavac.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -103,13 +107,15 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
+    <!-- jshell -->
     <configuration default="false" name="jshell" type="Application" factoryName="Application">
       <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
       <option name="MAIN_CLASS_NAME" value="jdk.internal.jshell.tool.JShellTool" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/jdk.internal.le/classes:build/jdk.jdi/classes:build/jdk.jshell/classes:build/java.compiler/classes:build/jdk.compiler/classes:build/jdk.javadoc/classes:build/jdk.jdeps/classes" />
+      <option name="VM_PARAMETERS" value="-Xpatch:build@FILE_SEP@modules -XaddExports:jdk.jshell/jdk.internal.jshell.tool=ALL-UNNAMED" />
       <option name="PROGRAM_PARAMETERS" value="" />
       <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+      <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
       <option name="ENABLE_SWING_INSPECTOR" value="false" />
       <option name="ENV_VARIABLES" />
       <option name="PASS_PARENT_ENVS" value="true" />
@@ -120,24 +126,11 @@
         <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
       </method>
     </configuration>
-    <!-- bootstrap javac -->
-    <configuration default="false" name="javac (bootstrap)" type="Application" factoryName="Application">
-      <option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
-      <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build@FILE_SEP@bootstrap@FILE_SEP@java.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@bootstrap@FILE_SEP@jdk.compiler@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@bootstrap@FILE_SEP@jdk.javadoc@FILE_SEP@classes@PATH_SEP@build@FILE_SEP@bootstrap@FILE_SEP@jdk.jdeps@FILE_SEP@classes" />
-      <option name="PROGRAM_PARAMETERS" value="" />
-      <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
-      <option name="ENABLE_SWING_INSPECTOR" value="false" />
-      <option name="ENV_VARIABLES" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <module name="langtools" />
-      <envs />
-      <RunnerSettings RunnerId="Run" />
-      <ConfigurationWrapper RunnerId="Run" />
+    <!-- jtreg run -->
+    <configuration default="false" name="jtreg (run)" type="AntRunConfiguration" factoryName="Ant Target">
+      <antsettings antfile="file://$PROJECT_DIR$/.idea/build.xml" target="jtreg" />
       <method>
         <option name="Make" enabled="false" />
-        <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-bootstrap-javac" />
       </method>
     </configuration>
     <!-- jtreg debug -->
@@ -181,4 +174,3 @@
     </buildFile>
   </component>
 </project>
-
diff --git a/langtools/make/launcher.sh-template b/langtools/make/launcher.sh-template
index 9397525..728d6bc 100644
--- a/langtools/make/launcher.sh-template
+++ b/langtools/make/launcher.sh-template
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# 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
@@ -31,22 +31,10 @@
       mydir=`cygpath -m $mydir`
       ;;
 esac
-mylib="$mydir/../lib"
+mylib="$mydir/../modules"
 
-# By default, put the jar file and its dependencies on the bootclasspath.
-# This is always required on a Mac, because the system langtools classes
-# are always on the main class path; in addition, it may be required on
-# standard versions of JDK (i.e. using rt.jar and tools.jar) because some
-# langtools interfaces are in rt.jar.
-# Assume that the jar file being invoked lists all the necessary langtools
-# jar files in its Class-Path manifest entry, so there is no need to search
-# dependent jar files for additional dependencies.
-
-if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then
-   cp=`echo "$mylib"/*.jar |
-       sed -e 's|\([a-z.]*\.jar\) *|\1#PS#|g'`
-   bcp=$cp
-fi
+# patch langtools modules
+bcp=-Xpatch:"$mylib"
 
 # tools currently assumes that assertions are enabled in the launcher
 ea=-ea:com.sun.tools...
@@ -71,4 +59,4 @@
 unset DUALCASE
 
 IFS=$nl
-"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} #PROGRAM# ${toolOpts}
+"#TARGET_JAVA#" $bcp ${ea} ${javaOpts} #PROGRAM# ${toolOpts}
diff --git a/langtools/make/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml
index 0013b62..20de2fc 100644
--- a/langtools/make/netbeans/langtools/build.xml
+++ b/langtools/make/netbeans/langtools/build.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
@@ -48,20 +48,12 @@
 
     <!-- Build project. (action: build; F11) -->
 
-    <target name="build" depends="-get-tool-if-set,-build-bootstrap-javac,-build-all" />
-    <target name="-build-bootstrap-javac" if="langtools.tool.bootstrap">
-        <antcall target="build-bootstrap-javac"/>
-    </target>
-    <target name="-build-all" unless="langtools.tool.bootstrap">
-        <antcall target="build-all-tools"/>
-    </target>
-
     <!-- Compile a single file. (action: compile.single; F9) -->
 
-    <target name="compile-single" depends="-get-tool-if-set,build-bootstrap-javac-classes" unless="langtools.tool.bootstrap">
+    <target name="compile-single" depends="-get-tool-if-set,-check-langtools.jdk.home">
         <fail unless="includes">Must set property 'includes'</fail>
         <mkdir dir="${build.dir}/${module.name}/classes" />
-        <javac fork="true" executable="${boot.java.home}/bin/javac"
+        <javac fork="true" executable="${java.home}/bin/javac"
                srcdir="${basedir}/src/${module.name}/share/classes"
                destdir="${build.dir}/${module.name}/classes"
                includes="${includes}"
@@ -72,7 +64,6 @@
                target="${javac.target}"
                debug="${javac.debug}"
                debuglevel="${javac.debuglevel}">
-            <compilerarg value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
         </javac>
     </target>
 
@@ -81,12 +72,11 @@
         the user.
     -->
 
-    <target name="run" depends="-check-target.java.home,-build-classes,-def-run,-get-tool-and-args,-setup-bootclasspath,-def-resolve-main-class"
+    <target name="run" depends="-check-langtools.jdk.home,-build-classes,-def-run,-get-tool-and-args,-def-resolve-main-class"
             description="run tool">
-        <echo level="info" message="${with_bootclasspath}"/>
-        <echo level="info" message="Run ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
+        <echo level="info" message="Run ${langtools.tool.name} with args ${langtools.tool.args}"/>
         <resolve-main-class tool.name="${langtools.tool.name}" />
-        <run bcp="${with_bootclasspath}" mainclass="${langtools.main.class}" args="${langtools.tool.args}"/>
+        <run mainclass="${langtools.main.class}" args="${langtools.tool.args}"/>
     </target>
 
     <target name="-def-resolve-main-class">
@@ -102,17 +92,14 @@
         </macrodef>
     </target>
 
-    <target name="-build-classes" depends="-get-tool-if-set,-build-classes-bootstrap-javac,-build-classes-all" />
-    <target name="-build-classes-bootstrap-javac" if="langtools.tool.bootstrap">
-        <antcall target="build-bootstrap-javac-classes"/>
-    </target>
-    <target name="-build-classes-all" unless="langtools.tool.bootstrap">
+    <target name="-build-classes" depends="-get-tool-if-set,-build-classes-all" />
+    <target name="-build-classes-all">
         <antcall target="build-all-classes"/>
     </target>
 
     <!-- Run a selected class. (action: run.single;  shift-F6) -->
 
-    <target name="run-single" depends="-check-target.java.home,-setup-bootclasspath,-def-run">
+    <target name="run-single" depends="-check-langtools.jdk.home,-def-run">
         <fail unless="run.classname">Must set property 'run.classname' </fail>
         <echo level="info" message="run ${run.classname}"/>
         <run mainclass="${run.classname}" args=""/>
@@ -123,22 +110,12 @@
         test all tools.
     -->
 
-    <target name="jtreg" depends="-get-tool-if-set,-jtreg-bootstrap-javac,-jtreg-all"
-        description="Test langtools tools or bootstrap javac"
+    <target name="jtreg" depends="-get-tool-if-set,-jtreg-all"
+        description="Test langtools tools"
         />
 
-    <target name="-jtreg-bootstrap-javac" if="langtools.tool.bootstrap">
-        <echo level="info" message="Testing bootstrap javac"/>
-        <echo level="verbose" message="(Unset langtools.tool.bootstrap to test all tools)"/>
-        <antcall>
-            <target name="jtreg-bootstrap-javac"/>
-            <target name="-show-jtreg"/>
-        </antcall>
-    </target>
-
-    <target name="-jtreg-all" unless="langtools.tool.bootstrap">
+    <target name="-jtreg-all">
         <echo level="info" message="Testing all tools"/>
-        <echo level="verbose" message="(Set langtools.tool.bootstrap to test bootstrap javac)"/>
         <antcall>
             <target name="langtools.jtreg"/>
             <target name="-show-jtreg"/>
@@ -173,29 +150,27 @@
 
     <!-- Debug tool in NetBeans. -->
 
-    <target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,-setup-bootclasspath,-build-classes,-def-resolve-main-class" if="netbeans.home">
-        <echo level="info" message="Debug ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
+    <target name="debug" depends="-check-langtools.jdk.home,-def-run,-def-start-debugger,-get-tool-and-args,-build-classes,-def-resolve-main-class" if="netbeans.home">
+        <echo level="info" message="Debug ${langtools.tool.name} with args ${langtools.tool.args}"/>
         <start-debugger/>
         <resolve-main-class tool.name="${langtools.tool.name}" />
-        <run bcp="${with_bootclasspath}" mainclass="${langtools.main.class}" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
+        <run mainclass="${langtools.main.class}" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
     </target>
 
     <!-- Debug a selected class . -->
-    <target name="debug-single" depends="-check-target.java.home,-def-start-debugger,-def-run">
+    <target name="debug-single" depends="-check-langtools.jdk.home,-def-start-debugger,-def-run">
         <fail unless="debug.classname">Must set property 'debug.classname'</fail>
         <start-debugger/>
         <run mainclass="${debug.classname}" args="" jpda.jvmargs="${jpda.jvmargs}"/>
     </target>
 
     <!-- Debug a jtreg test. -->
-    <target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg,-get-tool-if-set,-setup-bootclasspath">
+    <target name="debug-jtreg" depends="-check-langtools.jdk.home,-def-start-debugger,-def-jtreg,-get-tool-if-set">
         <fail unless="jtreg.tests">Must set property 'jtreg.tests'</fail>
         <start-debugger/>
         <jtreg-tool name="debug"
-                    samevm="false"
                     tests="${jtreg.tests}"
-                    jpda.jvmargs="${jpda.jvmargs}"
-                    langtools.classes="${with_bootclasspath}"/>
+                    jpda.jvmargs="${jpda.jvmargs}"/>
     </target>
 
     <!-- Update a class being debugged. -->
@@ -206,11 +181,7 @@
         <antcall target="compile-single">
             <param name="includes" value="${class}.java"/>
         </antcall>
-        <condition property="build.classes.dir"
-                   value="${build.dir}/${module.name}/classes"
-                   else="${boot.build.dir}/${module.name}/classes">
-            <isset property="use_bootstrap"/>
-        </condition>
+        <property name="build.classes.dir" value="${build.dir}/${module.name}/classes" />
         <nbjpdareload>
             <fileset dir="${build.classes.dir}">
                 <include name="${class}.class"/>
@@ -218,23 +189,11 @@
         </nbjpdareload>
     </target>
 
-    <!-- Generate javadoc for one or all tools. (action: javadoc; Alt-F6)
-        If langtools.tool.name is set, then just test that tool; otherwise
-        test all tools.
-    -->
-
-    <target name="javadoc" depends="langtools.javadoc,-show-javadoc" />
-
-    <target name="-show-javadoc" if="netbeans.home">
-        <nbbrowse file="${build.javadoc.dir}/index.html"/>
-    </target>
-
     <!-- Prompt for values. -->
 
     <target name="-get-tool-if-set" depends="-def-select-tool">
         <select-tool
             toolproperty="langtools.tool.name"
-            bootstrapproperty="langtools.tool.bootstrap"
             propertyfile="${langtools.properties}"
             askIfUnset="false"
             />
@@ -244,32 +203,22 @@
         <select-tool
             toolproperty="langtools.tool.name"
             argsproperty="langtools.tool.args"
-            bootstrapproperty="langtools.tool.bootstrap"
             propertyfile="${langtools.properties}"
             askIfUnset="true"
             />
     </target>
 
-    <target name="-setup-bootclasspath">
-        <condition property="use_bootstrap" value="bootstrap-" else="">
-            <isset property="langtools.tool.bootstrap"/>
-        </condition>
-        <condition property="with_bootclasspath" value="${langtools.boot.classes}" else="${langtools.classes}">
-            <isset property="langtools.tool.bootstrap"/>
-        </condition>
-    </target>
-
     <!-- Macro to run a tool or selected class - used by run* and debug* tasks -->
     <target name="-def-run">
         <macrodef name="run">
             <attribute name="mainclass"/>
             <attribute name="args" default=""/>
-            <attribute name="bcp" default="${with_bootclasspath}"/>
+            <attribute name="build.modules" default="${build.modules}"/>
             <attribute name="jpda.jvmargs" default=""/>
 
             <sequential>
-                <java fork="true" jvm="${target.java.home}/bin/java" classname="@{mainclass}">
-                    <jvmarg line="-Xbootclasspath/p:@{bcp}"/>
+                <java fork="true" jvm="${langtools.jdk.home}/bin/java" classname="@{mainclass}">
+                    <jvmarg line="-Xpatch:@{build.modules}"/>
                     <jvmarg line="@{jpda.jvmargs}"/>
                     <arg line="@{args}"/>
                 </java>
@@ -285,11 +234,7 @@
                 <nbjpdastart name="${ant.project.name}" addressproperty="jpda.address" transport="dt_socket">
                     <bootclasspath>
                         <pathelement path="${langtools.classes}"/>
-                        <pathelement location="${target.java.home}/jre/lib/rt.jar"/>
                     </bootclasspath>
-                    <sourcepath>
-                        <pathelement path="${langtools.sources}"/>
-                    </sourcepath>
                 </nbjpdastart>
                 <property
                     name="@{jpda.jvmargs.property}"
@@ -300,6 +245,7 @@
     </target>
 
     <target name="-def-select-tool">
+        <property name="build.toolclasses.dir" location="${build.dir}/toolclasses"/>
         <mkdir dir="${build.toolclasses.dir}"/>
         <javac srcdir="${make.tools.dir}"
                includes="anttasks/SelectTool*"
diff --git a/langtools/make/netbeans/langtools/nbproject/project.xml b/langtools/make/netbeans/langtools/nbproject/project.xml
index 2a1fe35..aa5b4dd 100644
--- a/langtools/make/netbeans/langtools/nbproject/project.xml
+++ b/langtools/make/netbeans/langtools/nbproject/project.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
@@ -408,9 +408,6 @@
                         </arity>
                     </context>
                 </action>
-                <action name="javadoc">
-                    <target>javadoc</target>
-                </action>
                 <action name="select-tool">
                     <target>select-tool</target>
                 </action>
@@ -477,7 +474,6 @@
                     <ide-action name="build"/>
                     <ide-action name="rebuild"/>
                     <ide-action name="clean"/>
-                    <ide-action name="javadoc"/>
                     <separator/>
                     <ide-action name="run"/>
                     <ide-action name="debug"/>
@@ -490,37 +486,35 @@
         <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
             <compilation-unit>
                 <package-root>${root}/src/java.compiler/share/classes</package-root>
-                <package-root>${root}/build/bootstrap/java.compiler/gensrc</package-root>
+                <package-root>${root}/build/gensrc/java.compiler</package-root>
                 <built-to>${root}/build/java.compiler/classes</built-to>
                 <source-level>1.8</source-level>
             </compilation-unit>
             <compilation-unit>
                 <package-root>${root}/src/jdk.compiler/share/classes</package-root>
-                <package-root>${root}/build/bootstrap/jdk.compiler/gensrc</package-root>
+                <package-root>${root}/build/gensrc/jdk.compiler</package-root>
                 <classpath mode="compile">${root}/build/java.compiler/classes</classpath>
                 <built-to>${root}/build/jdk.compiler/classes</built-to>
                 <source-level>1.8</source-level>
             </compilation-unit>
             <compilation-unit>
                 <package-root>${root}/src/jdk.jdeps/share/classes</package-root>
-                <package-root>${root}/build/bootstrap/jdk.jdeps/gensrc</package-root>
+                <package-root>${root}/build/gensrc/jdk.jdeps</package-root>
                 <classpath mode="compile">${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
                 <built-to>${root}/build/jdk.jdeps/classes</built-to>
                 <source-level>1.8</source-level>
             </compilation-unit>
             <compilation-unit>
                 <package-root>${root}/src/jdk.javadoc/share/classes</package-root>
-                <package-root>${root}/build/bootstrap/jdk.javadoc/gensrc</package-root>
+                <package-root>${root}/build/gensrc/jdk.javadoc</package-root>
                 <classpath mode="compile">${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
                 <built-to>${root}/build/jdk.javadoc/classes</built-to>
                 <source-level>1.8</source-level>
             </compilation-unit>
             <compilation-unit>
                 <package-root>${root}/src/jdk.jshell/share/classes</package-root>
-                <package-root>${root}/build/bootstrap/jdk.jshell/gensrc</package-root>
-                <package-root>${root}/../jdk/src/jdk.internal.le/share/classes</package-root>
-                <package-root>${root}/../jdk/src/jdk.jdi/share/classes</package-root>
-                <classpath mode="compile">${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes:${root}/build/jdk.internal.le/classes:${root}/build/jdk.jdi/classes</classpath>
+                <package-root>${root}/build/gensrc/jdk.jshell</package-root>
+                <classpath mode="compile">${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
                 <built-to>${root}/build/jdk.jshell/classes</built-to>
                 <source-level>1.8</source-level>
             </compilation-unit>
diff --git a/langtools/make/tools/anttasks/SelectToolTask.java b/langtools/make/tools/anttasks/SelectToolTask.java
index a71f9aa..bf33051 100644
--- a/langtools/make/tools/anttasks/SelectToolTask.java
+++ b/langtools/make/tools/anttasks/SelectToolTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,18 +74,7 @@
 
     enum ToolChoices {
         NONE(""),
-        BOOSTRAP_JAVAC("bootstrap-javac", true) {
-            @Override
-            public ToolChoices baseTool() {
-                return JAVAC;
-            }
-        },
-        JAVAC("javac") {
-            @Override
-            public ToolChoices asBootstrap() {
-                return BOOSTRAP_JAVAC;
-            }
-        },
+        JAVAC("javac"),
         JAVADOC("javadoc"),
         JAVAH("javah"),
         JAVAP("javap"),
@@ -103,14 +92,6 @@
             this.bootstrap = bootstrap;
         }
 
-        public ToolChoices asBootstrap() {
-            return this;
-        }
-
-        public ToolChoices baseTool() {
-            return this;
-        }
-
         @Override
         public String toString() {
             return toolName;
@@ -146,15 +127,6 @@
     }
 
     /**
-     * Set the name of the property which will be used to bootstrap the
-     * selected tool, if any. The property will remain unset.
-     * @param bootstrapProperty
-     */
-    public void setBootstrapProperty(String bootstrapProperty) {
-        this.bootstrapProperty = bootstrapProperty;
-    }
-
-    /**
      * Specify whether or not to pop up a dialog if the user has not specified
      * a default value for a property.
      * @param askIfUnset a boolean flag indicating to prompt the user or not
@@ -169,7 +141,6 @@
 
         Properties props = readProperties(propertyFile);
         toolName = props.getProperty("tool.name");
-        toolBootstrap = props.getProperty("tool.bootstrap") != null;
         if (toolName != null) {
             toolArgs = props.getProperty(toolName + ".args", "");
         }
@@ -183,8 +154,6 @@
         // finally, return required values, if any
         if (toolProperty != null && !(toolName == null || toolName.equals(""))) {
             p.setProperty(toolProperty, toolName);
-            if (toolBootstrap)
-                p.setProperty(bootstrapProperty, "true");
 
             if (argsProperty != null && toolArgs != null)
                 p.setProperty(argsProperty, toolArgs);
@@ -198,20 +167,15 @@
 
         ToolChoices tool = (ToolChoices)toolChoice.getSelectedItem();
 
-        toolName = tool.baseTool().toolName;
-        toolBootstrap = tool.bootstrap;
+        toolName = tool.toolName;
         toolArgs = argsField.getText();
         if (defaultCheck.isSelected()) {
             if (toolName.equals("")) {
                 fileProps.remove("tool.name");
                 fileProps.remove("tool.bootstrap");
             } else {
+                fileProps.remove("tool.bootstrap");
                 fileProps.put("tool.name", toolName);
-                if (toolBootstrap) {
-                    fileProps.put("tool.bootstrap", "true");
-                } else {
-                    fileProps.remove("tool.bootstrap");
-                }
                 fileProps.put(toolName + ".args", toolArgs);
             }
             writeProperties(propertyFile, fileProps);
@@ -237,8 +201,6 @@
         toolChoice = new JComboBox<>(toolChoices.toArray());
         ToolChoices tool = toolName != null ? ToolChoices.valueOf(toolName.toUpperCase()) : null;
         if (toolName != null) {
-            if (toolBootstrap)
-                tool = tool.asBootstrap();
             toolChoice.setSelectedItem(tool);
         }
         toolChoice.addItemListener(new ItemListener() {
@@ -348,14 +310,13 @@
     String getDefaultArgsForTool(Properties props, ToolChoices tool) {
         if (tool == null)
             return "";
-        String toolName = tool.baseTool().toolName;
+        String toolName = tool.toolName;
         return toolName.equals("") ? "" : props.getProperty(toolName + ".args", "");
     }
 
     // Ant task parameters
     private boolean askIfUnset;
     private String toolProperty;
-    private String bootstrapProperty;
     private String argsProperty;
     private File propertyFile;
 
@@ -367,6 +328,5 @@
 
     // Result values for the client
     private String toolName;
-    private boolean toolBootstrap;
     private String toolArgs;
 }
diff --git a/langtools/make/tools/crules/CodingRulesAnalyzerPlugin.java b/langtools/make/tools/crules/CodingRulesAnalyzerPlugin.java
index bc2d7d9..74edca3 100644
--- a/langtools/make/tools/crules/CodingRulesAnalyzerPlugin.java
+++ b/langtools/make/tools/crules/CodingRulesAnalyzerPlugin.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -23,10 +23,13 @@
 
 package crules;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 import javax.lang.model.element.TypeElement;
 import javax.tools.JavaFileObject;
@@ -52,6 +55,11 @@
 
     @DefinedBy(Api.COMPILER_TREE)
     public void init(JavacTask task, String... args) {
+        addExports("jdk.compiler",
+                "com.sun.tools.javac.api",
+                "com.sun.tools.javac.code",
+                "com.sun.tools.javac.tree",
+                "com.sun.tools.javac.util");
         BasicJavacTask impl = (BasicJavacTask)task;
         Context context = impl.getContext();
         log = Log.instance(context);
@@ -63,6 +71,20 @@
         ));
     }
 
+    private void addExports(String moduleName, String... packageNames) {
+        for (String packageName : packageNames) {
+            try {
+                Layer layer = Layer.boot();
+                Optional<Module> m = layer.findModule(moduleName);
+                if (!m.isPresent())
+                    throw new Error("module not found: " + moduleName);
+                m.get().addExports(packageName, getClass().getModule());
+            } catch (Exception e) {
+                throw new Error("failed to add exports for " + moduleName + "/" + packageName);
+            }
+        }
+    }
+
     public class PostAnalyzeTaskListener implements TaskListener {
         private final Map<Kind, List<AbstractCodingRulesAnalyzer>> analyzers = new HashMap<>();
 
diff --git a/langtools/make/tools/propertiesparser/parser/MessageType.java b/langtools/make/tools/propertiesparser/parser/MessageType.java
index 6c70084..c4d96f1 100644
--- a/langtools/make/tools/propertiesparser/parser/MessageType.java
+++ b/langtools/make/tools/propertiesparser/parser/MessageType.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
@@ -77,6 +77,7 @@
         MODIFIER("modifier", "Modifier", "javax.lang.model.element"),
         FILE("file", "File", "java.io"),
         FILE_OBJECT("file object", "JavaFileObject", "javax.tools"),
+        PATH("path", "Path", "java.nio.file"),
         NAME("name", "Name", "com.sun.tools.javac.util"),
         NUMBER("number", "int", null),
         OPTION_NAME("option name", "Option", "com.sun.tools.javac.main"),
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
index a57f7b8..3c00e68 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -105,8 +105,8 @@
      * java.util.Set<E>} is {@code "Set"}.
      *
      * If this element represents an unnamed {@linkplain
-     * PackageElement#getSimpleName package}, an empty name is
-     * returned.
+     * PackageElement#getSimpleName package} or unnamed {@linkplain
+     * ModuleElement#getSimpleName module}, an empty name is returned.
      *
      * If it represents a {@linkplain ExecutableElement#getSimpleName
      * constructor}, the name "{@code <init>}" is returned.  If it
@@ -122,6 +122,7 @@
      * @see ExecutableElement#getSimpleName
      * @see TypeElement#getSimpleName
      * @see VariableElement#getSimpleName
+     * @see ModuleElement#getSimpleName
      */
     Name getSimpleName();
 
@@ -137,7 +138,7 @@
      * top-level type}, its package is returned.
      *
      * <li> If this is a {@linkplain
-     * PackageElement#getEnclosingElement package}, {@code null} is
+     * PackageElement#getEnclosingElement package}, its module is
      * returned.
      *
      * <li> If this is a {@linkplain
@@ -150,6 +151,9 @@
      * parameter}, {@linkplain ExecutableElement the executable
      * element} which declares the parameter is returned.
      *
+     * <li> If this is a {@linkplain ModuleElement#getEnclosingElement
+     * module}, {@code null} is returned.
+     *
      * </ul>
      *
      * @return the enclosing element, or {@code null} if there is none
@@ -169,6 +173,9 @@
      * encloses the top-level classes and interfaces within it, but is
      * not considered to enclose subpackages.
      *
+     * A {@linkplain ModuleElement#getEnclosedElements module}
+     * encloses packages within it.
+     *
      * Other kinds of elements are not currently considered to enclose
      * any elements; however, that may change as this API or the
      * programming language evolves.
@@ -177,8 +184,9 @@
      * methods in {@link ElementFilter}.
      *
      * @return the enclosed elements, or an empty list if none
-     * @see PackageElement#getEnclosedElements
      * @see TypeElement#getEnclosedElements
+     * @see PackageElement#getEnclosedElements
+     * @see ModuleElement#getEnclosedElements
      * @see Elements#getAllMembers
      * @jls 8.8.9 Default Constructor
      * @jls 8.9 Enums
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
index 2561cb8..e98d454 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -94,7 +94,13 @@
      * A resource variable.
      * @since 1.7
      */
-    RESOURCE_VARIABLE;
+     RESOURCE_VARIABLE,
+
+    /**
+     * A module.
+     * @since 9
+     */
+     MODULE;
 
 
     /**
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
index e065551..a06a5c2 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -143,4 +143,13 @@
      *  a visitor implementation may optionally throw this exception
      */
     R visitUnknown(Element e, P p);
+
+    /**
+     * Visits a module element.
+     * @param e  the element to visit
+     * @param p  a visitor-specified parameter
+     * @return a visitor-specified result
+     * @since 9
+     */
+    R visitModule(ModuleElement e, P p);
 }
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
new file mode 100644
index 0000000..306bf82
--- /dev/null
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.lang.model.element;
+
+import java.util.List;
+
+/**
+ * Represents a module program element.  Provides access to information
+ * about the module and its members.
+ *
+ * @see javax.lang.model.util.Elements#getModuleOf
+ * @since 9
+ */  // TODO: add @jls to module section
+public interface ModuleElement extends Element, QualifiedNameable {
+
+    /**
+     * Returns the fully qualified name of this module.
+     *
+     * @return the qualified name of this module, or an
+     * empty name if this is an unnamed module
+     */
+    @Override
+    Name getQualifiedName();
+
+    /**
+     * Returns the simple name of this module.  For an unnamed
+     * module, an empty name is returned.
+     *
+     * @return the simple name of this module or an empty name if
+     * this is an unnamed module
+     */
+    @Override
+    Name getSimpleName();
+
+    /**
+     * Returns the packages within this module.
+     * @return the packages within this module
+     */
+    @Override
+    List<? extends Element> getEnclosedElements();
+
+    /**
+     * Returns {@code true} if this is an unnamed module and {@code
+     * false} otherwise.
+     *
+     * @return {@code true} if this is an unnamed module and {@code
+     * false} otherwise
+     */ // TODO: add @jls to unnamed module section
+    boolean isUnnamed();
+
+    /**
+     * Returns {@code null} since a module is not enclosed by another
+     * element.
+     *
+     * @return {@code null}
+     */
+    @Override
+    Element getEnclosingElement();
+
+    /**
+     * Returns the directives contained in the declaration of this module.
+     * @return  the directives in the declaration of this module
+     */
+    List<? extends Directive> getDirectives();
+
+    /**
+     * The {@code kind} of a directive.
+     *
+     * <p>Note that it is possible additional directive kinds will be added
+     * to accommodate new, currently unknown, language structures added to
+     * future versions of the Java&trade; programming language.
+     *
+     * @since 9
+     */
+    enum DirectiveKind {
+        /** A "requires [public] module-name" directive. */
+        REQUIRES,
+        /** An "exports package-name [to module-name-list]" directive. */
+        EXPORTS,
+        /** A "uses service-name" directive. */
+        USES,
+        /** A "provides service-name with implementation-name" directive. */
+        PROVIDES
+    };
+
+    /**
+     * Represents a "module statement" within the declaration of this module.
+     *
+     * @since 9
+     *
+     */ // TODO: add jls to Module Statement
+    interface Directive {
+        /**
+         * Returns the {@code kind} of this directive.
+         *
+         * @return the kind of this directive
+         */
+        DirectiveKind getKind();
+    }
+
+    /**
+     * A dependency of a module.
+     * @since 9
+     */
+    interface RequiresDirective extends Directive {
+        /**
+         * Returns whether or not this is a public dependency.
+         * @return whether or not this is a public dependency
+         */
+        boolean isPublic();
+
+        /**
+         * Returns the module that is required
+         * @return the module that is required
+         */
+        ModuleElement getDependency();
+    }
+
+    /**
+     * An exported package of a module.
+     * @since 9
+     */
+    interface ExportsDirective extends Directive {
+        /**
+         * Returns the package being exported.
+         * @return the package being exported
+         */
+        PackageElement getPackage();
+
+        /**
+         * Returns the specific modules to which the package is being exported,
+         * or null, if the package is exported to all modules which
+         * have readability to this module.
+         * @return the specific modules to which the package is being exported
+         */
+        List<? extends ModuleElement> getTargetModules();
+    }
+
+    /**
+     * An implementation of a service provided by a module.
+     * @since 9
+     */
+    interface ProvidesDirective extends Directive {
+        /**
+         * Returns the service being provided.
+         * @return the service being provided
+         */
+        TypeElement getService();
+
+        /**
+         * Returns the implementation of the service being provided.
+         * @return the implementation of the service being provided
+         */
+        TypeElement getImplementation();
+    }
+
+    /**
+     * A reference to a service used by a module.
+     * @since 9
+     */
+    interface UsesDirective extends Directive {
+        /**
+         * Returns the service that is used.
+         * @return the service that is used
+         */
+        TypeElement getService();
+    }
+}
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
index 1aafd34..f319d31 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -72,20 +72,19 @@
     List<? extends Element> getEnclosedElements();
 
     /**
-     * Returns {@code true} is this is an unnamed package and {@code
+     * Returns {@code true} if this is an unnamed package and {@code
      * false} otherwise.
      *
-     * @return {@code true} is this is an unnamed package and {@code
+     * @return {@code true} if this is an unnamed package and {@code
      * false} otherwise
      * @jls 7.4.2 Unnamed Packages
      */
     boolean isUnnamed();
 
     /**
-     * Returns {@code null} since a package is not enclosed by another
-     * element.
+     * Returns the enclosing module.
      *
-     * @return {@code null}
+     * @return the enclosing module
      */
     @Override
     Element getEnclosingElement();
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
index cd974ce..b0a1b62 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,14 @@
       *
       * @since 1.8
       */
-    INTERSECTION;
+    INTERSECTION,
+
+    /**
+     * A pseudo-type corresponding to a module element.
+     * @see NoType
+     * @since 9
+     */
+    MODULE;
 
     /**
      * Returns {@code true} if this kind corresponds to a primitive
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
index b9ea796..54cd3a0 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -132,4 +132,19 @@
     public R visitUnknown(Element e, P p) {
         throw new UnknownElementException(e, p);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * visitUnknown}.
+
+     * @param e  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     *
+     * @since 9
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return visitUnknown(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
index c239303..d313514 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -27,6 +27,7 @@
 
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
 import static javax.lang.model.SourceVersion.*;
 
 
@@ -71,4 +72,15 @@
     protected AbstractElementVisitor9(){
         super();
     }
+
+    /**
+     * Visits a {@code ModuleElement} in a manner defined by a
+     * subclass.
+     *
+     * @param t  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of the visit as defined by a subclass
+     */
+    @Override
+    public abstract R visitModule(ModuleElement t, P p);
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
index c4c23fe..e5dbf49 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -33,6 +33,12 @@
 import java.util.LinkedHashSet;
 
 import javax.lang.model.element.*;
+import javax.lang.model.element.ModuleElement.Directive;
+import javax.lang.model.element.ModuleElement.DirectiveKind;
+import javax.lang.model.element.ModuleElement.ExportsDirective;
+import javax.lang.model.element.ModuleElement.ProvidesDirective;
+import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.element.ModuleElement.UsesDirective;
 
 
 /**
@@ -78,6 +84,9 @@
     private static final Set<ElementKind> PACKAGE_KIND =
         Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
 
+    private static final Set<ElementKind> MODULE_KIND =
+        Collections.unmodifiableSet(EnumSet.of(ElementKind.MODULE));
+
     private static final Set<ElementKind> TYPE_KINDS =
         Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
                                                ElementKind.ENUM,
@@ -183,6 +192,28 @@
         return setFilter(elements, PACKAGE_KIND, PackageElement.class);
     }
 
+    /**
+     * Returns a list of modules in {@code elements}.
+     * @return a list of modules in {@code elements}
+     * @param elements the elements to filter
+     * @since 9
+     */
+    public static List<ModuleElement>
+            modulesIn(Iterable<? extends Element> elements) {
+        return listFilter(elements, MODULE_KIND, ModuleElement.class);
+    }
+
+    /**
+     * Returns a set of modules in {@code elements}.
+     * @return a set of modules in {@code elements}
+     * @param elements the elements to filter
+     * @since 9
+     */
+    public static Set<ModuleElement>
+            modulesIn(Set<? extends Element> elements) {
+        return setFilter(elements, MODULE_KIND, ModuleElement.class);
+    }
+
     // Assumes targetKinds and E are sensible.
     private static <E extends Element> List<E> listFilter(Iterable<? extends Element> elements,
                                                           Set<ElementKind> targetKinds,
@@ -207,4 +238,62 @@
         }
         return set;
     }
+
+
+
+    /**
+     * Returns a list of export directives in {@code directives}.
+     * @return a list of export directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<ExportsDirective>
+            exportsIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.EXPORTS, ExportsDirective.class);
+    }
+
+    /**
+     * Returns a list of provides directives in {@code directives}.
+     * @return a list of provides directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<ProvidesDirective>
+            providesIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.PROVIDES, ProvidesDirective.class);
+    }
+
+    /**
+     * Returns a list of requires directives in {@code directives}.
+     * @return a list of requires directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<RequiresDirective>
+            requiresIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.REQUIRES, RequiresDirective.class);
+    }
+
+    /**
+     * Returns a list of uses directives in {@code directives}.
+     * @return a list of uses directives in {@code directives}
+     * @param directives the directives to filter
+     * @since 9
+     */
+    public static List<UsesDirective>
+            usesIn(Iterable<? extends Directive> directives) {
+        return listFilter(directives, DirectiveKind.USES, UsesDirective.class);
+    }
+
+    // Assumes directiveKind and D are sensible.
+    private static <D extends Directive> List<D> listFilter(Iterable<? extends Directive> directives,
+                                                          DirectiveKind directiveKind,
+                                                          Class<D> clazz) {
+        List<D> list = new ArrayList<>();
+        for (Directive d : directives) {
+            if (d.getKind() == directiveKind)
+                list.add(clazz.cast(d));
+        }
+        return list;
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
index a0e51e2..eb1a303 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -95,4 +95,17 @@
     protected ElementKindVisitor9(R defaultValue) {
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * defaultAction}.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of {@code defaultAction}
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return defaultAction(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
index b6f8810..c7419c8 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -108,4 +108,17 @@
     protected ElementScanner9(R defaultValue){
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by scanning the enclosed
+     * elements.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of the scan
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return scan(e.getEnclosedElements(), p); // TODO: Hmmm, this might not be right
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
index bc4eb28..9c3801d 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -30,7 +30,6 @@
 import java.util.Map;
 
 import javax.lang.model.element.*;
-import javax.lang.model.type.*;
 
 
 /**
@@ -64,6 +63,15 @@
     TypeElement getTypeElement(CharSequence name);
 
     /**
+     * Returns a module element given its fully qualified name.
+     *
+     * @param name  the name
+     * @return the named module element, or {@code null} if it cannot be found
+     * @since 9
+     */
+    ModuleElement getModuleElement(CharSequence name);
+
+    /**
      * Returns the values of an annotation's elements, including defaults.
      *
      * @see AnnotationMirror#getElementValues()
@@ -129,6 +137,16 @@
     PackageElement getPackageOf(Element type);
 
     /**
+     * Returns the module of an element.  The module of a module is
+     * itself.
+     *
+     * @param type the element being examined
+     * @return the module of an element
+     * @since 9
+     */
+    ModuleElement getModuleOf(Element type);
+
+    /**
      * Returns all members of a type element, whether inherited or
      * declared directly.  For a class the result also includes its
      * constructors, but not local or anonymous classes.
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
index fae29ca..3b9f3f0 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -27,6 +27,7 @@
 
 import javax.annotation.processing.SupportedSourceVersion;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
 import static javax.lang.model.SourceVersion.*;
 
 /**
@@ -90,4 +91,17 @@
     protected SimpleElementVisitor9(R defaultValue){
         super(defaultValue);
     }
+
+    /**
+     * Visits a {@code ModuleElement} by calling {@code
+     * defaultAction}.
+     *
+     * @param e the element to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of {@code defaultAction}
+     */
+    @Override
+    public R visitModule(ModuleElement e, P p) {
+        return defaultAction(e, p);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java b/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
index f916c43..ed63244 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.Set;
 import javax.tools.JavaFileObject.Kind;
 
@@ -163,4 +164,24 @@
     public void close() throws IOException {
         fileManager.close();
     }
+
+    public Location getModuleLocation(Location location, String moduleName) throws IOException {
+        return fileManager.getModuleLocation(location, moduleName);
+    }
+
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        return fileManager.getModuleLocation(location, fo, pkgName);
+    }
+
+    public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws  IOException {
+        return fileManager.getServiceLoader(location, service);
+    }
+
+    public String inferModuleName(Location location) throws IOException {
+        return fileManager.inferModuleName(location);
+    }
+
+    public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        return fileManager.listModuleLocations(location);
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java
index e5e911e..bc1633a 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.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
@@ -29,7 +29,9 @@
 import java.io.Flushable;
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.ServiceLoader;
 import java.util.Set;
+
 import static javax.tools.JavaFileObject.Kind;
 
 /**
@@ -124,6 +126,17 @@
          * @return true if this is an output location, false otherwise
          */
         boolean isOutputLocation();
+
+        /**
+         * Indicates if this location is expected to contain modules,
+         * as compared to a location which contains packages and classes.
+         *
+         * @return true if this location is expected to contain modules
+         * @since 9
+         */
+        default boolean isModuleLocation() {
+            return false;
+        }
     }
 
     /**
@@ -385,6 +398,7 @@
      * @throws IOException if an I/O error occurred
      * @see #close
      */
+    @Override
     void flush() throws IOException;
 
     /**
@@ -398,5 +412,84 @@
      * @throws IOException if an I/O error occurred
      * @see #flush
      */
+    @Override
     void close() throws IOException;
+
+    /**
+     * Gets a location for a named module within a module-oriented location.
+     *
+     * @param location the module-oriented location
+     * @param moduleName the name of the module to be found
+     * @return the location for the named module
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Location getModuleLocation(Location location, String moduleName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Gets a location for the module containing a specific file representing a Java
+     * source or class.
+     *
+     * @param location a module-oriented location
+     * @param fo the file
+     * @param pkgName the package name for the class(es) defined in this file
+     * @return the module containing the file
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get a service loader for a specific service class from a given location.
+     *
+     * @param location the location
+     * @param service  the {@code Class} object of the service class
+     * @param <S> the service class
+     * @return a service loader for the given service class
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws  IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Infer the name of the module from its location, as returned by
+     * getModuleLocation or listModuleLocations.
+     *
+     * @param location a location representing a module
+     * @return the name of the module
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default String inferModuleName(Location location) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Lists the modules in a module-oriented location.
+     *
+     * @param location  the location for which to list the modules
+     * @return  a series of sets of locations containing modules
+     *
+     * @throws IOException if an I/O error occurred
+     * @throws UnsupportedOperationException if this operation if not supported by this file manager
+     * @since 9
+     */ // TODO: describe failure modes
+    default Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java b/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
index 199f22d..9ca72e0 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardLocation.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, 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
@@ -63,6 +63,12 @@
     ANNOTATION_PROCESSOR_PATH,
 
     /**
+     * Location to search for modules containing annotation processors.
+     * @since 9
+     */
+    ANNOTATION_PROCESSOR_MODULE_PATH,
+
+    /**
      * Location to search for platform classes.  Sometimes called
      * the boot class path.
      */
@@ -72,7 +78,31 @@
      * Location of new native header files.
      * @since 1.8
      */
-    NATIVE_HEADER_OUTPUT;
+    NATIVE_HEADER_OUTPUT,
+
+    /**
+     * Location to search for the source code of modules.
+     * @since 9
+     */
+    MODULE_SOURCE_PATH,
+
+    /**
+     * Location to search for upgradeable system modules.
+     * @since 9
+     */
+    UPGRADE_MODULE_PATH,
+
+    /**
+     * Location to search for system modules.
+     * @since 9
+     */
+    SYSTEM_MODULES,
+
+    /**
+     * Location to search for precompiled user modules.
+     * @since 9
+     */
+    MODULE_PATH;
 
     /**
      * Returns a location object with the given name.  The following
@@ -90,8 +120,11 @@
             for (Location location : values())
                 locations.putIfAbsent(location.getName(), location);
         }
-        locations.putIfAbsent(name.toString(/* null-check */), new Location() {
+        name.getClass(); /* null-check */
+        locations.putIfAbsent(name, new Location() {
+                @Override
                 public String getName() { return name; }
+                @Override
                 public boolean isOutputLocation() { return name.endsWith("_OUTPUT"); }
             });
         return locations.get(name);
@@ -100,8 +133,10 @@
         private static final ConcurrentMap<String,Location> locations
             = new ConcurrentHashMap<>();
 
+    @Override
     public String getName() { return name(); }
 
+    @Override
     public boolean isOutputLocation() {
         switch (this) {
             case CLASS_OUTPUT:
@@ -112,4 +147,18 @@
                 return false;
         }
     }
+
+    @Override
+    public boolean isModuleLocation() {
+        switch (this) {
+            case MODULE_SOURCE_PATH:
+            case ANNOTATION_PROCESSOR_MODULE_PATH:
+            case UPGRADE_MODULE_PATH:
+            case SYSTEM_MODULES:
+            case MODULE_PATH:
+                return true;
+            default:
+                return false;
+        }
+    }
 }
diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
index 447c964..1909ce4 100644
--- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java
@@ -25,10 +25,11 @@
 
 package javax.tools;
 
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * Provides methods for locating tool providers, for example,
@@ -40,8 +41,8 @@
  */
 public class ToolProvider {
 
-    private static final String systemJavaCompilerName
-        = "com.sun.tools.javac.api.JavacTool";
+    private static final String systemJavaCompilerModule = "jdk.compiler";
+    private static final String systemJavaCompilerName   = "com.sun.tools.javac.api.JavacTool";
 
     /**
      * Returns the Java&trade; programming language compiler provided
@@ -52,13 +53,17 @@
      * {@linkplain java.nio.file.FileSystem filesystem}.</p>
      * @return the compiler provided with this platform or
      * {@code null} if no compiler is provided
+     * @implNote This implementation returns the compiler provided
+     * by the {@code jdk.compiler} module if that module is available,
+     * and null otherwise.
      */
     public static JavaCompiler getSystemJavaCompiler() {
-        return instance().getSystemTool(JavaCompiler.class, systemJavaCompilerName);
+        return getSystemTool(JavaCompiler.class,
+                systemJavaCompilerModule, systemJavaCompilerName);
     }
 
-    private static final String systemDocumentationToolName
-        = "jdk.javadoc.internal.api.JavadocTool";
+    private static final String systemDocumentationToolModule = "jdk.javadoc";
+    private static final String systemDocumentationToolName = "jdk.javadoc.internal.api.JavadocTool";
 
     /**
      * Returns the Java&trade; programming language documentation tool provided
@@ -69,9 +74,13 @@
      * {@linkplain java.nio.file.FileSystem filesystem}.</p>
      * @return the documentation tool provided with this platform or
      * {@code null} if no documentation tool is provided
+     * @implNote This implementation returns the tool provided
+     * by the {@code jdk.javadoc} module if that module is available,
+     * and null otherwise.
      */
     public static DocumentationTool getSystemDocumentationTool() {
-        return instance().getSystemTool(DocumentationTool.class, systemDocumentationToolName);
+        return getSystemTool(DocumentationTool.class,
+                systemDocumentationToolModule, systemDocumentationToolName);
     }
 
     /**
@@ -87,41 +96,70 @@
         return ClassLoader.getSystemClassLoader();
     }
 
+    private static final boolean useLegacy;
 
-    private static ToolProvider instance;
-
-    private static synchronized ToolProvider instance() {
-        if (instance == null)
-            instance = new ToolProvider();
-        return instance;
-    }
-
-    // Cache for tool classes.
-    // Use weak references to avoid keeping classes around unnecessarily
-    private final Map<String, Reference<Class<?>>> toolClasses = new HashMap<>();
-
-    private ToolProvider() { }
-
-    private <T> T getSystemTool(Class<T> clazz, String name) {
-        Class<? extends T> c = getSystemToolClass(clazz, name);
+    static {
+        Class<?> c = null;
         try {
-            return c.asSubclass(clazz).newInstance();
-        } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) {
-            throw new Error(e);
+            c = Class.forName("java.lang.reflect.Module");
+        } catch (Throwable t) {
         }
+        useLegacy = (c == null);
     }
 
-    private <T> Class<? extends T> getSystemToolClass(Class<T> clazz, String name) {
-        Reference<Class<?>> refClass = toolClasses.get(name);
-        Class<?> c = (refClass == null ? null : refClass.get());
-        if (c == null) {
+    /**
+     * Get an instance of a system tool using the service loader.
+     * @implNote         By default, this returns the implementation in the specified module.
+     *                   For limited backward compatibility, if this code is run on an older version
+     *                   of the Java platform that does not support modules, this method will
+     *                   try and create an instance of the named class. Note that implies the
+     *                   class must be available on the system class path.
+     * @param <T>        the interface of the tool
+     * @param clazz      the interface of the tool
+     * @param moduleName the name of the module containing the desired implementation
+     * @param className  the class name of the desired implementation
+     * @return the specified implementation of the tool
+     */
+    private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) {
+        if (useLegacy) {
             try {
-                c = Class.forName(name, false, ClassLoader.getSystemClassLoader());
-            } catch (ClassNotFoundException | RuntimeException | Error e) {
+                return Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+            } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
-            toolClasses.put(name, new WeakReference<>(c));
         }
-        return c.asSubclass(clazz);
+
+        try {
+            ServiceLoader<T> sl = ServiceLoader.load(clazz, ClassLoader.getSystemClassLoader());
+            for (Iterator<T> iter = sl.iterator(); iter.hasNext(); ) {
+                T tool = iter.next();
+                if (matches(tool, moduleName))
+                    return tool;
+            }
+        } catch (ServiceConfigurationError e) {
+            throw new Error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Determine if this is tho desired tool instance.
+     * @param <T>        the interface of the tool
+     * @param tool       the instance of the tool
+     * @param moduleName the name of the module containing the desired implementation
+     * @return true if and only if the tool matches the specified criteria
+     */
+    private static <T> boolean matches(T tool, String moduleName) {
+        // for now, use reflection to implement
+        //      return moduleName.equals(tool.getClass().getModule().getName());
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object toolModule = getModuleMethod.invoke(tool.getClass());
+            Method getNameMethod = toolModule.getClass().getDeclaredMethod("getName");
+            String toolModuleName = (String) getNameMethod.invoke(toolModule);
+            return moduleName.equals(toolModuleName);
+        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
+            return false;
+        }
     }
 }
diff --git a/langtools/src/java.compiler/share/classes/module-info.java b/langtools/src/java.compiler/share/classes/module-info.java
new file mode 100644
index 0000000..c835200
--- /dev/null
+++ b/langtools/src/java.compiler/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * 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
+ * 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.
+ */
+
+module java.compiler {
+    exports javax.annotation.processing;
+    exports javax.lang.model;
+    exports javax.lang.model.element;
+    exports javax.lang.model.type;
+    exports javax.lang.model.util;
+    exports javax.tools;
+
+    uses javax.tools.DocumentationTool;
+    uses javax.tools.JavaCompiler;
+}
+
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java
new file mode 100644
index 0000000..dc4f6b3
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/DirectiveTree.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+/**
+ * A super-type for all the directives in a ModuleTree.
+ */
+public interface DirectiveTree extends Tree { }
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
new file mode 100644
index 0000000..aeaef2b
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
@@ -0,0 +1,55 @@
+/*
+ * 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 'exports' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    exports <em>package-name</em>;
+ *    exports <em>package-name</em> to <em>module-name</em>;
+ * </pre>
+ *
+ * @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();
+
+    /**
+     * Returns the names of the modules to which the package is exported,
+     * or null, if the package is exported to all modules.
+     *
+     * @return the names of the modules to which the package is exported, or null
+     */
+    List<? extends ExpressionTree> getModuleNames();
+}
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
new file mode 100644
index 0000000..bcfa6ef
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
@@ -0,0 +1,55 @@
+/*
+ * 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 a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    module <em>module-name</em> {
+ *        <em>directives</em>
+ *    }
+ * </pre>
+ *
+ * @since 9
+ */
+public interface ModuleTree extends Tree {
+    /**
+     * Returns the name of the module.
+     * @return the name of the module
+     */
+    ExpressionTree getName();
+
+    /**
+     * Returns the directives in the module declaration.
+     * @return the directives in the module declaration
+     */
+    List<? extends DirectiveTree> getDirectives();
+}
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
new file mode 100644
index 0000000..3189f3f
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+/**
+ * A tree node for a 'provides' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    provides <em>service-name</em> with <em>implementation-name</em>;
+ * </pre>
+
+ * @since 9
+ */
+public interface ProvidesTree extends DirectiveTree {
+    /**
+     * Returns the name of the service type being provided.
+     * @return the name of the service type being provided
+     */
+    ExpressionTree getServiceName();
+
+    /**
+     * Returns the name of the implementation type being provided.
+     * @return the name of the implementation type being provided
+     */
+    ExpressionTree getImplementationName();
+}
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
new file mode 100644
index 0000000..9a5f55c
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+/**
+ * A tree node for a 'requires' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    requires <em>module-name</em>;
+ *    requires public <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
+     */
+    boolean isPublic();
+
+    /**
+     * Returns the name of the module that is required.
+     * @return the name of the module that is required
+     */
+    ExpressionTree getModuleName();
+}
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 bdd0f53..73f1fd4 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, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -604,6 +604,35 @@
         ANNOTATION_TYPE(ClassTree.class),
 
         /**
+         * Used for instances of {@link ModuleTree} representing module declarations.
+         */
+        MODULE(ModuleTree.class),
+
+        /**
+         * Used for instances of {@link ExportsTree} representing
+         * export directives in a module declaration.
+         */
+        EXPORTS(ExportsTree.class),
+
+        /**
+         * Used for instances of {@link ProvidesTree} representing
+         * export directives in a module declaration.
+         */
+        PROVIDES(ProvidesTree.class),
+
+        /**
+         * Used for instances of {@link RequiresTree} representing
+         * export directives in a module declaration.
+         */
+        REQUIRES(RequiresTree.class),
+
+        /**
+         * Used for instances of {@link UsesTree} representing
+         * export directives in a module declaration.
+         */
+        USES(UsesTree.class),
+
+        /**
          * An implementation-reserved node. This is the not the node
          * you are looking for.
          */
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 30d2a32..f1f951e 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
@@ -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
@@ -482,6 +482,46 @@
     R visitWildcard(WildcardTree node, P p);
 
     /**
+     * Visits a ModuleTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitModule(ModuleTree node, P p);
+
+    /**
+     * Visits an ExportsTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitExports(ExportsTree node, P p);
+
+    /**
+     * Visits a ProvidesTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitProvides(ProvidesTree node, P p);
+
+    /**
+     * Visits a RequiresTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitRequires(RequiresTree node, P p);
+
+    /**
+     * Visits a UsesTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitUses(UsesTree node, P p);
+
+    /**
      * Visits an unknown type of Tree node.
      * This can occur if the language evolves and new kinds
      * of nodes are added to the {@code Tree} hierarchy.
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java
new file mode 100644
index 0000000..9b52eb2
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java
@@ -0,0 +1,45 @@
+
+/*
+ * 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;
+
+/**
+ * A tree node for a 'uses' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    uses <em>service-name</em>;
+ * </pre>
+ *
+ * @since 9
+ */
+public interface UsesTree extends DirectiveTree {
+    /**
+     * Returns the name of the service type.
+     * @return  the name of the service type
+     */
+    ExpressionTree getServiceName();
+}
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 a7e5740..0b13ca7 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, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -719,14 +719,30 @@
         return defaultAction(node, p);
     }
 
-    /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
-     *
-     * @param node {@inheritDoc}
-     * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
-     */
+    public R visitModule(ModuleTree node, P p) {
+        return defaultAction(node, p);
+    }
+
     @Override
+    public R visitExports(ExportsTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitProvides(ProvidesTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitRequires(RequiresTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
+    public R visitUses(UsesTree node, P p) {
+        return defaultAction(node, p);
+    }
+
     public R visitErroneous(ErroneousTree 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 3e37f6f..3751154 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, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -846,6 +846,32 @@
         return r;
     }
 
+    public R visitModule(ModuleTree node, P p) {
+        R r = scan(node.getName(), p);
+        r = scanAndReduce(node.getDirectives(), p, r);
+        return r;
+    }
+
+    public R visitExports(ExportsTree node, P p) {
+        R r = scan(node.getExportName(), 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);
+        return r;
+    }
+
+    public R visitRequires(RequiresTree node, P p) {
+        return scan(node.getModuleName(), p);
+    }
+
+    public R visitUses(UsesTree node, P p) {
+        return scan(node.getServiceName(), p);
+    }
+
     /**
      * {@inheritDoc} This implementation returns {@code null}.
      *
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
index 9559d4a..186b6e8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java
@@ -195,6 +195,9 @@
                 } else {
                     throw new BadArgs("dc.bad.value.for.option", arg, args[i]);
                 }
+            } else if ((arg.equals("-target") || arg.equals("-source")) && i + 1 < args.length) {
+                javacOpts.add(arg);
+                javacOpts.add(args[++i]);
             } else if (arg.equals(STATS)) {
                 env.messages.setStatsEnabled(true);
             } else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
index 0b958a6..e73f28c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/BasicJavacTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -28,6 +28,7 @@
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.Locale;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -57,7 +58,6 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.PropagatedException;
-import com.sun.tools.javac.util.ServiceLoader;
 
 /**
  * Provides basic functionality for implementations of JavacTask.
@@ -195,8 +195,7 @@
 
         Set<List<String>> pluginsToCall = new LinkedHashSet<>(pluginOpts);
         JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context);
-        ClassLoader cl = pEnv.getProcessorClassLoader();
-        ServiceLoader<Plugin> sl = ServiceLoader.load(Plugin.class, cl);
+        ServiceLoader<Plugin> sl = pEnv.getServiceLoader(Plugin.class);
         for (Plugin plugin : sl) {
             for (List<String> p : pluginsToCall) {
                 if (plugin.getName().equals(p.head)) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
index 439c2cc..3bdd316 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -36,6 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.net.URI;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -347,6 +348,50 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Location getModuleLocation(Location location, String moduleName) throws IOException {
+            try {
+                return clientJavaFileManager.getModuleLocation(location, moduleName);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+            try {
+                return clientJavaFileManager.getModuleLocation(location, fo, pkgName);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public String inferModuleName(Location location) throws IOException {
+            try {
+                return clientJavaFileManager.inferModuleName(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+            try {
+                return clientJavaFileManager.listModuleLocations(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public int isSupportedOption(String option) {
             try {
                 return clientJavaFileManager.isSupportedOption(option);
@@ -381,6 +426,17 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Iterable<? extends Path> paths) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromPaths(paths);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
             try {
                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(files);
@@ -392,6 +448,17 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(paths);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
         public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
             try {
                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromStrings(names);
@@ -414,9 +481,20 @@
         }
 
         @Override @DefinedBy(Api.COMPILER)
-        public void setLocation(Location location, Iterable<? extends File> path) throws IOException {
+        public void setLocation(Location location, Iterable<? extends File> files) throws IOException {
             try {
-                ((StandardJavaFileManager)clientJavaFileManager).setLocation(location, path);
+                ((StandardJavaFileManager)clientJavaFileManager).setLocation(location, files);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public void setLocationFromPaths(Location location, Iterable<? extends Path> paths) throws IOException {
+            try {
+                ((StandardJavaFileManager)clientJavaFileManager).setLocationFromPaths(location, paths);
             } catch (ClientCodeException e) {
                 throw e;
             } catch (RuntimeException | Error e) {
@@ -434,6 +512,28 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Iterable<? extends Path> getLocationAsPaths(Location location) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).getLocationAsPaths(location);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER)
+        public Path asPath(FileObject file) {
+            try {
+                return ((StandardJavaFileManager)clientJavaFileManager).asPath(file);
+            } catch (ClientCodeException e) {
+                throw e;
+            } catch (RuntimeException | Error e) {
+                throw new ClientCodeException(e);
+            }
+        }
     }
 
     protected class WrappedFileObject implements FileObject {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
index 1a17ec0..384dadc 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -33,12 +33,17 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
 import javax.tools.*;
+import javax.tools.JavaFileObject.Kind;
 
 import com.sun.source.tree.*;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.comp.*;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.main.*;
@@ -49,6 +54,8 @@
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
+import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.List;
@@ -253,7 +260,7 @@
      * @return a list of elements corresponding to the top level
      * classes in the abstract syntax trees
      */
-    public Iterable<? extends TypeElement> enter() {
+    public Iterable<? extends Element> enter() {
         return enter(null);
     }
 
@@ -264,11 +271,13 @@
      * @return a list of elements corresponding to the top level
      * classes in the abstract syntax trees
      */
-    public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees)
+    public Iterable<? extends Element> enter(Iterable<? extends CompilationUnitTree> trees)
     {
         if (trees == null && notYetEntered != null && notYetEntered.isEmpty())
             return List.nil();
 
+        boolean wasInitialized = compiler != null;
+
         prepareCompiler(true);
 
         ListBuffer<JCCompilationUnit> roots = null;
@@ -305,22 +314,38 @@
             }
         }
 
-        if (roots == null)
+        if (roots == null) {
+            if (trees == null && !wasInitialized) {
+                compiler.initModules(List.nil());
+            }
             return List.nil();
+        }
+
+        List<JCCompilationUnit> units = compiler.initModules(roots.toList());
 
         try {
-            List<JCCompilationUnit> units = compiler.enterTrees(roots.toList());
+            units = compiler.enterTrees(units);
 
             if (notYetEntered.isEmpty())
                 compiler.processAnnotations(units);
 
-            ListBuffer<TypeElement> elements = new ListBuffer<>();
+            ListBuffer<Element> elements = new ListBuffer<>();
             for (JCCompilationUnit unit : units) {
-                for (JCTree node : unit.defs) {
-                    if (node.hasTag(JCTree.Tag.CLASSDEF)) {
-                        JCClassDecl cdef = (JCClassDecl) node;
-                        if (cdef.sym != null) // maybe null if errors in anno processing
-                            elements.append(cdef.sym);
+                boolean isPkgInfo = unit.sourcefile.isNameCompatible("package-info",
+                                                                     JavaFileObject.Kind.SOURCE);
+                if (isPkgInfo) {
+                    elements.append(unit.packge);
+                } else {
+                    for (JCTree node : unit.defs) {
+                        if (node.hasTag(JCTree.Tag.CLASSDEF)) {
+                            JCClassDecl cdef = (JCClassDecl) node;
+                            if (cdef.sym != null) // maybe null if errors in anno processing
+                                elements.append(cdef.sym);
+                        } else if (node.hasTag(JCTree.Tag.MODULEDEF)) {
+                            JCModuleDecl mdef = (JCModuleDecl) node;
+                            if (mdef.sym != null)
+                                elements.append(mdef.sym);
+                        }
                     }
                 }
             }
@@ -353,7 +378,7 @@
     // This implementation requires that we open up privileges on JavaCompiler.
     // An alternative implementation would be to move this code to JavaCompiler and
     // wrap it here
-    public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) {
+    public Iterable<? extends Element> analyze(Iterable<? extends Element> classes) {
         enter(null);  // ensure all classes have been entered
 
         final ListBuffer<Element> results = new ListBuffer<>();
@@ -383,8 +408,13 @@
                         if (cdef.sym != null)
                             elems.append(cdef.sym);
                         break;
-                    case TOPLEVEL:
-                        JCCompilationUnit unit = (JCCompilationUnit) env.tree;
+                    case MODULEDEF:
+                        JCModuleDecl mod = (JCModuleDecl) env.tree;
+                        if (mod.sym != null)
+                            elems.append(mod.sym);
+                        break;
+                    case PACKAGEDEF:
+                        JCCompilationUnit unit = env.toplevel;
                         if (unit.packge != null)
                             elems.append(unit.packge);
                         break;
@@ -413,7 +443,7 @@
      * @param classes a list of class elements
      * @return the files that were generated
      */
-    public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) {
+    public Iterable<? extends JavaFileObject> generate(Iterable<? extends Element> classes) {
         final ListBuffer<JavaFileObject> results = new ListBuffer<>();
         try {
             analyze(null);  // ensure all classes have been parsed, entered, and analyzed
@@ -447,17 +477,33 @@
         return TreeInfo.pathFor((JCTree) node, (JCTree.JCCompilationUnit) unit).reverse();
     }
 
+    public void ensureEntered() {
+        args.allowEmpty();
+        enter(null);
+    }
+
     abstract class Filter {
-        void run(Queue<Env<AttrContext>> list, Iterable<? extends TypeElement> classes) {
-            Set<TypeElement> set = new HashSet<>();
-            for (TypeElement item: classes)
+        void run(Queue<Env<AttrContext>> list, Iterable<? extends Element> elements) {
+            Set<Element> set = new HashSet<>();
+            for (Element item: elements) {
                 set.add(item);
+            }
 
             ListBuffer<Env<AttrContext>> defer = new ListBuffer<>();
             while (list.peek() != null) {
                 Env<AttrContext> env = list.remove();
-                ClassSymbol csym = env.enclClass.sym;
-                if (csym != null && set.contains(csym.outermostClass()))
+                Symbol test = null;
+
+                if (env.tree.hasTag(Tag.MODULEDEF)) {
+                    test = ((JCModuleDecl) env.tree).sym;
+                } else if (env.tree.hasTag(Tag.PACKAGEDEF)) {
+                    test = env.toplevel.packge;
+                } else {
+                    ClassSymbol csym = env.enclClass.sym;
+                    if (csym != null)
+                        test = csym.outermostClass();
+                }
+                if (test != null && set.contains(test))
                     process(env);
                 else
                     defer = defer.append(env);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java
index 99b7982..bc750f2 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTool.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
@@ -129,9 +129,17 @@
             }
 
             if (classes != null) {
-                for (String cls : classes)
-                    if (!SourceVersion.isName(cls)) // implicit null check
+                for (String cls : classes) {
+                    int sep = cls.indexOf('/'); // implicit null check
+                    if (sep > 0) {
+                        String mod = cls.substring(0, sep);
+                        if (!SourceVersion.isName(mod))
+                            throw new IllegalArgumentException("Not a valid module name: " + mod);
+                        cls = cls.substring(sep + 1);
+                    }
+                    if (!SourceVersion.isName(cls))
                         throw new IllegalArgumentException("Not a valid class name: " + cls);
+                }
             }
 
             if (compilationUnits != null) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
index d75f6f2..abd811b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
@@ -76,6 +76,7 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -92,6 +93,7 @@
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
 import com.sun.tools.javac.comp.MemberEnter;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.file.BaseFileManager;
 import com.sun.tools.javac.model.JavacElements;
@@ -156,6 +158,7 @@
 public class JavacTrees extends DocTrees {
 
     // in a world of a single context per compilation, these would all be final
+    private Modules modules;
     private Resolve resolve;
     private Enter enter;
     private Log log;
@@ -206,6 +209,7 @@
     }
 
     private void init(Context context) {
+        modules = Modules.instance(context);
         attr = Attr.instance(context);
         enter = Enter.instance(context);
         elements = JavacElements.instance(context);
@@ -434,21 +438,31 @@
                 // and if not, then we check to see if it identifies a package.
                 Type t = attr.attribType(ref.qualifierExpression, env);
                 if (t.isErroneous()) {
-                    if (ref.memberName == null) {
-                        // Attr/Resolve assume packages exist and create symbols as needed
-                        // so use getPackageElement to restrict search to existing packages
-                        PackageSymbol pck = elements.getPackageElement(ref.qualifierExpression.toString());
-                        if (pck != null) {
-                            return pck;
-                        } else if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
+                    JCCompilationUnit toplevel =
+                        treeMaker.TopLevel(List.<JCTree>nil());
+                    final ModuleSymbol msym = modules.getDefaultModule();
+                    toplevel.modle = msym;
+                    toplevel.packge = msym.unnamedPackage;
+                    Symbol sym = attr.attribIdent(ref.qualifierExpression, toplevel);
+
+                    sym.complete();
+
+                    if ((sym.kind == PCK || sym.kind == TYP) && sym.exists()) {
+                        tsym = (TypeSymbol) sym;
+                        memberName = (Name) ref.memberName;
+                        if (sym.kind == PCK && memberName != null) {
+                            //cannot refer to a package "member"
+                            return null;
+                        }
+                    } else {
+                        if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
                             // fixup:  allow "identifier" instead of "#identifier"
                             // for compatibility with javadoc
                             tsym = env.enclClass.sym;
                             memberName = ((JCIdent) ref.qualifierExpression).name;
-                        } else
+                        } else {
                             return null;
-                    } else {
-                        return null;
+                        }
                     }
                 } else {
                     tsym = t.tsym;
@@ -1179,7 +1193,8 @@
             }
         };
 
-        PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo, syms.unnamedPackage);
+        PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo,
+                syms.unnamedModule.unnamedPackage);
 
         jcCompilationUnit.docComments = new DocCommentTable() {
             @Override
@@ -1209,13 +1224,12 @@
 
         };
         jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap();
+        jcCompilationUnit.modle = psym.modle;
+        jcCompilationUnit.sourcefile = jfo;
         jcCompilationUnit.namedImportScope = new NamedImportScope(psym, jcCompilationUnit.toplevelScope);
         jcCompilationUnit.packge = psym;
-        jcCompilationUnit.starImportScope = null;
-        jcCompilationUnit.sourcefile = jfo;
         jcCompilationUnit.starImportScope = new StarImportScope(psym);
         jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
-
         return new TreePath(jcCompilationUnit);
     }
 }
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 466a41d..047eaa3 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
@@ -37,11 +37,13 @@
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.comp.Annotate;
@@ -118,6 +120,10 @@
      */
     final Name completionFailureName;
 
+    /** Module specified with -Xmodule:
+     */
+    final Name moduleOverride;
+
     /** Access to files
      */
     private final JavaFileManager fileManager;
@@ -178,7 +184,7 @@
         return instance;
     }
 
-    /** Construct a new class reader. */
+    /** Construct a new class finder. */
     protected ClassFinder(Context context) {
         context.put(classFinderKey, this);
         reader = ClassReader.instance(context);
@@ -205,6 +211,9 @@
             ? names.fromString(options.get("failcomplete"))
             : null;
 
+        moduleOverride = options.isSet(XMODULE) ? names.fromString(options.get(XMODULE))
+                                                : null;
+
         // Temporary, until more info is available from the module system.
         boolean useCtProps;
         JavaFileManager fm = context.get(JavaFileManager.class);
@@ -237,7 +246,7 @@
      * available from the module system.
      */
     long getSupplementaryFlags(ClassSymbol c) {
-        if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile)) {
+        if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) {
             return 0;
         }
 
@@ -318,7 +327,7 @@
             for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
                 Symbol encl = owner.members().findFirst(name);
                 if (encl == null)
-                    encl = syms.classes.get(TypeSymbol.formFlatName(name, owner));
+                    encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner));
                 if (encl != null)
                     encl.complete();
             }
@@ -328,7 +337,7 @@
     /** Fill in definition of class `c' from corresponding class or
      *  source file.
      */
-    private void fillIn(ClassSymbol c) {
+    void fillIn(ClassSymbol c) {
         if (completionFailureName == c.fullname) {
             throw new CompletionFailure(c, "user-selected completion failure by class name");
         }
@@ -397,14 +406,21 @@
     /** Load a toplevel class with given fully qualified name
      *  The class is entered into `classes' only if load was successful.
      */
-    public ClassSymbol loadClass(Name flatname) throws CompletionFailure {
-        boolean absent = syms.classes.get(flatname) == null;
-        ClassSymbol c = syms.enterClass(flatname);
+    public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure {
+        Assert.checkNonNull(msym);
+        Name packageName = Convert.packagePart(flatname);
+        PackageSymbol ps = syms.lookupPackage(msym, packageName);
+
+        Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname);
+
+        boolean absent = syms.getClass(ps.modle, flatname) == null;
+        ClassSymbol c = syms.enterClass(ps.modle, flatname);
+
         if (c.members_field == null) {
             try {
                 c.complete();
             } catch (CompletionFailure ex) {
-                if (absent) syms.classes.remove(flatname);
+                if (absent) syms.removeClass(ps.modle, flatname);
                 throw ex;
             }
         }
@@ -438,7 +454,7 @@
             ? p.package_info
             : (ClassSymbol) p.members_field.findFirst(classname);
         if (c == null) {
-            c = syms.enterClass(classname, p);
+            c = syms.enterClass(p.modle, classname, p);
             if (c.classfile == null) // only update the file if's it's newly created
                 c.classfile = file;
             if (isPkgInfo) {
@@ -479,6 +495,7 @@
     /**
      * specifies types of files to be read when filling in a package symbol
      */
+    // Note: overridden by JavadocClassFinder
     protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() {
         return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE);
     }
@@ -502,16 +519,83 @@
         if (p.members_field == null)
             p.members_field = WriteableScope.create(p);
 
-        preferCurrent = false;
-        if (userPathsFirst) {
+        ModuleSymbol msym = p.modle;
+
+        Assert.checkNonNull(msym, () -> p.toString());
+
+        msym.complete();
+
+        if (msym == syms.noModule) {
+            preferCurrent = false;
+            if (userPathsFirst) {
+                scanUserPaths(p);
+                preferCurrent = true;
+                scanPlatformPath(p);
+            } else {
+                scanPlatformPath(p);
+                scanUserPaths(p);
+            }
+        } else if (msym.classLocation == StandardLocation.CLASS_PATH) {
+            // assert p.modle.sourceLocation == StandardLocation.SOURCE_PATH);
             scanUserPaths(p);
-            preferCurrent = true;
-            scanPlatformPath(p);
         } else {
-            scanPlatformPath(p);
-            scanUserPaths(p);
+            scanModulePaths(p, msym);
         }
-        verbosePath = false;
+    }
+
+    // TODO: for now, this is a much simplified form of scanUserPaths
+    // and (deliberately) does not default sourcepath to classpath.
+    // But, we need to think about retaining existing behavior for
+    // -classpath and -sourcepath for single module mode.
+    // One plausible solution is to detect if the module's sourceLocation
+    // is the same as the module's classLocation.
+    private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException {
+        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();
+
+        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
+        classKinds.remove(JavaFileObject.Kind.SOURCE);
+        boolean wantClassFiles = !classKinds.isEmpty();
+
+        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
+        sourceKinds.remove(JavaFileObject.Kind.CLASS);
+        boolean wantSourceFiles = !sourceKinds.isEmpty();
+
+        String packageName = p.fullname.toString();
+
+        if (msym.name == moduleOverride) {
+            if (wantClassFiles) {
+                fillIn(p, CLASS_PATH,
+                       fileManager.list(CLASS_PATH,
+                                        packageName,
+                                        classKinds,
+                                        false));
+            }
+            if (wantSourceFiles && fileManager.hasLocation(SOURCE_PATH)) {
+                fillIn(p, SOURCE_PATH,
+                        fileManager.list(SOURCE_PATH,
+                                        packageName,
+                                        sourceKinds,
+                                        false));
+            }
+        }
+
+        Location classLocn = msym.classLocation;
+        Location sourceLocn = msym.sourceLocation;
+
+        if (wantClassFiles && (classLocn != null)) {
+            fillIn(p, classLocn,
+                   fileManager.list(classLocn,
+                                    packageName,
+                                    classKinds,
+                                    false));
+        }
+        if (wantSourceFiles && (sourceLocn != null)) {
+            fillIn(p, sourceLocn,
+                   fileManager.list(sourceLocn,
+                                    packageName,
+                                    sourceKinds,
+                                    false));
+        }
     }
 
     /**
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
new file mode 100644
index 0000000..9867b00
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.code;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.List;
+
+
+/**
+ *  Root class for the directives that may appear in module compilation units.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public abstract class Directive implements ModuleElement.Directive {
+
+    /** Flags for RequiresDirective. */
+    public enum RequiresFlag {
+        PUBLIC(0x0020),
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000),
+        EXTRA(0x10000);
+
+        // overkill? move to ClassWriter?
+        public static int value(Set<RequiresFlag> s) {
+            int v = 0;
+            for (RequiresFlag f: s)
+                v |= f.value;
+            return v;
+        }
+
+        RequiresFlag(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+    }
+
+    /**
+     * 'exports' Package ';'
+     */
+    public static class ExportsDirective extends Directive
+            implements ModuleElement.ExportsDirective {
+        public final PackageSymbol packge;
+        public final List<ModuleSymbol> modules;
+
+        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
+            this.packge = packge;
+            this.modules = modules;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.EXPORTS;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public PackageElement getPackage() {
+            return packge;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public java.util.List<? extends ModuleElement> getTargetModules() {
+            return Collections.unmodifiableList(modules);
+        }
+
+        @Override
+        public String toString() {
+            if (modules == null)
+                return "Exports[" + packge + "]";
+            else
+                return "Exports[" + packge + ":" + modules + "]";
+        }
+    }
+
+    /**
+     * 'provides' ServiceName 'with' QualifiedIdentifer ';'
+     */
+    public static class ProvidesDirective extends Directive
+            implements ModuleElement.ProvidesDirective {
+        public final ClassSymbol service;
+        public final ClassSymbol impl;
+
+        public ProvidesDirective(ClassSymbol service, ClassSymbol impl) {
+            this.service = service;
+            this.impl = impl;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.PROVIDES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getService() {
+            return service;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getImplementation() {
+            return impl;
+        }
+
+        @Override
+        public String toString() {
+            return "Provides[" + service + "," + impl + "]";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ProvidesDirective)) {
+                return false;
+            }
+            ProvidesDirective other = (ProvidesDirective)obj;
+            return service == other.service && impl == other.impl;
+        }
+
+        @Override
+        public int hashCode() {
+            return service.hashCode() * 31 + impl.hashCode() * 37;
+        }
+    }
+
+    /**
+     * 'requires' ['public'] ModuleName ';'
+     */
+    public static class RequiresDirective extends Directive
+            implements ModuleElement.RequiresDirective {
+        public final ModuleSymbol module;
+        public final Set<RequiresFlag> flags;
+
+        public RequiresDirective(ModuleSymbol module) {
+            this(module, EnumSet.noneOf(RequiresFlag.class));
+        }
+
+        public RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags) {
+            this.module = module;
+            this.flags = flags;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.REQUIRES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public boolean isPublic() {
+            return flags.contains(RequiresFlag.PUBLIC);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement getDependency() {
+            return module;
+        }
+
+        @Override
+        public String toString() {
+            return "Requires[" + flags + "," + module + "]";
+        }
+    }
+
+    /**
+     * 'uses' ServiceName ';'
+     */
+    public static class UsesDirective extends Directive
+            implements ModuleElement.UsesDirective {
+        public final ClassSymbol service;
+
+        public UsesDirective(ClassSymbol service) {
+            this.service = service;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.USES;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public TypeElement getService() {
+            return service;
+        }
+
+        @Override
+        public String toString() {
+            return "Uses[" + service + "]";
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof UsesDirective)) {
+                return false;
+            }
+            UsesDirective other = (UsesDirective)obj;
+            return service == other.service;
+        }
+
+        @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 02cf124..5aa826e 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
@@ -107,6 +107,7 @@
     public static final int ACC_SUPER    = 0x0020;
     public static final int ACC_BRIDGE   = 0x0040;
     public static final int ACC_VARARGS  = 0x0080;
+    public static final int ACC_MODULE   = 0x8000;
 
     /*****************************************
      * Internal compiler flags (no bits in the lower 16).
@@ -277,6 +278,21 @@
      */
     public static final long TYPE_TRANSLATED = 1L<<50;
 
+    /**
+     * Flag to indicate class symbol is for module-info
+     */
+    public static final long MODULE = 1L<<51;
+
+    /**
+     * Flag to indicate the given ModuleSymbol is an automatic module.
+     */
+    public static final long AUTOMATIC_MODULE = 1L<<52;
+
+    /**
+     * Flag to indicate the given ModuleSymbol is a system module.
+     */
+    public static final long SYSTEM_MODULE = 1L<<53;
+
     /** Modifier masks.
      */
     public static final int
@@ -385,7 +401,8 @@
         SIGNATURE_POLYMORPHIC(Flags.SIGNATURE_POLYMORPHIC),
         THROWS(Flags.THROWS),
         LAMBDA_METHOD(Flags.LAMBDA_METHOD),
-        TYPE_TRANSLATED(Flags.TYPE_TRANSLATED);
+        TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
+        MODULE(Flags.MODULE);
 
         Flag(long flag) {
             this.value = flag;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
index 263d0c5..e98a1a4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java
@@ -65,6 +65,7 @@
         VAR(Category.BASIC, KindName.VAR, KindSelector.VAR),
         MTH(Category.BASIC, KindName.METHOD, KindSelector.MTH),
         POLY(Category.BASIC, KindSelector.POLY),
+        MDL(Category.BASIC, KindSelector.MDL),
         ERR(Category.ERROR, KindSelector.ERR),
         AMBIGUOUS(Category.RESOLUTION_TARGET),                         // overloaded       target
         HIDDEN(Category.RESOLUTION_TARGET),                            // not overloaded   non-target
@@ -169,9 +170,10 @@
         public static final KindSelector VAR = new KindSelector(0x04);
         public static final KindSelector VAL = new KindSelector(0x0c);
         public static final KindSelector MTH = new KindSelector(0x10);
-        public static final KindSelector ERR = new KindSelector(0x3f);
         public static final KindSelector POLY = new KindSelector(0x20);
-        public static final KindSelector ASG = new KindSelector(0x44);
+        public static final KindSelector MDL = new KindSelector(0x40);
+        public static final KindSelector ERR = new KindSelector(0x7f);
+        public static final KindSelector ASG = new KindSelector(0x84);
 
         //common derived selectors
         public static final KindSelector TYP_PCK = of(TYP, PCK);
@@ -212,6 +214,7 @@
             if ((data & MTH.data) != 0) kinds.add(KindName.METHOD);
             if ((data & TYP.data) != 0) kinds.add(KindName.CLASS);
             if ((data & PCK.data) != 0) kinds.add(KindName.PACKAGE);
+            if ((data & MDL.data) != 0) kinds.add(KindName.MODULE);
             return kinds;
         }
     }
@@ -230,7 +233,8 @@
         CLASS("kindname.class"),
         STATIC_INIT("kindname.static.init"),
         INSTANCE_INIT("kindname.instance.init"),
-        PACKAGE("kindname.package");
+        PACKAGE("kindname.package"),
+        MODULE("kindname.module");
 
         private final String name;
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java
new file mode 100644
index 0000000..0c08c49
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ModuleFinder.java
@@ -0,0 +1,335 @@
+/*
+ * 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 com.sun.tools.javac.code;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Fragments;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.Fragment;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.StringUtils;
+
+import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+/**
+ *  This class provides operations to locate module definitions
+ *  from the source and class files on the paths provided to javac.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class ModuleFinder {
+    /** The context key for the module finder. */
+    protected static final Context.Key<ModuleFinder> moduleFinderKey = new Context.Key<>();
+
+    /** The log to use for verbose output. */
+    private final Log log;
+
+    /** The symbol table. */
+    private final Symtab syms;
+
+    /** The name table. */
+    private final Names names;
+
+    private final ClassFinder classFinder;
+
+    /** Access to files
+     */
+    private final JavaFileManager fileManager;
+
+    private final JCDiagnostic.Factory diags;
+
+    /** Get the ModuleFinder instance for this invocation. */
+    public static ModuleFinder instance(Context context) {
+        ModuleFinder instance = context.get(moduleFinderKey);
+        if (instance == null)
+            instance = new ModuleFinder(context);
+        return instance;
+    }
+
+    /** Construct a new module finder. */
+    protected ModuleFinder(Context context) {
+        context.put(moduleFinderKey, this);
+        names = Names.instance(context);
+        syms = Symtab.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        log = Log.instance(context);
+        classFinder = ClassFinder.instance(context);
+
+        diags = JCDiagnostic.Factory.instance(context);
+    }
+
+    class ModuleLocationIterator implements Iterator<Set<Location>> {
+        StandardLocation outer;
+        Set<Location> next = null;
+
+        Iterator<StandardLocation> outerIter = Arrays.asList(
+                StandardLocation.MODULE_SOURCE_PATH,
+                StandardLocation.UPGRADE_MODULE_PATH,
+                StandardLocation.SYSTEM_MODULES,
+                StandardLocation.MODULE_PATH
+        ).iterator();
+        Iterator<Set<Location>> innerIter = null;
+
+        @Override
+        public boolean hasNext() {
+            while (next == null) {
+                while (innerIter == null || !innerIter.hasNext()) {
+                    if (outerIter.hasNext()) {
+                        outer = outerIter.next();
+                        try {
+                            innerIter = fileManager.listModuleLocations(outer).iterator();
+                        } catch (IOException e) {
+                            System.err.println("error listing module locations for " + outer + ": " + e);  // FIXME
+                        }
+                    } else
+                        return false;
+                }
+
+                if (innerIter.hasNext())
+                    next = innerIter.next();
+            }
+            return true;
+        }
+
+        @Override
+        public Set<Location> next() {
+            hasNext();
+            if (next != null) {
+                Set<Location> result = next;
+                next = null;
+                return result;
+            }
+            throw new NoSuchElementException();
+        }
+
+    }
+
+    ModuleLocationIterator moduleLocationIterator = new ModuleLocationIterator();
+
+    public ModuleSymbol findModule(Name name) {
+        return findModule(syms.enterModule(name));
+    }
+
+    public ModuleSymbol findModule(ModuleSymbol msym) {
+        if (msym.kind != ERR && msym.sourceLocation == null && msym.classLocation == null) {
+            // fill in location
+            List<ModuleSymbol> list = scanModulePath(msym);
+            if (list.isEmpty()) {
+                msym.kind = ERR;
+            }
+        }
+        if (msym.kind != ERR && msym.module_info.sourcefile == null && msym.module_info.classfile == null) {
+            // fill in module-info
+            findModuleInfo(msym);
+        }
+        return msym;
+    }
+
+    public List<ModuleSymbol> findAllModules() {
+        List<ModuleSymbol> list = scanModulePath(null);
+        for (ModuleSymbol msym: list) {
+            if (msym.kind != ERR && msym.module_info.sourcefile == null && msym.module_info.classfile == null) {
+                // fill in module-info
+                findModuleInfo(msym);
+            }
+        }
+        return list;
+    }
+
+    public ModuleSymbol findSingleModule() {
+        try {
+            JavaFileObject src_fo = getModuleInfoFromLocation(StandardLocation.SOURCE_PATH, Kind.SOURCE);
+            JavaFileObject class_fo = getModuleInfoFromLocation(StandardLocation.CLASS_OUTPUT, Kind.CLASS);
+            JavaFileObject fo = (src_fo == null) ? class_fo
+                    : (class_fo == null) ? src_fo
+                            : classFinder.preferredFileObject(src_fo, class_fo);
+
+            ModuleSymbol msym;
+            if (fo == null) {
+                msym = syms.unnamedModule;
+            } else {
+                // Note: the following may trigger a re-entrant call to Modules.enter
+//                msym = new ModuleSymbol();
+//                ClassSymbol info = new ClassSymbol(Flags.MODULE, names.module_info, msym);
+//                info.modle = msym;
+//                info.classfile = fo;
+//                info.members_field = WriteableScope.create(info);
+//                msym.module_info = info;
+                msym = ModuleSymbol.create(null, names.module_info);
+                msym.module_info.classfile = fo;
+                msym.completer = sym -> classFinder.fillIn(msym.module_info);
+//                // TODO: should we do the following here, or as soon as we find the name in
+//                // the source or class file?
+//                // Consider the case when the class/source path module shadows one on the
+//                // module source path
+//                if (syms.modules.get(msym.name) != null) {
+//                    // error: module already defined
+//                    System.err.println("ERROR: module already defined: " + msym);
+//                } else {
+//                    syms.modules.put(msym.name, msym);
+//                }
+            }
+
+            msym.classLocation = StandardLocation.CLASS_OUTPUT;
+            return msym;
+
+        } catch (IOException e) {
+            throw new Error(e); // FIXME
+        }
+    }
+
+    private JavaFileObject getModuleInfoFromLocation(Location location, Kind kind) throws IOException {
+        if (!fileManager.hasLocation(location))
+            return null;
+
+        return fileManager.getJavaFileForInput(location,
+                                               names.module_info.toString(),
+                                               kind);
+    }
+
+    private List<ModuleSymbol> scanModulePath(ModuleSymbol toFind) {
+        ListBuffer<ModuleSymbol> results = new ListBuffer<>();
+        Map<Name, Location> namesInSet = new HashMap<>();
+        while (moduleLocationIterator.hasNext()) {
+            Set<Location> locns = (moduleLocationIterator.next());
+            namesInSet.clear();
+            for (Location l: locns) {
+                try {
+                    Name n = names.fromString(fileManager.inferModuleName(l));
+                    if (namesInSet.put(n, l) == null) {
+                        ModuleSymbol msym = syms.enterModule(n);
+                        if (msym.sourceLocation != null || msym.classLocation != null) {
+                            // module has already been found, so ignore this instance
+                            continue;
+                        }
+                        if (moduleLocationIterator.outer == StandardLocation.MODULE_SOURCE_PATH) {
+                            msym.sourceLocation = l;
+                            if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                                msym.classLocation = fileManager.getModuleLocation(StandardLocation.CLASS_OUTPUT, msym.name.toString());
+                            }
+                        } else {
+                            msym.classLocation = l;
+                        }
+                        if (moduleLocationIterator.outer == StandardLocation.SYSTEM_MODULES ||
+                            moduleLocationIterator.outer == StandardLocation.UPGRADE_MODULE_PATH) {
+                            msym.flags_field |= Flags.SYSTEM_MODULE;
+                        }
+                        if (toFind == msym || toFind == null) {
+                            // Note: cannot return msym directly, because we must finish
+                            // processing this set first
+                            results.add(msym);
+                        }
+                    } else {
+                        log.error(Errors.DuplicateModuleOnPath(
+                                getDescription(moduleLocationIterator.outer), n));
+                    }
+                } catch (IOException e) {
+                    // skip location for now?  log error?
+                }
+            }
+            if (toFind != null && results.nonEmpty())
+                return results.toList();
+        }
+
+        return results.toList();
+    }
+
+    private void findModuleInfo(ModuleSymbol msym) {
+        try {
+            JavaFileObject src_fo = (msym.sourceLocation == null) ? null
+                    : fileManager.getJavaFileForInput(msym.sourceLocation,
+                            names.module_info.toString(), Kind.SOURCE);
+
+            JavaFileObject class_fo = (msym.classLocation == null) ? null
+                    : fileManager.getJavaFileForInput(msym.classLocation,
+                            names.module_info.toString(), Kind.CLASS);
+
+            JavaFileObject fo = (src_fo == null) ? class_fo :
+                    (class_fo == null) ? src_fo :
+                    classFinder.preferredFileObject(src_fo, class_fo);
+
+            if (fo == null) {
+                String moduleName = msym.sourceLocation == null && msym.classLocation != null ?
+                    fileManager.inferModuleName(msym.classLocation) : null;
+                if (moduleName != null) {
+                    msym.module_info.classfile = null;
+                    msym.flags_field |= Flags.AUTOMATIC_MODULE;
+                } else {
+                    msym.kind = ERR;
+                }
+            } else {
+                msym.module_info.classfile = fo;
+                msym.module_info.completer = new Symbol.Completer() {
+                    @Override
+                    public void complete(Symbol sym) throws CompletionFailure {
+                        classFinder.fillIn(msym.module_info);
+                    }
+                    @Override
+                    public String toString() {
+                        return "ModuleInfoCompleter";
+                    }
+                };
+            }
+        } catch (IOException e) {
+            msym.kind = ERR;
+        }
+    }
+
+    Fragment getDescription(StandardLocation l) {
+        switch (l) {
+            case MODULE_PATH: return Fragments.LocnModule_path;
+            case MODULE_SOURCE_PATH: return Fragments.LocnModule_source_path;
+            case SYSTEM_MODULES: return Fragments.LocnSystem_modules;
+            case UPGRADE_MODULE_PATH: return Fragments.LocnUpgrade_module_path;
+            default:
+                throw new AssertionError();
+        }
+    }
+
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
index 8971e6c..138432b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -152,14 +152,14 @@
         if (seenCaptured.contains(t))
             return printAnnotations(t) +
                 localize(locale, "compiler.misc.type.captureof.1",
-                         capturedVarId(t, locale));
+                capturedVarId(t, locale));
         else {
             try {
                 seenCaptured = seenCaptured.prepend(t);
                 return printAnnotations(t) +
                     localize(locale, "compiler.misc.type.captureof",
-                             capturedVarId(t, locale),
-                             visit(t.wildcard, locale));
+                    capturedVarId(t, locale),
+                    visit(t.wildcard, locale));
             }
             finally {
                 seenCaptured = seenCaptured.tail;
@@ -274,6 +274,11 @@
         return visitType(t, locale);
     }
 
+    @Override
+    public String visitModuleType(ModuleType t, Locale locale) {
+        return visitType(t, locale);
+    }
+
     public String visitType(Type t, Locale locale) {
         String s = (t.tsym == null || t.tsym.name == null)
                 ? localize(locale, "compiler.misc.type.none")
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
index 6870123..aac3e76 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
@@ -137,6 +137,9 @@
     public boolean allowImprovedCatchAnalysis() {
         return compareTo(JDK1_7) >= 0;
     }
+    public boolean allowModules() {
+        return compareTo(JDK1_9) >= 0;
+    }
     public boolean allowTryWithResources() {
         return compareTo(JDK1_7) >= 0;
     }
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 428a30a..c6957ff4 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
@@ -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,16 +27,26 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
+import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
-import javax.lang.model.element.*;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 
-import com.sun.tools.javac.code.Attribute.Compound;
-import com.sun.tools.javac.code.TypeAnnotations.AnnotationType;
-import com.sun.tools.javac.code.TypeMetadata.Entry;
-import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
+import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Type.*;
@@ -48,6 +58,7 @@
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.Name;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -843,7 +854,7 @@
             boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
                 return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
                         anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
-                       anno.position.parameter_index == index;
+                        anno.position.parameter_index == index;
             }
 
 
@@ -852,6 +863,122 @@
             return v.visitTypeParameter(this, p);
         }
     }
+    /** A class for module symbols.
+     */
+    public static class ModuleSymbol extends TypeSymbol
+            implements ModuleElement {
+
+        public Name version;
+        public JavaFileManager.Location sourceLocation;
+        public JavaFileManager.Location classLocation;
+
+        /** All directives, in natural order. */
+        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.ProvidesDirective> provides;
+        public List<com.sun.tools.javac.code.Directive.UsesDirective> uses;
+
+        public ClassSymbol module_info;
+
+        public PackageSymbol unnamedPackage;
+        public Map<Name, PackageSymbol> visiblePackages;
+        public List<Symbol> enclosedPackages = List.nil();
+
+        public Completer usesProvidesCompleter = Completer.NULL_COMPLETER;
+
+        /**
+         * Create a ModuleSymbol with an associated module-info ClassSymbol.
+         * The name of the module may be null, if it is not known yet.
+         */
+        public static ModuleSymbol create(Name name, Name module_info) {
+            ModuleSymbol msym = new ModuleSymbol(name, null);
+            ClassSymbol info = new ClassSymbol(Flags.MODULE, module_info, msym);
+            info.fullname = formFullName(module_info, msym);
+            info.flatname = info.fullname;
+            info.members_field = WriteableScope.create(info);
+            msym.module_info = info;
+            return msym;
+        }
+
+        public ModuleSymbol() {
+            super(MDL, 0, null, null, null);
+            this.type = new ModuleType(this);
+        }
+
+        public ModuleSymbol(Name name, Symbol owner) {
+            super(MDL, 0, name, null, owner);
+            this.type = new ModuleType(this);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public boolean isUnnamed() {
+            return name.isEmpty() && owner == null;
+        }
+
+        public boolean isNoModule() {
+            return false;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ElementKind getKind() {
+            return ElementKind.MODULE;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public java.util.List<Directive> getDirectives() {
+            completeUsesProvides();
+            return Collections.unmodifiableList(directives);
+        }
+
+        public void completeUsesProvides() {
+            if (usesProvidesCompleter != Completer.NULL_COMPLETER) {
+                Completer c = usesProvidesCompleter;
+                usesProvidesCompleter = Completer.NULL_COMPLETER;
+                c.complete(this);
+            }
+        }
+
+        @Override
+        public ClassSymbol outermostClass() {
+            return null;
+        }
+
+        @Override
+        public String toString() {
+            // TODO: the following strings should be localized
+            // Do this with custom anon subtypes in Symtab
+            String n = (name == null) ? "<unknown>"
+                    : (name.isEmpty()) ? "<unnamed>"
+                    : String.valueOf(name);
+            return n;
+        }
+
+        @Override
+        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+            return v.visitModule(this, p);
+        }
+
+        @Override
+        public List<Symbol> getEnclosedElements() {
+            List<Symbol> list = List.nil();
+            for (Symbol sym : enclosedPackages) {
+                if (sym.members().anyMatch(m -> m.kind == TYP))
+                    list = list.prepend(sym);
+            }
+            return list;
+        }
+
+        public void reset() {
+            this.directives = null;
+            this.requires = null;
+            this.exports = null;
+            this.provides = null;
+            this.uses = null;
+            this.visiblePackages = null;
+        }
+
+    }
 
     /** A class for package symbols
      */
@@ -861,6 +988,7 @@
         public WriteableScope members_field;
         public Name fullname;
         public ClassSymbol package_info; // see bug 6443073
+        public ModuleSymbol modle;
 
         public PackageSymbol(Name name, Type type, Symbol owner) {
             super(PCK, 0, name, type, owner);
@@ -929,7 +1057,7 @@
 
         @DefinedBy(Api.LANGUAGE_MODEL)
         public Symbol getEnclosingElement() {
-            return null;
+            return modle != null && !modle.isNoModule() ? modle : null;
         }
 
         @DefinedBy(Api.LANGUAGE_MODEL)
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
index 68e36be..d0b75a8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.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
@@ -25,18 +25,20 @@
 
 package com.sun.tools.javac.code;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import javax.lang.model.element.ElementVisitor;
-import javax.tools.JavaFileObject;
-
 
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 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.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
@@ -47,17 +49,18 @@
 import com.sun.tools.javac.code.Type.JCVoidType;
 import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Type.UnknownType;
-import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Iterators;
 import com.sun.tools.javac.util.JavacMessages;
 import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Log;
 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.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -100,17 +103,26 @@
     public final JCVoidType voidType = new JCVoidType();
 
     private final Names names;
+    private final JavacMessages messages;
     private final Completer initialCompleter;
-    private final Target target;
+    private final Completer moduleCompleter;
+
+    /** A symbol for the unnamed module.
+     */
+    public final ModuleSymbol unnamedModule;
+
+    /** The error module.
+     */
+    public final ModuleSymbol errModule;
+
+    /** A symbol for no module, for use with -source 8 or less
+     */
+    public final ModuleSymbol noModule;
 
     /** A symbol for the root package.
      */
     public final PackageSymbol rootPackage;
 
-    /** A symbol for the unnamed package.
-     */
-    public final PackageSymbol unnamedPackage;
-
     /** A symbol that stands for a missing symbol.
      */
     public final TypeSymbol noSymbol;
@@ -139,6 +151,10 @@
     /** The builtin type of all methods. */
     public final ClassSymbol methodClass;
 
+    /** A symbol for the java.base module.
+     */
+    public final ModuleSymbol java_base;
+
     /** Predefined types.
      */
     public final Type objectType;
@@ -208,7 +224,7 @@
      */
     public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()];
 
-    /** The name of the class that belongs to a basix type tag.
+    /** The name of the class that belongs to a basic type tag.
      */
     public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()];
 
@@ -217,13 +233,17 @@
      *  It should be updated from the outside to reflect classes defined
      *  by compiled source files.
      */
-    public final Map<Name, ClassSymbol> classes = new HashMap<>();
+    private final Map<Name, Map<ModuleSymbol,ClassSymbol>> classes = new HashMap<>();
 
     /** A hashtable containing the encountered packages.
      *  the table should be updated from outside to reflect packages defined
      *  by compiled source files.
      */
-    public final Map<Name, PackageSymbol> packages = new HashMap<>();
+    private final Map<Name, Map<ModuleSymbol,PackageSymbol>> packages = new HashMap<>();
+
+    /** A hashtable giving the encountered modules.
+     */
+    private final Map<Name, ModuleSymbol> modules = new LinkedHashMap<>();
 
     public void initType(Type type, ClassSymbol c) {
         type.tsym = c;
@@ -239,7 +259,7 @@
 
     public void initType(Type type, String name, String bname) {
         initType(type, name);
-            boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
+        boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
     }
 
     /** The class symbol that owns all predefined symbols.
@@ -250,12 +270,13 @@
      *  @param s The name of the class.
      */
     private Type enterClass(String s) {
-        return enterClass(names.fromString(s)).type;
+        return enterClass(java_base, names.fromString(s)).type;
     }
 
     public void synthesizeEmptyInterfaceIfMissing(final Type type) {
         final Completer completer = type.tsym.completer;
         type.tsym.completer = new Completer() {
+            @Override
             public void complete(Symbol sym) throws CompletionFailure {
                 try {
                     completer.complete(sym);
@@ -273,9 +294,10 @@
     }
 
     public void synthesizeBoxTypeIfMissing(final Type type) {
-        ClassSymbol sym = enterClass(boxedName[type.getTag().ordinal()]);
+        ClassSymbol sym = enterClass(java_base, boxedName[type.getTag().ordinal()]);
         final Completer completer = sym.completer;
         sym.completer = new Completer() {
+            @Override
             public void complete(Symbol sym) throws CompletionFailure {
                 try {
                     completer.complete(sym);
@@ -308,7 +330,9 @@
     // Enter a synthetic class that is used to mark classes in ct.sym.
     // This class does not have a class file.
     private Type enterSyntheticAnnotation(String name) {
-        ClassType type = (ClassType)enterClass(name);
+        // for now, leave the module null, to prevent problems from synthesizing the
+        // existence of a class in any specific module, including noModule
+        ClassType type = (ClassType)enterClass(java_base, names.fromString(name)).type;
         ClassSymbol sym = (ClassSymbol)type.tsym;
         sym.completer = Completer.NULL_COMPLETER;
         sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE;
@@ -328,22 +352,35 @@
         context.put(symtabKey, this);
 
         names = Names.instance(context);
-        target = Target.instance(context);
 
         // Create the unknown type
         unknownType = new UnknownType();
 
-        // create the basic builtin symbols
+        messages = JavacMessages.instance(context);
+
         rootPackage = new PackageSymbol(names.empty, null);
-        packages.put(names.empty, rootPackage);
-        final JavacMessages messages = JavacMessages.instance(context);
-        unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
+
+        // create the basic builtin symbols
+        unnamedModule = new ModuleSymbol(names.empty, null) {
+                @Override
                 public String toString() {
-                    return messages.getLocalizedString("compiler.misc.unnamed.package");
+                    return messages.getLocalizedString("compiler.misc.unnamed.module");
                 }
             };
+        addRootPackageFor(unnamedModule);
+
+        errModule = new ModuleSymbol(names.empty, null) { };
+        addRootPackageFor(errModule);
+
+        noModule = new ModuleSymbol(names.empty, null) {
+            @Override public boolean isNoModule() {
+                return true;
+            }
+        };
+        addRootPackageFor(noModule);
+
         noSymbol = new TypeSymbol(NIL, 0, names.empty, Type.noType, rootPackage) {
-            @DefinedBy(Api.LANGUAGE_MODEL)
+            @Override @DefinedBy(Api.LANGUAGE_MODEL)
             public <R, P> R accept(ElementVisitor<R, P> v, P p) {
                 return v.visitUnknown(this, p);
             }
@@ -389,8 +426,7 @@
 
         // Get the initial completer for Symbols from the ClassFinder
         initialCompleter = ClassFinder.instance(context).getCompleter();
-        rootPackage.completer = initialCompleter;
-        unnamedPackage.completer = initialCompleter;
+        rootPackage.members_field = WriteableScope.create(rootPackage);
 
         // Enter symbols for basic types.
         scope.enter(byteType.tsym);
@@ -406,9 +442,22 @@
         // Enter symbol for the errSymbol
         scope.enter(errSymbol);
 
-        classes.put(predefClass.fullname, predefClass);
+        Source source = Source.instance(context);
+        Options options = Options.instance(context);
+        boolean noModules = options.isSet("noModules");
+        if (source.allowModules() && !noModules) {
+            java_base = enterModule(names.java_base);
+            //avoid completing java.base during the Symtab initialization
+            java_base.completer = Completer.NULL_COMPLETER;
+            java_base.visiblePackages = Collections.emptyMap();
+        } else {
+            java_base = noModule;
+        }
 
-        // Enter predefined classes.
+        // Get the initial completer for ModuleSymbols from Modules
+        moduleCompleter = Modules.instance(context).getCompleter();
+
+        // Enter predefined classes. All are assumed to be in the java.base module.
         objectType = enterClass("java.lang.Object");
         objectsType = enterClass("java.util.Objects");
         classType = enterClass("java.lang.Class");
@@ -434,7 +483,7 @@
         cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException");
         annotationType = enterClass("java.lang.annotation.Annotation");
         classLoaderType = enterClass("java.lang.ClassLoader");
-        enumSym = enterClass(names.java_lang_Enum);
+        enumSym = enterClass(java_base, names.java_lang_Enum);
         enumFinalFinalize =
             new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL,
                              names.finalize,
@@ -512,14 +561,16 @@
                            List.<Type>nil(), methodClass),
             arrayClass);
         arrayClass.members().enter(arrayCloneMethod);
+
+        if (java_base != noModule)
+            java_base.completer = sym -> moduleCompleter.complete(sym); //bootstrap issues
+
     }
 
     /** Define a new class given its name and owner.
      */
     public ClassSymbol defineClass(Name name, Symbol owner) {
         ClassSymbol c = new ClassSymbol(0, name, owner);
-        if (owner.kind == PCK)
-            Assert.checkNull(classes.get(c.flatname), c);
         c.completer = initialCompleter;
         return c;
     }
@@ -527,12 +578,13 @@
     /** Create a new toplevel or member class symbol with given name
      *  and owner and enter in `classes' unless already there.
      */
-    public ClassSymbol enterClass(Name name, TypeSymbol owner) {
+    public ClassSymbol enterClass(ModuleSymbol msym, Name name, TypeSymbol owner) {
+        Assert.checkNonNull(msym);
         Name flatname = TypeSymbol.formFlatName(name, owner);
-        ClassSymbol c = classes.get(flatname);
+        ClassSymbol c = getClass(msym, flatname);
         if (c == null) {
             c = defineClass(name, owner);
-            classes.put(flatname, c);
+            doEnterClass(msym, c);
         } else if ((c.name != name || c.owner != owner) && owner.kind == TYP && c.owner.kind == PCK) {
             // reassign fields of classes that might have been loaded with
             // their flat names.
@@ -544,71 +596,212 @@
         return c;
     }
 
-    /**
-     * Creates a new toplevel class symbol with given flat name and
-     * given class (or source) file.
-     *
-     * @param flatName a fully qualified binary class name
-     * @param classFile the class file or compilation unit defining
-     * the class (may be {@code null})
-     * @return a newly created class symbol
-     * @throws AssertionError if the class symbol already exists
-     */
-    public ClassSymbol enterClass(Name flatName, JavaFileObject classFile) {
-        ClassSymbol cs = classes.get(flatName);
-        if (cs != null) {
-            String msg = Log.format("%s: completer = %s; class file = %s; source file = %s",
-                                    cs.fullname,
-                                    cs.completer,
-                                    cs.classfile,
-                                    cs.sourcefile);
-            throw new AssertionError(msg);
+    public ClassSymbol getClass(ModuleSymbol msym, Name flatName) {
+        Assert.checkNonNull(msym, () -> flatName.toString());
+        return classes.getOrDefault(flatName, Collections.emptyMap()).get(msym);
+    }
+
+    public PackageSymbol lookupPackage(ModuleSymbol msym, Name flatName) {
+        Assert.checkNonNull(msym);
+
+        if (flatName.isEmpty()) {
+            //unnamed packages only from the current module - visiblePackages contains *root* package, not unnamed package!
+            return msym.unnamedPackage;
         }
-        Name packageName = Convert.packagePart(flatName);
-        PackageSymbol owner = packageName.isEmpty()
-                                ? unnamedPackage
-                                : enterPackage(packageName);
-        cs = defineClass(Convert.shortName(flatName), owner);
-        cs.classfile = classFile;
-        classes.put(flatName, cs);
-        return cs;
+
+        if (msym == noModule) {
+            return enterPackage(msym, flatName);
+        }
+
+        msym.complete();
+
+        PackageSymbol pack;
+
+        pack = msym.visiblePackages.get(flatName);
+
+        if (pack != null)
+            return pack;
+
+        pack = getPackage(msym, flatName);
+
+        if (pack != null && pack.exists())
+            return pack;
+
+        boolean dependsOnUnnamed = msym.requires != null &&
+                                   msym.requires.stream()
+                                                .map(rd -> rd.module)
+                                                .anyMatch(mod -> mod == unnamedModule);
+
+        if (dependsOnUnnamed) {
+            //msyms depends on the unnamed module, for which we generally don't know
+            //the list of packages it "exports" ahead of time. So try to lookup the package in the
+            //current module, and in the unnamed module and see if it exists in one of them
+            PackageSymbol unnamedPack = getPackage(unnamedModule, flatName);
+
+            if (unnamedPack != null && unnamedPack.exists()) {
+                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
+                return unnamedPack;
+            }
+
+            pack = enterPackage(msym, flatName);
+            pack.complete();
+            if (pack.exists())
+                return pack;
+
+            unnamedPack = enterPackage(unnamedModule, flatName);
+            unnamedPack.complete();
+            if (unnamedPack.exists()) {
+                msym.visiblePackages.put(unnamedPack.fullname, unnamedPack);
+                return unnamedPack;
+            }
+
+            return pack;
+        }
+
+        return enterPackage(msym, flatName);
+    }
+
+    private static final Map<ModuleSymbol, ClassSymbol> EMPTY = new HashMap<>();
+
+    public void removeClass(ModuleSymbol msym, Name flatName) {
+        classes.getOrDefault(flatName, EMPTY).remove(msym);
+    }
+
+    public Iterable<ClassSymbol> getAllClasses() {
+        return () -> Iterators.createCompoundIterator(classes.values(), v -> v.values().iterator());
+    }
+
+    private void doEnterClass(ModuleSymbol msym, ClassSymbol cs) {
+        classes.computeIfAbsent(cs.flatname, n -> new HashMap<>()).put(msym, cs);
     }
 
     /** Create a new member or toplevel class symbol with given flat name
      *  and enter in `classes' unless already there.
      */
-    public ClassSymbol enterClass(Name flatname) {
-        ClassSymbol c = classes.get(flatname);
-        if (c == null)
-            return enterClass(flatname, (JavaFileObject)null);
-        else
+    public ClassSymbol enterClass(ModuleSymbol msym, Name flatname) {
+        Assert.checkNonNull(msym);
+        PackageSymbol ps = lookupPackage(msym, Convert.packagePart(flatname));
+        Assert.checkNonNull(ps);
+        Assert.checkNonNull(ps.modle);
+        ClassSymbol c = getClass(ps.modle, flatname);
+        if (c == null) {
+            c = defineClass(Convert.shortName(flatname), ps);
+            doEnterClass(ps.modle, c);
+            return c;
+        } else
             return c;
     }
 
     /** Check to see if a package exists, given its fully qualified name.
      */
-    public boolean packageExists(Name fullname) {
-        return enterPackage(fullname).exists();
+    public boolean packageExists(ModuleSymbol msym, Name fullname) {
+        Assert.checkNonNull(msym);
+        return enterPackage(msym, fullname).exists();
     }
 
     /** Make a package, given its fully qualified name.
      */
-    public PackageSymbol enterPackage(Name fullname) {
-        PackageSymbol p = packages.get(fullname);
+    public PackageSymbol enterPackage(ModuleSymbol currModule, Name fullname) {
+        Assert.checkNonNull(currModule);
+        PackageSymbol p = getPackage(currModule, fullname);
         if (p == null) {
-            Assert.check(!fullname.isEmpty(), "rootPackage missing!");
+            Assert.check(!fullname.isEmpty(), () -> "rootPackage missing!; currModule: " + currModule);
             p = new PackageSymbol(
-                Convert.shortName(fullname),
-                enterPackage(Convert.packagePart(fullname)));
+                    Convert.shortName(fullname),
+                    enterPackage(currModule, Convert.packagePart(fullname)));
             p.completer = initialCompleter;
-            packages.put(fullname, p);
+            p.modle = currModule;
+            doEnterPackage(currModule, p);
         }
         return p;
     }
 
-    /** Make a package, given its unqualified name and enclosing package.
-     */
-    public PackageSymbol enterPackage(Name name, PackageSymbol owner) {
-        return enterPackage(TypeSymbol.formFullName(name, owner));
+    private void doEnterPackage(ModuleSymbol msym, PackageSymbol pack) {
+        packages.computeIfAbsent(pack.fullname, n -> new HashMap<>()).put(msym, pack);
+        msym.enclosedPackages = msym.enclosedPackages.prepend(pack);
+    }
+
+    private void addRootPackageFor(ModuleSymbol module) {
+        doEnterPackage(module, rootPackage);
+        PackageSymbol unnamedPackage = new PackageSymbol(names.empty, rootPackage) {
+                @Override
+                public String toString() {
+                    return messages.getLocalizedString("compiler.misc.unnamed.package");
+                }
+            };
+        unnamedPackage.modle = module;
+        unnamedPackage.completer = sym -> initialCompleter.complete(sym);
+        module.unnamedPackage = unnamedPackage;
+    }
+
+    public PackageSymbol getPackage(ModuleSymbol module, Name fullname) {
+        return packages.getOrDefault(fullname, Collections.emptyMap()).get(module);
+    }
+
+    public ModuleSymbol enterModule(Name name) {
+        ModuleSymbol msym = modules.get(name);
+        if (msym == null) {
+            msym = ModuleSymbol.create(name, names.module_info);
+            addRootPackageFor(msym);
+            msym.completer = sym -> moduleCompleter.complete(sym); //bootstrap issues
+            modules.put(name, msym);
+        }
+        return msym;
+    }
+
+    public void enterModule(ModuleSymbol msym, Name name) {
+        Assert.checkNull(modules.get(name));
+        Assert.checkNull(msym.name);
+        msym.name = name;
+        addRootPackageFor(msym);
+        ClassSymbol info = msym.module_info;
+        info.fullname = msym.name.append('.', names.module_info);
+        info.flatname = info.fullname;
+        modules.put(name, msym);
+    }
+
+    public ModuleSymbol getModule(Name name) {
+        return modules.get(name);
+    }
+
+    //temporary:
+    public ModuleSymbol inferModule(Name packageName) {
+        if (packageName.isEmpty())
+            return java_base == noModule ? noModule : unnamedModule;//!
+
+        ModuleSymbol msym = null;
+        Map<ModuleSymbol,PackageSymbol> map = packages.get(packageName);
+        if (map == null)
+            return null;
+        for (Map.Entry<ModuleSymbol,PackageSymbol> e: map.entrySet()) {
+            if (!e.getValue().members().isEmpty()) {
+                if (msym == null) {
+                    msym = e.getKey();
+                } else {
+                    return null;
+                }
+            }
+        }
+        return msym;
+    }
+
+    public List<ModuleSymbol> listPackageModules(Name packageName) {
+        if (packageName.isEmpty())
+            return List.nil();
+
+        List<ModuleSymbol> result = List.nil();
+        Map<ModuleSymbol,PackageSymbol> map = packages.get(packageName);
+        if (map != null) {
+            for (Map.Entry<ModuleSymbol, PackageSymbol> e: map.entrySet()) {
+                if (!e.getValue().members().isEmpty()) {
+                    result = result.prepend(e.getKey());
+                }
+            }
+        }
+        return result;
+    }
+
+    public Collection<ModuleSymbol> getAllModules() {
+        return modules.values();
     }
 }
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 8609c0d..666051f 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
@@ -1525,7 +1525,7 @@
 
     public static class PackageType extends Type implements NoType {
 
-        PackageType(TypeSymbol tsym) {
+        PackageType(PackageSymbol tsym) {
             // Package types cannot be annotated
             super(tsym, TypeMetadata.EMPTY);
         }
@@ -1561,6 +1561,49 @@
         }
     }
 
+    public static class ModuleType extends Type implements NoType {
+
+        ModuleType(ModuleSymbol tsym) {
+            // Module types cannot be annotated
+            super(tsym, TypeMetadata.EMPTY);
+        }
+
+        @Override
+        public ModuleType cloneWithMetadata(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a module type");
+        }
+
+        @Override
+        public ModuleType annotatedType(List<Attribute.TypeCompound> annos) {
+            throw new AssertionError("Cannot annotate a module type");
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return TypeTag.MODULE;
+        }
+
+        @Override
+        public <R,S> R accept(Type.Visitor<R,S> v, S s) {
+            return v.visitModuleType(this, s);
+        }
+
+        @Override
+        public String toString() {
+            return tsym.getQualifiedName().toString();
+        }
+
+        @Override
+        public TypeKind getKind() {
+            return TypeKind.MODULE;
+        }
+
+        @Override
+        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+            return v.visitNoType(this, p);
+        }
+    }
+
     public static class TypeVar extends Type implements TypeVariable {
 
         /** The upper bound of this type variable; set from outside.
@@ -2384,6 +2427,7 @@
         R visitArrayType(ArrayType t, S s);
         R visitMethodType(MethodType t, S s);
         R visitPackageType(PackageType t, S s);
+        R visitModuleType(ModuleType t, S s);
         R visitTypeVar(TypeVar t, S s);
         R visitCapturedType(CapturedType t, S s);
         R visitForAll(ForAll t, S s);
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 40a0a51..42cdaec 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
@@ -49,6 +49,7 @@
 import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Type.ModuleType;
 import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Attr;
@@ -652,6 +653,11 @@
                 }
 
                 @Override
+                public Type visitModuleType(ModuleType t, List<TypeCompound> s) {
+                    return t.annotatedType(s);
+                }
+
+                @Override
                 public Type visitCapturedType(CapturedType t, List<TypeCompound> s) {
                     return t.annotatedType(s);
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
index 418f1e1..e9ea368 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -89,6 +89,10 @@
      */
     PACKAGE,
 
+    /** The tag of all module "types".
+     */
+    MODULE,
+
     /** The tag of all (source-level) type variables.
      */
     TYPEVAR,
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
index 33029b4..8400fc7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
@@ -3938,7 +3938,7 @@
      * Return the class that boxes the given primitive.
      */
     public ClassSymbol boxedClass(Type t) {
-        return syms.enterClass(syms.boxedName[t.getTag().ordinal()]);
+        return syms.enterClass(syms.java_base, syms.boxedName[t.getTag().ordinal()]);
     }
 
     /**
@@ -3957,7 +3957,7 @@
         for (int i=0; i<syms.boxedName.length; i++) {
             Name box = syms.boxedName[i];
             if (box != null &&
-                asSuper(t, syms.enterClass(box)) != null)
+                asSuper(t, syms.enterClass(syms.java_base, box)) != null)
                 return syms.typeOfTag[i];
         }
         return Type.noType;
@@ -4536,6 +4536,7 @@
         public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
         public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
         public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
+        public R visitModuleType(ModuleType t, S s)     { return visitType(t, s); }
         public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
         public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
         public R visitForAll(ForAll t, S s)             { return visitType(t, s); }
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 efa57d8..60c77fc 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
@@ -36,6 +36,7 @@
 import com.sun.source.tree.TreeVisitor;
 import com.sun.source.util.SimpleTreeVisitor;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -60,6 +61,7 @@
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
 import com.sun.tools.javac.util.List;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
 import static com.sun.tools.javac.code.Flags.BLOCK;
@@ -332,7 +334,15 @@
                                            syms.errSymbol.name,
                                            null, null, null, null);
         localEnv.enclClass.sym = syms.errSymbol;
-        return tree.accept(identAttributer, localEnv);
+        return attribIdent(tree, localEnv);
+    }
+
+    /** Attribute a parsed identifier.
+     * @param tree Parsed identifier name
+     * @param env The env to use
+     */
+    public Symbol attribIdent(JCTree tree, Env<AttrContext> env) {
+        return tree.accept(identAttributer, env);
     }
     // where
         private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer();
@@ -4238,13 +4248,19 @@
     }
 
     /**
-     * Attribute an env for either a top level tree or class declaration.
+     * Attribute an env for either a top level tree or class or module declaration.
      */
     public void attrib(Env<AttrContext> env) {
-        if (env.tree.hasTag(TOPLEVEL))
-            attribTopLevel(env);
-        else
-            attribClass(env.tree.pos(), env.enclClass.sym);
+        switch (env.tree.getTag()) {
+            case MODULEDEF:
+                attribModule(env.tree.pos(), ((JCModuleDecl)env.tree).sym);
+                break;
+            case TOPLEVEL:
+                attribTopLevel(env);
+                break;
+            default:
+                attribClass(env.tree.pos(), env.enclClass.sym);
+        }
     }
 
     /**
@@ -4260,6 +4276,21 @@
         }
     }
 
+    public void attribModule(DiagnosticPosition pos, ModuleSymbol m) {
+        try {
+            annotate.flush();
+            attribModule(m);
+        } catch (CompletionFailure ex) {
+            chk.completionError(pos, ex);
+        }
+    }
+
+    void attribModule(ModuleSymbol m) {
+        // Get environment current at the point of module definition.
+        Env<AttrContext> env = enter.typeEnvs.get(m);
+        attribStat(env.tree, env);
+    }
+
     /** Main method: attribute class definition associated with given class symbol.
      *  reporting completion failures at the given position.
      *  @param pos The source position at which completion errors are to be
@@ -4358,6 +4389,10 @@
         // nothing to do
     }
 
+    public void visitModuleDef(JCModuleDecl tree) {
+        tree.sym.completeUsesProvides();
+    }
+
     /** Finish the attribution of a class. */
     private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
         JCClassDecl tree = (JCClassDecl)env.tree;
@@ -4929,4 +4964,22 @@
         }
     }
     // </editor-fold>
+
+    public void setPackageSymbols(JCExpression pid, Symbol pkg) {
+        new TreeScanner() {
+            Symbol packge = pkg;
+            @Override
+            public void visitIdent(JCIdent that) {
+                that.sym = packge;
+            }
+
+            @Override
+            public void visitSelect(JCFieldAccess that) {
+                that.sym = packge;
+                packge = packge.owner;
+                super.visitSelect(that);
+            }
+        }.scan(pid);
+    }
+
 }
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 4b0b3a1..894f73a 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
@@ -173,10 +173,10 @@
      */
     char syntheticNameChar;
 
-    /** A table mapping flat names of all compiled classes in this run to their
-     *  symbols; maintained from outside.
+    /** A table mapping flat names of all compiled classes for each module in this run
+     *  to their symbols; maintained from outside.
      */
-    public Map<Name,ClassSymbol> compiled = new HashMap<>();
+    private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
 
     /** A handler for messages about deprecated usage.
      */
@@ -404,7 +404,7 @@
         for (int i = (index == null) ? 1 : index; ; i++) {
             Name flatname = names.fromString(enclFlatnameStr
                     + syntheticNameChar + i + c.name);
-            if (compiled.get(flatname) == null) {
+            if (getCompiled(c.packge().modle, flatname) == null) {
                 localClassNameIndexes.put(key, i + 1);
                 return flatname;
             }
@@ -421,6 +421,22 @@
         localClassNameIndexes.clear();
     }
 
+    public void putCompiled(ClassSymbol csym) {
+        compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
+    }
+
+    public ClassSymbol getCompiled(ClassSymbol csym) {
+        return compiled.get(Pair.of(csym.packge().modle, csym.flatname));
+    }
+
+    public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) {
+        return compiled.get(Pair.of(msym, flatname));
+    }
+
+    public void removeCompiled(ClassSymbol csym) {
+        compiled.remove(Pair.of(csym.packge().modle, csym.flatname));
+    }
+
 /* *************************************************************************
  * Type Checking
  **************************************************************************/
@@ -3473,7 +3489,7 @@
         private boolean isCanonical(JCTree tree) {
             while (tree.hasTag(SELECT)) {
                 JCFieldAccess s = (JCFieldAccess) tree;
-                if (s.sym.owner != TreeInfo.symbol(s.selected))
+                if (s.sym.owner.name != TreeInfo.symbol(s.selected).name)
                     return false;
                 tree = s.selected;
             }
@@ -3576,9 +3592,19 @@
 
     // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2)
     public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) {
-        for (JCImport imp : toplevel.getImports()) {
+        OUTER: for (JCImport imp : toplevel.getImports()) {
             if (!imp.staticImport && TreeInfo.name(imp.qualid) == names.asterisk) {
                 TypeSymbol tsym = ((JCFieldAccess)imp.qualid).selected.type.tsym;
+                if (toplevel.modle.visiblePackages != null) {
+                    //TODO - unclear: selects like javax.* will get resolved from the current module
+                    //(as javax is not an exported package from any module). And as javax in the current
+                    //module typically does not contain any classes or subpackages, we need to go through
+                    //the visible packages to find a sub-package:
+                    for (PackageSymbol known : toplevel.modle.visiblePackages.values()) {
+                        if (Convert.packagePart(known.fullname) == tsym.flatName())
+                            continue OUTER;
+                    }
+                }
                 if (tsym.kind == PCK && tsym.members().isEmpty() && !tsym.exists()) {
                     log.error(DiagnosticFlag.RESOLVE_ERROR, imp.pos, "doesnt.exist", tsym);
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
index 6205646..c588ecd 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
@@ -452,17 +452,21 @@
         Log.DeferredDiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator.apply(newTree);
         try {
             attr.attribTree(newTree, speculativeEnv, resultInfo);
-            unenterScanner.scan(newTree);
             return newTree;
         } finally {
-            unenterScanner.scan(newTree);
+            new UnenterScanner(env.toplevel.modle).scan(newTree);
             log.popDiagnosticHandler(deferredDiagnosticHandler);
         }
     }
     //where
-        protected UnenterScanner unenterScanner = new UnenterScanner();
 
         class UnenterScanner extends TreeScanner {
+            private final ModuleSymbol msym;
+
+            public UnenterScanner(ModuleSymbol msym) {
+                this.msym = msym;
+            }
+
             @Override
             public void visitClassDef(JCClassDecl tree) {
                 ClassSymbol csym = tree.sym;
@@ -471,9 +475,9 @@
                 //are left unchecked - in such cases there's nothing to clean up.
                 if (csym == null) return;
                 typeEnvs.remove(csym);
-                chk.compiled.remove(csym.flatname);
+                chk.removeCompiled(csym);
                 chk.clearLocalClassNameIndexes(csym);
-                syms.classes.remove(csym.flatname);
+                syms.removeClass(msym, csym.flatname);
                 super.visitClassDef(tree);
             }
         }
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 fea9983..1fe59e9 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
@@ -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
@@ -25,6 +25,9 @@
 
 package com.sun.tools.javac.comp;
 
+import java.util.Map;
+import java.util.Optional;
+
 import javax.tools.JavaFileObject;
 import javax.tools.JavaFileManager;
 
@@ -34,13 +37,13 @@
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.main.Option.PkgInfo;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 
-
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 
@@ -97,6 +100,8 @@
     JavaFileManager fileManager;
     PkgInfo pkginfoOpt;
     TypeEnvs typeEnvs;
+    Modules modules;
+    JCDiagnostic.Factory diags;
 
     private final Todo todo;
 
@@ -119,6 +124,8 @@
         annotate = Annotate.instance(context);
         lint = Lint.instance(context);
         names = Names.instance(context);
+        modules = Modules.instance(context);
+        diags = JCDiagnostic.Factory.instance(context);
 
         predefClassDef = make.ClassDef(
             make.Modifiers(PUBLIC),
@@ -229,6 +236,24 @@
             : env.info.scope;
     }
 
+    /** Create a fresh environment for modules.
+     *
+     *  @param tree     The module definition.
+     *  @param env      The environment current outside of the module definition.
+     */
+    public Env<AttrContext> moduleEnv(JCModuleDecl tree, Env<AttrContext> env) {
+        Assert.checkNonNull(tree.sym);
+        Env<AttrContext> localEnv =
+            env.dup(tree, env.info.dup(WriteableScope.create(tree.sym)));
+        localEnv.enclClass = predefClassDef;
+        localEnv.outer = env;
+        localEnv.info.isSelfCall = false;
+        localEnv.info.lint = null; // leave this to be filled in by Attr,
+                                   // when annotations have been processed
+        return localEnv;
+    }
+
+
 /* ************************************************************************
  * Visitor methods for phase 1: class enter
  *************************************************************************/
@@ -276,57 +301,80 @@
 
     @Override
     public void visitTopLevel(JCCompilationUnit tree) {
+//        Assert.checkNonNull(tree.modle, tree.sourcefile.toString());
+
         JavaFileObject prev = log.useSource(tree.sourcefile);
         boolean addEnv = false;
         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
                                                              JavaFileObject.Kind.SOURCE);
-        JCPackageDecl pd = tree.getPackage();
-        if (pd != null) {
-            tree.packge = pd.packge = syms.enterPackage(TreeInfo.fullName(pd.pid));
-            if (   pd.annotations.nonEmpty()
-                || pkginfoOpt == PkgInfo.ALWAYS
-                || tree.docComments != null) {
-                if (isPkgInfo) {
-                    addEnv = true;
-                } else if (pd.annotations.nonEmpty()) {
-                    log.error(pd.annotations.head.pos(),
-                              "pkg.annotations.sb.in.package-info.java");
-                }
-            }
+        if (TreeInfo.isModuleInfo(tree)) {
+            tree.packge = syms.rootPackage;
+            Env<AttrContext> topEnv = topLevelEnv(tree);
+            classEnter(tree.defs, topEnv);
+            tree.modle.usesProvidesCompleter = modules.getUsesProvidesCompleter();
         } else {
-            tree.packge = syms.unnamedPackage;
-        }
-        tree.packge.complete(); // Find all classes in package.
-        Env<AttrContext> topEnv = topLevelEnv(tree);
-        Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
-
-        // Save environment of package-info.java file.
-        if (isPkgInfo) {
-            Env<AttrContext> env0 = typeEnvs.get(tree.packge);
-            if (env0 != null) {
-                JCCompilationUnit tree0 = env0.toplevel;
-                if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
-                    log.warning(pd != null ? pd.pid.pos() : null,
-                                "pkg-info.already.seen",
-                                tree.packge);
+            JCPackageDecl pd = tree.getPackage();
+            if (pd != null) {
+                tree.packge = pd.packge = syms.enterPackage(tree.modle, TreeInfo.fullName(pd.pid));
+                if (   pd.annotations.nonEmpty()
+                    || pkginfoOpt == PkgInfo.ALWAYS
+                    || tree.docComments != null) {
+                    if (isPkgInfo) {
+                        addEnv = true;
+                    } else if (pd.annotations.nonEmpty()) {
+                        log.error(pd.annotations.head.pos(),
+                                  "pkg.annotations.sb.in.package-info.java");
+                    }
                 }
+            } else {
+                tree.packge = tree.modle.unnamedPackage;
             }
-            typeEnvs.put(tree.packge, packageEnv);
 
-            for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
-                q.flags_field |= EXISTS;
+            Map<Name, PackageSymbol> visiblePackages = tree.modle.visiblePackages;
+            Optional<ModuleSymbol> dependencyWithPackage =
+                syms.listPackageModules(tree.packge.fullname)
+                    .stream()
+                    .filter(m -> m != tree.modle)
+                    .filter(cand -> visiblePackages.get(tree.packge.fullname) == syms.getPackage(cand, tree.packge.fullname))
+                    .findAny();
 
-            Name name = names.package_info;
-            ClassSymbol c = syms.enterClass(name, tree.packge);
-            c.flatname = names.fromString(tree.packge + "." + name);
-            c.sourcefile = tree.sourcefile;
+            if (dependencyWithPackage.isPresent()) {
+                log.error(pd, Errors.PackageInOtherModule(dependencyWithPackage.get()));
+            }
+
+            tree.packge.complete(); // Find all classes in package.
+
+            Env<AttrContext> topEnv = topLevelEnv(tree);
+            Env<AttrContext> packageEnv = isPkgInfo ? topEnv.dup(pd) : null;
+
+            // Save environment of package-info.java file.
+            if (isPkgInfo) {
+                Env<AttrContext> env0 = typeEnvs.get(tree.packge);
+                if (env0 != null) {
+                    JCCompilationUnit tree0 = env0.toplevel;
+                    if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
+                        log.warning(pd != null ? pd.pid.pos() : null,
+                                    "pkg-info.already.seen",
+                                    tree.packge);
+                    }
+                }
+                typeEnvs.put(tree.packge, packageEnv);
+
+                for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner)
+                    q.flags_field |= EXISTS;
+
+                Name name = names.package_info;
+                ClassSymbol c = syms.enterClass(tree.modle, name, tree.packge);
+                c.flatname = names.fromString(tree.packge + "." + name);
+                c.sourcefile = tree.sourcefile;
             c.completer = Completer.NULL_COMPLETER;
-            c.members_field = WriteableScope.create(c);
-            tree.packge.package_info = c;
-        }
-        classEnter(tree.defs, topEnv);
-        if (addEnv) {
-            todo.append(packageEnv);
+                c.members_field = WriteableScope.create(c);
+                tree.packge.package_info = c;
+            }
+            classEnter(tree.defs, topEnv);
+            if (addEnv) {
+                todo.append(packageEnv);
+            }
         }
         log.useSource(prev);
         result = null;
@@ -342,7 +390,7 @@
             PackageSymbol packge = (PackageSymbol)owner;
             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
                 q.flags_field |= EXISTS;
-            c = syms.enterClass(tree.name, packge);
+            c = syms.enterClass(env.toplevel.modle, tree.name, packge);
             packge.members().enterIfAbsent(c);
             if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
                 log.error(tree.pos(),
@@ -356,7 +404,7 @@
             }
             if (owner.kind == TYP) {
                 // We are seeing a member class.
-                c = syms.enterClass(tree.name, (TypeSymbol)owner);
+                c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
                 if ((owner.flags_field & INTERFACE) != 0) {
                     tree.mods.flags |= PUBLIC | STATIC;
                 }
@@ -371,13 +419,13 @@
         tree.sym = c;
 
         // Enter class into `compiled' table and enclosing scope.
-        if (chk.compiled.get(c.flatname) != null) {
+        if (chk.getCompiled(c) != null) {
             duplicateClass(tree.pos(), c);
             result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
             tree.sym = (ClassSymbol)result.tsym;
             return;
         }
-        chk.compiled.put(c.flatname, c);
+        chk.putCompiled(c);
         enclScope.enter(c);
 
         // Set up an environment for class block and store in `typeEnvs'
@@ -421,6 +469,8 @@
         // Recursively enter all member classes.
         classEnter(tree.defs, localEnv);
 
+//        Assert.checkNonNull(c.modle, c.sourcefile.toString());
+
         result = c.type;
     }
     //where
@@ -453,6 +503,13 @@
         result = a;
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        Env<AttrContext> moduleEnv = moduleEnv(tree, env);
+        typeEnvs.put(tree.sym, moduleEnv);
+        todo.append(moduleEnv);
+    }
+
     /** Default class enter visitor method: do nothing.
      */
     @Override
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index ad82a1e..776a1bf 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -743,6 +743,10 @@
             }
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -1305,6 +1309,10 @@
             }
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2416,6 +2424,10 @@
             tree.underlyingType.accept(this);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
@@ -2605,6 +2617,10 @@
             super.visitTry(tree);
         }
 
+        public void visitModuleDef(JCModuleDecl tree) {
+            // Do nothing for modules
+        }
+
     /**************************************************************************
      * main method
      *************************************************************************/
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 19044bb..197cff5 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
@@ -652,7 +652,7 @@
 
         // Enter class symbol in owner scope and compiled table.
         enterSynthetic(odef.pos(), c, owner.members());
-        chk.compiled.put(c.flatname, c);
+        chk.putCompiled(c);
 
         // Create class definition tree.
         JCClassDecl cdef = make.ClassDef(
@@ -1286,10 +1286,11 @@
      */
     ClassSymbol accessConstructorTag() {
         ClassSymbol topClass = currentClass.outermostClass();
+        ModuleSymbol topModle = topClass.packge().modle;
         Name flatname = names.fromString("" + topClass.getQualifiedName() +
                                          target.syntheticNameChar() +
                                          "1");
-        ClassSymbol ctag = chk.compiled.get(flatname);
+        ClassSymbol ctag = chk.getCompiled(topModle, flatname);
         if (ctag == null)
             ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym;
         // keep a record of all tags, to verify that all are generated as required
@@ -2342,25 +2343,18 @@
 
     public void visitPackageDef(JCPackageDecl tree) {
         if (!needPackageInfoClass(tree))
-            return;
+                        return;
 
-        Name name = names.package_info;
         long flags = Flags.ABSTRACT | Flags.INTERFACE;
         // package-info is marked SYNTHETIC in JDK 1.6 and later releases
         flags = flags | Flags.SYNTHETIC;
-        JCClassDecl packageAnnotationsClass
-            = make.ClassDef(make.Modifiers(flags, tree.getAnnotations()),
-                            name, List.<JCTypeParameter>nil(),
-                            null, List.<JCExpression>nil(), List.<JCTree>nil());
         ClassSymbol c = tree.packge.package_info;
-        c.flags_field |= flags;
         c.setAttributes(tree.packge);
+        c.flags_field |= flags;
         ClassType ctype = (ClassType) c.type;
         ctype.supertype_field = syms.objectType;
         ctype.interfaces_field = List.nil();
-        packageAnnotationsClass.sym = c;
-
-        translated.append(packageAnnotationsClass);
+        createInfoClass(tree.annotations, c);
     }
     // where
     private boolean needPackageInfoClass(JCPackageDecl pd) {
@@ -2381,6 +2375,23 @@
         throw new AssertionError();
     }
 
+    public void visitModuleDef(JCModuleDecl tree) {
+        ModuleSymbol msym = tree.sym;
+        ClassSymbol c = msym.module_info;
+        c.flags_field |= Flags.MODULE;
+        createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info);
+    }
+
+    private void createInfoClass(List<JCAnnotation> annots, ClassSymbol c) {
+        long flags = Flags.ABSTRACT | Flags.INTERFACE;
+        JCClassDecl infoClass =
+                make.ClassDef(make.Modifiers(flags, annots),
+                    c.name, List.<JCTypeParameter>nil(),
+                    null, List.<JCExpression>nil(), List.<JCTree>nil());
+        infoClass.sym = c;
+        translated.append(infoClass);
+    }
+
     public void visitClassDef(JCClassDecl tree) {
         Env<AttrContext> prevEnv = attrEnv;
         ClassSymbol currentClassPrev = currentClass;
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
new file mode 100644
index 0000000..f25e928
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
@@ -0,0 +1,1243 @@
+/*
+ * 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.tools.javac.comp;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+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.StandardLocation;
+
+import com.sun.tools.javac.code.Directive;
+import com.sun.tools.javac.code.Directive.ExportsDirective;
+import com.sun.tools.javac.code.Directive.RequiresDirective;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
+import com.sun.tools.javac.code.Directive.UsesDirective;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.ModuleFinder;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+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.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.jvm.ClassWriter;
+import com.sun.tools.javac.jvm.JNIWriter;
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+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.JCExports;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
+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.TreeInfo;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.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 static com.sun.tools.javac.code.Flags.ABSTRACT;
+import static com.sun.tools.javac.code.Flags.PUBLIC;
+import static com.sun.tools.javac.tree.JCTree.Tag.MODULEDEF;
+
+/**
+ *  TODO: fill in
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Modules extends JCTree.Visitor {
+    private static final String ALL_SYSTEM = "ALL-SYSTEM";
+    private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
+
+    private final Log log;
+    private final Names names;
+    private final Symtab syms;
+    private final Attr attr;
+    private final TypeEnvs typeEnvs;
+    private final JavaFileManager fileManager;
+    private final ModuleFinder moduleFinder;
+    private final boolean allowModules;
+
+    public final boolean multiModuleMode;
+    public final boolean noModules;
+
+    private final String moduleOverride;
+
+    ModuleSymbol defaultModule;
+
+    private final String addExportsOpt;
+    private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
+    private final String addReadsOpt;
+    private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
+    private final String addModsOpt;
+    private final String limitModsOpt;
+
+    private Set<ModuleSymbol> rootModules = Collections.emptySet();
+
+    public static Modules instance(Context context) {
+        Modules instance = context.get(Modules.class);
+        if (instance == null)
+            instance = new Modules(context);
+        return instance;
+    }
+
+    protected Modules(Context context) {
+        context.put(Modules.class, this);
+        log = Log.instance(context);
+        names = Names.instance(context);
+        syms = Symtab.instance(context);
+        attr = Attr.instance(context);
+        typeEnvs = TypeEnvs.instance(context);
+        moduleFinder = ModuleFinder.instance(context);
+        fileManager = context.get(JavaFileManager.class);
+        allowModules = Source.instance(context).allowModules();
+        Options options = Options.instance(context);
+
+        moduleOverride = options.get(Option.XMODULE);
+
+        // The following is required, for now, to support building
+        // Swing beaninfo via javadoc.
+        noModules = options.isSet("noModules");
+
+        multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
+        ClassWriter classWriter = ClassWriter.instance(context);
+        classWriter.multiModuleMode = multiModuleMode;
+        JNIWriter jniWriter = JNIWriter.instance(context);
+        jniWriter.multiModuleMode = multiModuleMode;
+
+        addExportsOpt = options.get(Option.XADDEXPORTS);
+        addReadsOpt = options.get(Option.XADDREADS);
+        addModsOpt = options.get(Option.ADDMODS);
+        limitModsOpt = options.get(Option.LIMITMODS);
+    }
+
+    int depth = -1;
+    private void dprintln(String msg) {
+        for (int i = 0; i < depth; i++)
+            System.err.print("  ");
+        System.err.println(msg);
+    }
+
+    public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
+        if (!allowModules || noModules) {
+            for (JCCompilationUnit tree: trees) {
+                tree.modle = syms.noModule;
+            }
+            defaultModule = syms.noModule;
+            return true;
+        }
+
+        int startErrors = log.nerrors;
+
+        depth++;
+        try {
+            // scan trees for module defs
+            Set<ModuleSymbol> roots = enterModules(trees, c);
+
+            setCompilationUnitModules(trees, roots);
+
+            if (!roots.isEmpty() && this.rootModules.isEmpty()) {
+                this.rootModules = roots;
+                allModules(); //ensure errors reported
+            }
+
+            for (ModuleSymbol msym: roots) {
+                msym.complete();
+            }
+        } finally {
+            depth--;
+        }
+
+        return (log.nerrors == startErrors);
+    }
+
+    public Completer getCompleter() {
+        return mainCompleter;
+    }
+
+    public ModuleSymbol getDefaultModule() {
+        return defaultModule;
+    }
+
+    private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) {
+        Set<ModuleSymbol> modules = new LinkedHashSet<>();
+        for (JCCompilationUnit tree : trees) {
+            JavaFileObject prev = log.useSource(tree.sourcefile);
+            try {
+                enterModule(tree, c, modules);
+            } finally {
+                log.useSource(prev);
+            }
+        }
+        return modules;
+    }
+
+
+    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);
+        if (isModuleInfo && isModuleDecl) {
+            JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head;
+            Name name = TreeInfo.fullName(decl.qualId);
+            ModuleSymbol sym;
+            if (c != null) {
+               sym = (ModuleSymbol) c.owner;
+               if (sym.name == null) {
+                   //ModuleFinder.findSingleModule creates a stub of a ModuleSymbol without a name,
+                   //fill the name here after the module-info.java has been parsed
+                   //also enter the ModuleSymbol among modules:
+                   syms.enterModule(sym, name);
+               } else {
+                   // TODO: validate name
+               }
+            } else {
+                sym = syms.enterModule(name);
+                if (sym.module_info.sourcefile != null && sym.module_info.sourcefile != toplevel.sourcefile) {
+                    log.error(decl.pos(), Errors.DuplicateModule(sym));
+                    return;
+                }
+            }
+            sym.completer = getSourceCompleter(toplevel);
+            sym.module_info.sourcefile = toplevel.sourcefile;
+            decl.sym = sym;
+
+            if (multiModuleMode || modules.isEmpty()) {
+                modules.add(sym);
+            } else {
+                log.error(toplevel.pos(), Errors.TooManyModules);
+            }
+
+            Env<AttrContext> provisionalEnv = new Env<>(decl, null);
+
+            provisionalEnv.toplevel = toplevel;
+            typeEnvs.put(sym, provisionalEnv);
+        } else if (isModuleInfo) {
+            if (multiModuleMode) {
+                JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head;
+                log.error(tree.pos(), Errors.ExpectedModule);
+            }
+        } else if (isModuleDecl) {
+            JCTree tree = toplevel.defs.head;
+            log.error(tree.pos(), Errors.ModuleDeclSbInModuleInfoJava);
+        }
+    }
+
+    private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules) {
+        // update the module for each compilation unit
+        if (multiModuleMode) {
+            checkNoAllModulePath();
+            for (JCCompilationUnit tree: trees) {
+                if (tree.defs.isEmpty()) {
+                    tree.modle = syms.unnamedModule;
+                    continue;
+                }
+
+                JavaFileObject prev = log.useSource(tree.sourcefile);
+                try {
+                    Location locn = getModuleLocation(tree);
+                    if (locn != null) {
+                        Name name = names.fromString(fileManager.inferModuleName(locn));
+                        ModuleSymbol msym;
+                        if (tree.defs.head.hasTag(MODULEDEF)) {
+                            JCModuleDecl decl = (JCModuleDecl) tree.defs.head;
+                            msym = decl.sym;
+                            if (msym.name != name) {
+                                log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
+                            }
+                        } else {
+                            msym = syms.enterModule(name);
+                        }
+                        if (msym.sourceLocation == null) {
+                            msym.sourceLocation = locn;
+                            if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                                msym.classLocation = fileManager.getModuleLocation(
+                                        StandardLocation.CLASS_OUTPUT, msym.name.toString());
+                            }
+                        }
+                        tree.modle = msym;
+                        rootModules.add(msym);
+                    } else {
+                        log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules);
+                        tree.modle = syms.errModule;
+                    }
+                } catch (IOException e) {
+                    throw new Error(e); // FIXME
+                } finally {
+                    log.useSource(prev);
+                }
+            }
+            if (syms.unnamedModule.sourceLocation == null) {
+                syms.unnamedModule.completer = getUnnamedModuleCompleter();
+                syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
+            }
+            defaultModule = syms.unnamedModule;
+        } else {
+            if (defaultModule == null) {
+                switch (rootModules.size()) {
+                    case 0:
+                        defaultModule = moduleFinder.findSingleModule();
+                        if (defaultModule == syms.unnamedModule) {
+                            if (moduleOverride != null) {
+                                checkNoAllModulePath();
+                                defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
+                            } else {
+                                // Question: why not do findAllModules and initVisiblePackages here?
+                                // i.e. body of unnamedModuleCompleter
+                                defaultModule.completer = getUnnamedModuleCompleter();
+                                defaultModule.classLocation = StandardLocation.CLASS_PATH;
+                            }
+                        } else {
+                            checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleClasspath);
+                            checkNoAllModulePath();
+                            defaultModule.complete();
+                            // Question: why not do completeModule here?
+                            defaultModule.completer = new Completer() {
+                                @Override
+                                public void complete(Symbol sym) throws CompletionFailure {
+                                    completeModule((ModuleSymbol) sym);
+                                }
+                            };
+                        }
+                        rootModules.add(defaultModule);
+                        break;
+                    case 1:
+                        checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleSourcepath);
+                        checkNoAllModulePath();
+                        defaultModule = rootModules.iterator().next();
+                        defaultModule.classLocation = StandardLocation.CLASS_OUTPUT;
+                        break;
+                    default:
+                        Assert.error("too many modules");
+                }
+                defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
+            } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) {
+                defaultModule.complete();
+                defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
+            } else {
+                Assert.check(rootModules.isEmpty());
+            }
+
+            if (defaultModule != syms.unnamedModule) {
+                syms.unnamedModule.completer = getUnnamedModuleCompleter();
+                syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
+                syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
+            }
+
+            for (JCCompilationUnit tree: trees) {
+                tree.modle = defaultModule;
+            }
+        }
+    }
+
+    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;
+        }
+    }
+
+    private Location getModuleLocation(JavaFileObject fo, Name pkgName) throws IOException {
+        // For now, just check module source path.
+        // We may want to check source path as well.
+        return fileManager.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH,
+                fo, (pkgName == null) ? null : pkgName.toString());
+    }
+
+    private void checkSpecifiedModule(List<JCCompilationUnit> trees, JCDiagnostic.Error error) {
+        if (moduleOverride != null) {
+            JavaFileObject prev = log.useSource(trees.head.sourcefile);
+            try {
+                log.error(trees.head.pos(), error);
+            } finally {
+                log.useSource(prev);
+            }
+        }
+    }
+
+    private void checkNoAllModulePath() {
+        if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) {
+            log.error(Errors.AddmodsAllModulePathInvalid);
+        }
+    }
+
+    private final Completer mainCompleter = new Completer() {
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
+
+            if (msym.kind == Kinds.Kind.ERR) {
+                log.error(Errors.CantFindModule(msym));
+                //make sure the module is initialized:
+                msym.directives = List.nil();
+                msym.exports = List.nil();
+                msym.provides = List.nil();
+                msym.requires = List.nil();
+                msym.uses = List.nil();
+            } else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
+                completeAutomaticModule(msym);
+            } else {
+                msym.module_info.complete();
+            }
+
+            // If module-info comes from a .java file, the underlying
+            // call of classFinder.fillIn will have called through the
+            // source completer, to Enter, and then to Modules.enter,
+            // which will call completeModule.
+            // But, if module-info comes from a .class file, the underlying
+            // call of classFinder.fillIn will just call ClassReader to read
+            // the .class file, and so we call completeModule here.
+            if (msym.module_info.classfile == null || msym.module_info.classfile.getKind() == Kind.CLASS) {
+                completeModule(msym);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "mainCompleter";
+        }
+    };
+
+    private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
+        try {
+            ListBuffer<Directive> directives = new ListBuffer<>();
+            ListBuffer<ExportsDirective> exports = new ListBuffer<>();
+            Set<String> seenPackages = new HashSet<>();
+
+            for (JavaFileObject clazz : fileManager.list(msym.classLocation, "", EnumSet.of(Kind.CLASS), true)) {
+                String binName = fileManager.inferBinaryName(msym.classLocation, clazz);
+                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);
+                    directives.add(d);
+                    exports.add(d);
+                }
+            }
+
+            ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+
+            //ensure all modules are found:
+            moduleFinder.findAllModules();
+
+            for (ModuleSymbol ms : allModules()) {
+                if (ms == syms.unnamedModule || ms == msym)
+                    continue;
+                RequiresDirective d = new RequiresDirective(ms, EnumSet.of(RequiresFlag.PUBLIC));
+                directives.add(d);
+                requires.add(d);
+            }
+
+            RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
+            directives.add(requiresUnnamed);
+            requires.add(requiresUnnamed);
+
+            msym.exports = exports.toList();
+            msym.provides = List.nil();
+            msym.requires = requires.toList();
+            msym.uses = List.nil();
+            msym.directives = directives.toList();
+            msym.flags_field |= Flags.ACYCLIC;
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private Completer getSourceCompleter(JCCompilationUnit tree) {
+        return new Completer() {
+            @Override
+            public void complete(Symbol sym) throws CompletionFailure {
+                ModuleSymbol msym = (ModuleSymbol) sym;
+                msym.flags_field |= UNATTRIBUTED;
+                ModuleVisitor v = new ModuleVisitor();
+                JavaFileObject prev = log.useSource(tree.sourcefile);
+                try {
+                    tree.defs.head.accept(v);
+                    completeModule(msym);
+                    checkCyclicDependencies((JCModuleDecl) tree.defs.head);
+                } finally {
+                    log.useSource(prev);
+                    msym.flags_field &= ~UNATTRIBUTED;
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "SourceCompleter: " + tree.sourcefile.getName();
+            }
+
+        };
+    }
+
+    class ModuleVisitor extends JCTree.Visitor {
+        private ModuleSymbol sym;
+        private final Set<ModuleSymbol> allRequires = new HashSet<>();
+        private final Set<PackageSymbol> allExports = new HashSet<>();
+
+        @Override
+        public void visitModuleDef(JCModuleDecl tree) {
+            sym = Assert.checkNonNull(tree.sym);
+
+            sym.requires = List.nil();
+            sym.exports = List.nil();
+            tree.directives.forEach(t -> t.accept(this));
+            sym.requires = sym.requires.reverse();
+            sym.exports = sym.exports.reverse();
+            ensureJavaBase();
+        }
+
+        @Override
+        public void visitRequires(JCRequires tree) {
+            ModuleSymbol msym = lookupModule(tree.moduleName);
+            if (msym.kind != MDL) {
+                log.error(tree.moduleName.pos(), Errors.ModuleNotFound(msym));
+            } else if (allRequires.contains(msym)) {
+                log.error(tree.moduleName.pos(), Errors.DuplicateRequires(msym));
+            } else {
+                allRequires.add(msym);
+                Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
+                if (tree.isPublic)
+                    flags.add(RequiresFlag.PUBLIC);
+                RequiresDirective d = new RequiresDirective(msym, flags);
+                tree.directive = d;
+                sym.requires = sym.requires.prepend(d);
+            }
+        }
+
+        @Override
+        public void visitExports(JCExports tree) {
+            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));
+            }
+
+            List<ModuleSymbol> toModules = null;
+            if (tree.moduleNames != null) {
+                Set<ModuleSymbol> to = new HashSet<>();
+                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));
+                    }
+                }
+                toModules = List.from(to);
+            }
+
+            if (toModules == null || !toModules.isEmpty()) {
+                ExportsDirective d = new ExportsDirective(packge, toModules);
+                tree.directive = d;
+                sym.exports = sym.exports.prepend(d);
+            }
+        }
+
+        @Override
+        public void visitProvides(JCProvides tree) { }
+
+        @Override
+        public void visitUses(JCUses tree) { }
+
+        private void ensureJavaBase() {
+            if (sym.name == names.java_base)
+                return;
+
+            for (RequiresDirective d: sym.requires) {
+                if (d.module.name == names.java_base)
+                    return;
+            }
+
+            ModuleSymbol java_base = syms.enterModule(names.java_base);
+            Directive.RequiresDirective d =
+                    new Directive.RequiresDirective(java_base,
+                            EnumSet.of(Directive.RequiresFlag.MANDATED));
+            sym.requires = sym.requires.prepend(d);
+        }
+
+        private ModuleSymbol lookupModule(JCExpression moduleName) {
+            try {
+            Name name = TreeInfo.fullName(moduleName);
+            ModuleSymbol msym = moduleFinder.findModule(name);
+            TreeInfo.setSymbol(moduleName, msym);
+            return msym;
+            } catch (Throwable t) {
+                System.err.println("Module " + sym + "; lookup export " + moduleName);
+                throw t;
+            }
+        }
+    }
+
+    public Completer getUsesProvidesCompleter() {
+        return sym -> {
+            ModuleSymbol msym = (ModuleSymbol) sym;
+            Env<AttrContext> env = typeEnvs.get(msym);
+            UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
+            JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
+            try {
+                env.toplevel.defs.head.accept(v);
+            } finally {
+                log.useSource(prev);
+            }
+        };
+    }
+
+    class UsesProvidesVisitor extends JCTree.Visitor {
+        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<>();
+
+        public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) {
+            this.msym = msym;
+            this.env = env;
+        }
+
+        @Override @SuppressWarnings("unchecked")
+        public void visitModuleDef(JCModuleDecl tree) {
+            msym.directives = List.nil();
+            msym.provides = List.nil();
+            msym.uses = List.nil();
+            tree.directives.forEach(t -> t.accept(this));
+            msym.directives = msym.directives.reverse();
+            msym.provides = msym.provides.reverse();
+            msym.uses = msym.uses.reverse();
+
+            if (msym.requires.nonEmpty() && msym.requires.head.flags.contains(RequiresFlag.MANDATED))
+                msym.directives = msym.directives.prepend(msym.requires.head);
+
+            msym.directives = msym.directives.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet())));
+
+            checkForCorrectness();
+        }
+
+        @Override
+        public void visitExports(JCExports tree) {
+            if (tree.directive.packge.members().isEmpty()) {
+                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;
+                if (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, st);
+            ClassSymbol service = (ClassSymbol) st.tsym;
+            ClassSymbol impl = (ClassSymbol) it.tsym;
+            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 if (service.isInner()) {
+                log.error(tree.serviceName.pos(), Errors.ServiceDefinitionIsInner(service));
+            } 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));
+                }
+            }
+            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));
+                }
+                msym.provides = msym.provides.prepend(d);
+                msym.directives = msym.directives.prepend(d);
+                directiveToTreeMap.put(d, tree);
+            }
+        }
+
+        @Override
+        public void visitRequires(JCRequires tree) {
+            msym.directives = msym.directives.prepend(tree.directive);
+        }
+
+        @Override
+        public void visitUses(JCUses tree) {
+            Type st = attr.attribType(tree.qualid, env, syms.objectType);
+            if (st.hasTag(CLASS)) {
+                ClassSymbol service = (ClassSymbol) st.tsym;
+                Directive.UsesDirective d = new Directive.UsesDirective(service);
+                if (!allUses.add(d)) {
+                    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) {
+                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;
+                        }
+                    }
+                    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));
+                    }
+                }
+            }
+        }
+    }
+
+    private Set<ModuleSymbol> allModulesCache;
+
+    private Set<ModuleSymbol> allModules() {
+        if (allModulesCache != null)
+            return allModulesCache;
+
+        Set<ModuleSymbol> observable;
+
+        if (limitModsOpt == null) {
+            observable = null;
+        } else {
+            Set<ModuleSymbol> limitMods = new HashSet<>();
+            for (String limit : limitModsOpt.split(",")) {
+                limitMods.add(syms.enterModule(names.fromString(limit)));
+            }
+            observable = computeTransitiveClosure(limitMods, null);
+            observable.addAll(rootModules);
+        }
+
+        Predicate<ModuleSymbol> observablePred = sym -> observable == null || observable.contains(sym);
+        Predicate<ModuleSymbol> systemModulePred = sym -> (sym.flags() & Flags.SYSTEM_MODULE) != 0;
+        Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>();
+
+        if (rootModules.contains(syms.unnamedModule)) {
+            for (ModuleSymbol sym : syms.getAllModules()) {
+                if (systemModulePred.test(sym) && observablePred.test(sym)) {
+                    enabledRoot.add(sym);
+                }
+            }
+        }
+
+        enabledRoot.addAll(rootModules);
+
+        if (addModsOpt != null) {
+            for (String added : addModsOpt.split(",")) {
+                Stream<ModuleSymbol> modules;
+                switch (added) {
+                    case ALL_SYSTEM:
+                        modules = syms.getAllModules()
+                                      .stream()
+                                      .filter(systemModulePred.and(observablePred));
+                        break;
+                    case ALL_MODULE_PATH:
+                        modules = syms.getAllModules()
+                                      .stream()
+                                      .filter(systemModulePred.negate().and(observablePred));
+                        break;
+                    default:
+                        modules = Stream.of(syms.enterModule(names.fromString(added)));
+                        break;
+                }
+                modules.forEach(sym -> {
+                    enabledRoot.add(sym);
+                    if (observable != null)
+                        observable.add(sym);
+                });
+            }
+        }
+
+        Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
+
+        result.add(syms.unnamedModule);
+
+        if (!rootModules.isEmpty())
+            allModulesCache = result;
+
+        return result;
+    }
+
+    public void enableAllModules() {
+        allModulesCache = new HashSet<>();
+
+        moduleFinder.findAllModules();
+
+        for (ModuleSymbol msym : syms.getAllModules()) {
+            allModulesCache.add(msym);
+        }
+    }
+
+    private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
+        List<ModuleSymbol> todo = List.nil();
+
+        for (ModuleSymbol ms : base) {
+            todo = todo.prepend(ms);
+        }
+
+        Set<ModuleSymbol> result = new LinkedHashSet<>();
+        result.add(syms.java_base);
+
+        while (todo.nonEmpty()) {
+            ModuleSymbol current = todo.head;
+            todo = todo.tail;
+            if (observable != null && !observable.contains(current))
+                continue;
+            if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0))
+                continue;
+            current.complete();
+            for (RequiresDirective rd : current.requires) {
+                todo = todo.prepend(rd.module);
+            }
+        }
+
+        return result;
+    }
+
+    public ModuleSymbol getObservableModule(Name name) {
+        ModuleSymbol mod = syms.getModule(name);
+
+        if (allModules().contains(mod)) {
+            return mod;
+        }
+
+        return null;
+    }
+
+    private Completer getUnnamedModuleCompleter() {
+        moduleFinder.findAllModules();
+        return new Symbol.Completer() {
+            @Override
+            public void complete(Symbol sym) throws CompletionFailure {
+                ModuleSymbol msym = (ModuleSymbol) sym;
+                Set<ModuleSymbol> allModules = allModules();
+                for (ModuleSymbol m : allModules) {
+                    m.complete();
+                }
+                initVisiblePackages(msym, allModules);
+            }
+
+            @Override
+            public String toString() {
+                return "unnamedModule Completer";
+            }
+        };
+    }
+
+    private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>();
+
+    private void completeModule(ModuleSymbol msym) {
+        Assert.checkNonNull(msym.requires);
+
+        initAddReads();
+
+        msym.requires = msym.requires.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet())));
+
+        List<RequiresDirective> requires = msym.requires;
+        List<RequiresDirective> previous = null;
+
+        while (requires.nonEmpty()) {
+            if (!allModules().contains(requires.head.module)) {
+                Env<AttrContext> env = typeEnvs.get(msym);
+                if (env != null) {
+                    JavaFileObject origSource = log.useSource(env.toplevel.sourcefile);
+                    try {
+                        log.error(/*XXX*/env.tree, Errors.ModuleNotFound(requires.head.module));
+                    } finally {
+                        log.useSource(origSource);
+                    }
+                } else {
+                    Assert.check((msym.flags() & Flags.AUTOMATIC_MODULE) == 0);
+                }
+                if (previous != null) {
+                    previous.tail = requires.tail;
+                } else {
+                    msym.requires.tail = requires.tail;
+                }
+            } else {
+                previous = requires;
+            }
+            requires = requires.tail;
+        }
+
+        Set<ModuleSymbol> readable = new LinkedHashSet<>();
+        Set<ModuleSymbol> requiresPublic = new HashSet<>();
+        if ((msym.flags() & Flags.AUTOMATIC_MODULE) == 0) {
+            for (RequiresDirective d : msym.requires) {
+                d.module.complete();
+                readable.add(d.module);
+                Set<ModuleSymbol> s = retrieveRequiresPublic(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);
+                }
+            }
+        } else {
+            //the module graph may contain cycles involving automatic modules
+            //handle automatic modules separatelly:
+            Set<ModuleSymbol> s = retrieveRequiresPublic(msym);
+
+            readable.addAll(s);
+            requiresPublic.addAll(s);
+
+            //ensure the unnamed module is added (it is not requires public):
+            readable.add(syms.unnamedModule);
+        }
+        requiresPublicCache.put(msym, requiresPublic);
+        initVisiblePackages(msym, readable);
+        for (ExportsDirective d: msym.exports) {
+            d.packge.modle = msym;
+        }
+
+    }
+
+    private Set<ModuleSymbol> retrieveRequiresPublic(ModuleSymbol msym) {
+        Set<ModuleSymbol> requiresPublic = requiresPublicCache.get(msym);
+
+        if (requiresPublic == null) {
+            //the module graph may contain cycles involving automatic modules or -XaddReads edges
+            requiresPublic = new HashSet<>();
+
+            Set<ModuleSymbol> seen = new HashSet<>();
+            List<ModuleSymbol> todo = List.of(msym);
+
+            while (todo.nonEmpty()) {
+                ModuleSymbol current = todo.head;
+                todo = todo.tail;
+                if (!seen.add(current))
+                    continue;
+                requiresPublic.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())
+                            todo = todo.prepend(rd.module);
+                    }
+                } else {
+                    for (ModuleSymbol mod : allModules()) {
+                        todo = todo.prepend(mod);
+                    }
+                }
+            }
+
+            requiresPublic.remove(msym);
+        }
+
+        return requiresPublic;
+    }
+
+    private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {
+        initAddExports();
+
+        msym.visiblePackages = new LinkedHashMap<>();
+
+        Map<Name, ModuleSymbol> seen = new HashMap<>();
+
+        for (ModuleSymbol rm : readable) {
+            if (rm == syms.unnamedModule)
+                continue;
+            addVisiblePackages(msym, seen, rm, rm.exports);
+        }
+
+        for (Entry<ModuleSymbol, Set<ExportsDirective>> addExportsEntry : addExports.entrySet())
+            addVisiblePackages(msym, seen, addExportsEntry.getKey(), addExportsEntry.getValue());
+    }
+
+    private void addVisiblePackages(ModuleSymbol msym,
+                                    Map<Name, ModuleSymbol> seenPackages,
+                                    ModuleSymbol exportsFrom,
+                                    Collection<ExportsDirective> exports) {
+        for (ExportsDirective d : exports) {
+            if (d.modules == null || d.modules.contains(msym)) {
+                Name packageName = d.packge.fullname;
+                ModuleSymbol previousModule = seenPackages.get(packageName);
+
+                if (previousModule != null && previousModule != exportsFrom) {
+                    Env<AttrContext> env = typeEnvs.get(msym);
+                    JavaFileObject origSource = env != null ? log.useSource(env.toplevel.sourcefile)
+                                                            : null;
+                    DiagnosticPosition pos = env != null ? env.tree.pos() : null;
+                    try {
+                        log.error(pos, Errors.PackageClashFromRequires(msym, packageName,
+                                                                      previousModule, exportsFrom));
+                    } finally {
+                        if (env != null)
+                            log.useSource(origSource);
+                    }
+                    continue;
+                }
+
+                seenPackages.put(packageName, exportsFrom);
+                msym.visiblePackages.put(d.packge.fullname, d.packge);
+            }
+        }
+    }
+
+    private void initAddExports() {
+        if (addExports != null)
+            return;
+
+        addExports = new LinkedHashMap<>();
+
+        if (addExportsOpt == null)
+            return;
+
+//        System.err.println("Modules.addExports:\n   " + addExportsOpt.replace("\0", "\n   "));
+
+        Pattern ep = Pattern.compile("([^/]+)/([^=]+)=(.*)");
+        for (String s: addExportsOpt.split("\0+")) {
+            if (s.isEmpty())
+                continue;
+            Matcher em = ep.matcher(s);
+            if (!em.matches()) {
+                continue;
+            }
+
+            // Terminology comes from
+            //  -XaddExports:module/package=target,...
+            // Compare to
+            //  module module { exports package to target, ... }
+            String moduleName = em.group(1);
+            String packageName = em.group(2);
+            String targetNames = em.group(3);
+
+            ModuleSymbol msym = syms.enterModule(names.fromString(moduleName));
+            PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
+            p.modle = msym;  // TODO: do we need this?
+
+            List<ModuleSymbol> targetModules = List.nil();
+            for (String toModule : targetNames.split("[ ,]+")) {
+                ModuleSymbol m;
+                if (toModule.equals("ALL-UNNAMED")) {
+                    m = syms.unnamedModule;
+                } else {
+                    if (!SourceVersion.isName(toModule)) {
+                        // TODO: error: invalid module name
+                        continue;
+                    }
+                    m = syms.enterModule(names.fromString(toModule));
+                }
+                targetModules = targetModules.prepend(m);
+            }
+
+            Set<ExportsDirective> extra = addExports.computeIfAbsent(msym, _x -> new LinkedHashSet<>());
+            ExportsDirective d = new ExportsDirective(p, targetModules);
+            extra.add(d);
+        }
+    }
+
+    private void initAddReads() {
+        if (addReads != null)
+            return;
+
+        addReads = new LinkedHashMap<>();
+
+        if (addReadsOpt == null)
+            return;
+
+//        System.err.println("Modules.addReads:\n   " + addReadsOpt.replace("\0", "\n   "));
+
+        Pattern rp = Pattern.compile("([^=]+)=(.*)");
+        for (String s : addReadsOpt.split("\0+")) {
+            if (s.isEmpty())
+                continue;
+            Matcher rm = rp.matcher(s);
+            if (!rm.matches()) {
+                continue;
+            }
+
+            // Terminology comes from
+            //  -XaddReads:target-module=source-module,...
+            // Compare to
+            //  module target-module { requires source-module; ... }
+            String targetName = rm.group(1);
+            String sources = rm.group(2);
+
+            ModuleSymbol msym = syms.enterModule(names.fromString(targetName));
+            for (String source : sources.split("[ ,]+")) {
+                ModuleSymbol sourceModule;
+                if (source.equals("ALL-UNNAMED")) {
+                    sourceModule = syms.unnamedModule;
+                } else {
+                    if (!SourceVersion.isName(source)) {
+                        // TODO: error: invalid module name
+                        continue;
+                    }
+                    sourceModule = syms.enterModule(names.fromString(source));
+                }
+                addReads.computeIfAbsent(msym, m -> new HashSet<>())
+                        .add(new RequiresDirective(sourceModule, EnumSet.of(RequiresFlag.EXTRA)));
+            }
+        }
+    }
+
+    private void checkCyclicDependencies(JCModuleDecl mod) {
+        for (JCDirective d : mod.directives) {
+            if (!d.hasTag(Tag.REQUIRES))
+                continue;
+            JCRequires rd = (JCRequires) d;
+            Set<ModuleSymbol> nonSyntheticDeps = new HashSet<>();
+            List<ModuleSymbol> queue = List.of(rd.directive.module);
+            while (queue.nonEmpty()) {
+                ModuleSymbol current = queue.head;
+                queue = queue.tail;
+                if (!nonSyntheticDeps.add(current))
+                    continue;
+                if ((current.flags() & Flags.ACYCLIC) != 0)
+                    continue;
+                current.complete();
+                Assert.checkNonNull(current.requires, () -> current.toString());
+                for (RequiresDirective dep : current.requires) {
+                    if (!dep.flags.contains(RequiresFlag.EXTRA))
+                        queue = queue.prepend(dep.module);
+                }
+            }
+            if (nonSyntheticDeps.contains(mod.sym)) {
+                log.error(rd.moduleName.pos(), Errors.CyclicRequires(rd.directive.module));
+            }
+            mod.sym.flags_field |= Flags.ACYCLIC;
+        }
+    }
+
+    // DEBUG
+    private String toString(ModuleSymbol msym) {
+        return msym.name + "["
+                + "kind:" + msym.kind + ";"
+                + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
+                + "info:" + toString(msym.module_info.sourcefile) + ","
+                            + toString(msym.module_info.classfile) + ","
+                            + msym.module_info.completer
+                + "]";
+    }
+
+    // DEBUG
+    String toString(Location locn) {
+        return (locn == null) ? "--" : locn.getName();
+    }
+
+    // DEBUG
+    String toString(JavaFileObject fo) {
+        return (fo == null) ? "--" : fo.getName();
+    }
+
+    public void newRound() {
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
index 38a941b..6be12dd 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
@@ -93,10 +93,13 @@
     JCDiagnostic.Factory diags;
     public final boolean allowMethodHandles;
     public final boolean allowFunctionalInterfaceMostSpecific;
+    public final boolean allowModules;
     public final boolean checkVarargsAccessAfterResolution;
     private final boolean compactMethodDiags;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
 
+    private final boolean checkModuleAccess;
+
     WriteableScope polymorphicSignatureScope;
 
     protected Resolve(Context context) {
@@ -130,6 +133,12 @@
         polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
+
+        allowModules = source.allowModules();
+
+        // The following is required, for now, to support building
+        // Swing beaninfo via javadoc.
+        checkModuleAccess = !options.isSet("noModules");
     }
 
     /** error symbols, which are returned when resolution fails
@@ -309,8 +318,19 @@
                     env.toplevel.packge == c.packge();
                 break;
             default: // error recovery
+                isAccessible = true;
+                break;
             case PUBLIC:
                 isAccessible = true;
+                if (allowModules && checkModuleAccess) {
+                    ModuleSymbol currModule = env.toplevel.modle;
+                    currModule.complete();
+                    PackageSymbol p = c.packge();
+                    isAccessible =
+                        (currModule == p.modle) || currModule.visiblePackages.get(p.fullname) == p || p == syms.rootPackage;
+                } else {
+                    isAccessible = true;
+                }
                 break;
             case PROTECTED:
                 isAccessible =
@@ -1947,16 +1967,27 @@
      */
     Symbol loadClass(Env<AttrContext> env, Name name) {
         try {
-            ClassSymbol c = finder.loadClass(name);
+            ClassSymbol c = finder.loadClass(env.toplevel.modle, name);
             return isAccessible(env, c) ? c : new AccessError(c);
         } catch (ClassFinder.BadClassFile err) {
             throw err;
         } catch (CompletionFailure ex) {
+            //even if a class cannot be found in the current module and packages in modules it depends on that
+            //are exported for any or this module, the class may exist internally in some of these modules,
+            //or may exist in a module on which this module does not depend. Provide better diagnostic in
+            //such cases by looking for the class in any module:
+            for (ModuleSymbol ms : syms.getAllModules()) {
+                //do not load currently unloaded classes, to avoid too eager completion of random things in other modules:
+                ClassSymbol clazz = syms.getClass(ms, name);
+
+                if (clazz != null) {
+                    return new AccessError(clazz);
+                }
+            }
             return typeNotFound;
         }
     }
 
-
     /**
      * Find a type declared in a scope (not inherited).  Return null
      * if none is found.
@@ -2157,7 +2188,7 @@
         }
 
         if (kind.contains(KindSelector.PCK))
-            return syms.enterPackage(name);
+            return syms.lookupPackage(env.toplevel.modle, name);
         else return bestSoFar;
     }
 
@@ -2173,7 +2204,7 @@
         Symbol bestSoFar = typeNotFound;
         PackageSymbol pack = null;
         if (kind.contains(KindSelector.PCK)) {
-            pack = syms.enterPackage(fullname);
+            pack = syms.lookupPackage(env.toplevel.modle, fullname);
             if (pack.exists()) return pack;
         }
         if (kind.contains(KindSelector.TYP)) {
@@ -3920,9 +3951,15 @@
             else if ((sym.flags() & PUBLIC) != 0
                 || (env != null && this.site != null
                     && !isAccessible(env, this.site))) {
-                return diags.create(dkind, log.currentSource(),
-                        pos, "not.def.access.class.intf.cant.access",
-                    sym, sym.location());
+                if (sym.owner.kind == PCK) {
+                    return diags.create(dkind, log.currentSource(),
+                            pos, "not.def.access.package.cant.access",
+                        sym, sym.location());
+                } else {
+                    return diags.create(dkind, log.currentSource(),
+                            pos, "not.def.access.class.intf.cant.access",
+                        sym, sym.location());
+                }
             }
             else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0) {
                 return diags.create(dkind, log.currentSource(),
@@ -3935,6 +3972,18 @@
                         pos, "not.def.public.cant.access", sym, sym.location());
             }
         }
+
+        private String toString(Type type) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(type);
+            if (type != null) {
+                sb.append("[tsym:").append(type.tsym);
+                if (type.tsym != null)
+                    sb.append("packge:").append(type.tsym.packge());
+                sb.append("]");
+            }
+            return sb.toString();
+        }
     }
 
     /**
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 04aaa83..8e8665d 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
@@ -162,6 +162,8 @@
         // 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); });
@@ -330,7 +332,7 @@
                                          chk.importAccessible(sym, packge);
 
                 // Import-on-demand java.lang.
-                PackageSymbol javaLang = syms.enterPackage(names.java_lang);
+                PackageSymbol javaLang = syms.enterPackage(syms.java_base, names.java_lang);
                 if (javaLang.members().isEmpty() && !javaLang.exists())
                     throw new FatalError(diags.fragment("fatal.err.no.java.lang"));
                 importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env);
@@ -358,7 +360,9 @@
                 Symbol p = env.toplevel.packge;
                 while (p.owner != syms.rootPackage) {
                     p.owner.complete(); // enter all class members of p
-                    if (syms.classes.get(p.getQualifiedName()) != null) {
+                    //need to lookup the owning module/package:
+                    PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, p.owner.getQualifiedName());
+                    if (syms.getClass(pack.modle, p.getQualifiedName()) != null) {
                         log.error(tree.pos,
                                   "pkg.clashes.with.class.of.same.name",
                                   p);
@@ -515,7 +519,7 @@
             return result;
         }
 
-        protected Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) {
+        protected Type modelMissingTypes(Env<AttrContext> env, Type t, final JCExpression tree, final boolean interfaceExpected) {
             if (!t.hasTag(ERROR))
                 return t;
 
@@ -525,19 +529,21 @@
                 @Override
                 public Type getModelType() {
                     if (modelType == null)
-                        modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree);
+                        modelType = new Synthesizer(env.toplevel.modle, getOriginalType(), interfaceExpected).visit(tree);
                     return modelType;
                 }
             };
         }
             // where:
             private class Synthesizer extends JCTree.Visitor {
+                ModuleSymbol msym;
                 Type originalType;
                 boolean interfaceExpected;
                 List<ClassSymbol> synthesizedSymbols = List.nil();
                 Type result;
 
-                Synthesizer(Type originalType, boolean interfaceExpected) {
+                Synthesizer(ModuleSymbol msym, Type originalType, boolean interfaceExpected) {
+                    this.msym = msym;
                     this.originalType = originalType;
                     this.interfaceExpected = interfaceExpected;
                 }
@@ -564,7 +570,7 @@
                     if (!tree.type.hasTag(ERROR)) {
                         result = tree.type;
                     } else {
-                        result = synthesizeClass(tree.name, syms.unnamedPackage).type;
+                        result = synthesizeClass(tree.name, msym.unnamedPackage).type;
                     }
                 }
 
@@ -654,7 +660,7 @@
                 ? Type.noType
                 : syms.objectType;
             }
-            ct.supertype_field = modelMissingTypes(supertype, extending, false);
+            ct.supertype_field = modelMissingTypes(baseEnv, supertype, extending, false);
 
             // Determine interfaces.
             ListBuffer<Type> interfaces = new ListBuffer<>();
@@ -669,7 +675,7 @@
                 } else {
                     if (all_interfaces == null)
                         all_interfaces = new ListBuffer<Type>().appendList(interfaces);
-                    all_interfaces.append(modelMissingTypes(it, iface, true));
+                    all_interfaces.append(modelMissingTypes(baseEnv, it, iface, true));
                 }
             }
 
@@ -816,8 +822,8 @@
             // but admit classes in the unnamed package which have the same
             // name as a top-level package.
             if (checkClash &&
-                sym.owner.kind == PCK && sym.owner != syms.unnamedPackage &&
-                syms.packageExists(sym.fullname)) {
+                sym.owner.kind == PCK && sym.owner != env.toplevel.modle.unnamedPackage &&
+                syms.packageExists(env.toplevel.modle, sym.fullname)) {
                 log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), sym);
             }
             if (sym.owner.kind == PCK && (sym.flags_field & PUBLIC) == 0 &&
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 caf3dc3..874f78c 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
@@ -31,6 +31,7 @@
 import java.io.OutputStreamWriter;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.nio.ByteBuffer;
@@ -42,6 +43,7 @@
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -58,6 +60,8 @@
 import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.main.OptionHelper;
 import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.util.Abort;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
@@ -192,12 +196,34 @@
                         Class.forName(classLoaderClass).asSubclass(ClassLoader.class);
                 Class<?>[] constrArgTypes = { URL[].class, ClassLoader.class };
                 Constructor<? extends ClassLoader> constr = loader.getConstructor(constrArgTypes);
-                return constr.newInstance(urls, thisClassLoader);
+                return ensureReadable(constr.newInstance(urls, thisClassLoader));
             } catch (ReflectiveOperationException t) {
                 // ignore errors loading user-provided class loader, fall through
             }
         }
-        return new URLClassLoader(urls, thisClassLoader);
+        return ensureReadable(new URLClassLoader(urls, thisClassLoader));
+    }
+
+    /**
+     * Ensures that the unnamed module of the given classloader is readable to this
+     * module.
+     */
+    private ClassLoader ensureReadable(ClassLoader targetLoader) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Method getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
+            Object targetModule = getUnnamedModuleMethod.invoke(targetLoader);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new Abort(e);
+        }
+        return targetLoader;
     }
 
     public boolean isDefaultBootClassPath() {
@@ -284,8 +310,14 @@
      */
     public boolean handleOptions(Map<Option, String> map) {
         boolean ok = true;
-        for (Map.Entry<Option, String> e: map.entrySet())
-            ok = ok & handleOption(e.getKey(), e.getValue());
+        for (Map.Entry<Option, String> e: map.entrySet()) {
+            try {
+                ok = ok & handleOption(e.getKey(), e.getValue());
+            } catch (IllegalArgumentException ex) {
+                log.error(Errors.IllegalArgumentForOption(e.getKey().getText(), ex.getMessage()));
+                ok = false;
+            }
+        }
         return ok;
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
index 6ca7bcd..20f7a48 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java
@@ -201,6 +201,8 @@
             if (Files.exists(dir)) {
                 try (DirectoryStream<Path> modules = Files.newDirectoryStream(dir)) {
                     for (Path module: modules) {
+                        if (Files.isSymbolicLink(module))
+                            module = Files.readSymbolicLink(module);
                         Path p = rd.resolveAgainst(module);
                         if (!Files.exists(p))
                             continue;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
index 1fc2fa1a..496c039 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java
@@ -47,12 +47,14 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -70,6 +72,10 @@
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.ModuleWrappers.Configuration;
+import com.sun.tools.javac.util.ModuleWrappers.Layer;
+import com.sun.tools.javac.util.ModuleWrappers.ModuleFinder;
+import com.sun.tools.javac.util.ModuleWrappers.ServiceLoaderHelper;
 
 import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
 
@@ -421,16 +427,7 @@
                                boolean recurse,
                                ListBuffer<JavaFileObject> resultList)
             throws IOException {
-        // Very temporary and obnoxious interim hack
-        if (container.endsWith("bootmodules.jimage")) {
-            System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
-            container = Locations.JRT_MARKER_FILE;
-        } else if (container.getNameCount() > 0 && container.getFileName().toString().endsWith(".jimage")) {
-            System.err.println("Warning: reference to " + container + " ignored");
-            return;
-        }
-
-        if (container == Locations.JRT_MARKER_FILE) {
+        if (Files.isRegularFile(container) && container.equals(Locations.thisSystemModules)) {
             try {
                 listJRTImage(subdirectory,
                         fileKinds,
@@ -443,7 +440,7 @@
             return;
         }
 
-        if  (fsInfo.isDirectory(container)) {
+        if  (Files.isDirectory(container)) {
             listDirectory(container, null,
                           subdirectory,
                           fileKinds,
@@ -452,7 +449,7 @@
             return;
         }
 
-        if (Files.exists(container)) {
+        if (Files.isRegularFile(container)) {
             listArchive(container,
                     subdirectory,
                     fileKinds,
@@ -530,6 +527,7 @@
             return;
         }
 
+        locations.close();
         for (FileSystem fs: fileSystems.values()) {
             fs.close();
         }
@@ -604,7 +602,8 @@
 
     @Override @DefinedBy(Api.COMPILER)
     public boolean hasLocation(Location location) {
-        return getLocation(location) != null;
+        nullCheck(location);
+        return locations.hasLocation(location);
     }
 
     @Override @DefinedBy(Api.COMPILER)
@@ -645,14 +644,14 @@
             return null;
 
         for (Path file: path) {
-            if (file == Locations.JRT_MARKER_FILE) {
+            if (file.equals(Locations.thisSystemModules)) {
                 JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname());
                 if (symbolFileEnabled && e.ctSym.hidden)
                     continue;
                 Path p = e.files.get(name.basename());
                 if (p != null)
                     return PathFileObject.forJRTPath(this, p);
-            } else if (fsInfo.isDirectory(file)) {
+            } else if (Files.isDirectory(file)) {
                 try {
                     Path f = name.resolveAgainst(file);
                     if (Files.exists(f))
@@ -660,7 +659,7 @@
                                 fsInfo.getCanonicalFile(f), f);
                 } catch (InvalidPathException ignore) {
                 }
-            } else if (Files.exists(file)) {
+            } else if (Files.isRegularFile(file)) {
                 FileSystem fs = getFileSystem(file);
                 if (fs != null) {
                     Path fsRoot = fs.getRootDirectories().iterator().next();
@@ -830,6 +829,69 @@
     }
 
     @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, String moduleName) throws IOException {
+        nullCheck(location);
+        nullCheck(moduleName);
+        return locations.getModuleLocation(location, moduleName);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws IOException {
+        nullCheck(location);
+        nullCheck(service);
+        if (location.isModuleLocation()) {
+            Collection<Path> paths = locations.getLocation(location);
+            ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[paths.size()]));
+            Layer bootLayer = Layer.boot();
+            Configuration cf = bootLayer.configuration().resolveRequiresAndUses(ModuleFinder.empty(), finder, Collections.emptySet());
+            Layer layer = bootLayer.defineModulesWithOneLoader(cf, ClassLoader.getSystemClassLoader());
+            return ServiceLoaderHelper.load(layer, service);
+        } else {
+            return ServiceLoader.load(service, getClassLoader(location));
+        }
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        nullCheck(location);
+        if (!(fo instanceof PathFileObject))
+            throw new IllegalArgumentException(fo.getName());
+        int depth = 1; // allow 1 for filename
+        if (pkgName != null && !pkgName.isEmpty()) {
+            depth += 1;
+            for (int i = 0; i < pkgName.length(); i++) {
+                switch (pkgName.charAt(i)) {
+                    case '/': case '.':
+                        depth++;
+                }
+            }
+        }
+        Path p = Locations.normalize(((PathFileObject) fo).path);
+        int fc = p.getNameCount();
+        if (depth < fc) {
+            Path root = p.getRoot();
+            Path subpath = p.subpath(0, fc - depth);
+            Path dir = (root == null) ? subpath : root.resolve(subpath);
+            // need to find dir in location
+            return locations.getModuleLocation(location, dir);
+        } else {
+            return null;
+        }
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public String inferModuleName(Location location) {
+        nullCheck(location);
+        return locations.inferModuleName(location);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
+    public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        nullCheck(location);
+        return locations.listModuleLocations(location);
+    }
+
+    @Override @DefinedBy(Api.COMPILER)
     public Path asPath(FileObject file) {
         if (file instanceof PathFileObject) {
             return ((PathFileObject) file).path;
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 aec0e7f..f3a7b61 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
@@ -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
@@ -25,15 +25,23 @@
 
 package com.sun.tools.javac.file;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.UncheckedIOException;
-import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -43,15 +51,20 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
+import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
@@ -59,13 +72,14 @@
 
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Pair;
 import com.sun.tools.javac.util.StringUtils;
 
-import static javax.tools.StandardLocation.CLASS_PATH;
 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
-import static javax.tools.StandardLocation.SOURCE_PATH;
 
 import static com.sun.tools.javac.main.Option.BOOTCLASSPATH;
 import static com.sun.tools.javac.main.Option.DJAVA_ENDORSED_DIRS;
@@ -103,16 +117,35 @@
      */
     private boolean warn;
 
-    // Used by Locations(for now) to indicate that the PLATFORM_CLASS_PATH
-    // should use the jrt: file system.
-    // When Locations has been converted to use java.nio.file.Path,
-    // Locations can use Paths.get(URI.create("jrt:"))
-    static final Path JRT_MARKER_FILE = Paths.get("JRT_MARKER_FILE");
+    private ModuleNameReader moduleNameReader;
+
+    static final Path javaHome = Paths.get(System.getProperty("java.home"));
+    static final Path thisSystemModules = javaHome.resolve("lib").resolve("modules");
+
+    Map<Path, FileSystem> fileSystems = new LinkedHashMap<>();
+    List<Closeable> closeables = new ArrayList<>();
 
     Locations() {
         initHandlers();
     }
 
+    public void close() throws IOException {
+        ListBuffer<IOException> list = new ListBuffer<>();
+        closeables.forEach(closeable -> {
+            try {
+                closeable.close();
+            } catch (IOException ex) {
+                list.add(ex);
+            }
+        });
+        if (list.nonEmpty()) {
+            IOException ex = new IOException();
+            for (IOException e: list)
+                ex.addSuppressed(e);
+            throw ex;
+        }
+    }
+
     // could replace Lint by "boolean warn"
     void update(Log log, Lint lint, FSInfo fsInfo) {
         this.log = log;
@@ -269,10 +302,13 @@
 
             if (fsInfo.isFile(file)) {
                 /* File is an ordinary file. */
-                if (!isArchive(file) && !file.getFileName().toString().endsWith(".jimage")) {
+                if (!isArchive(file)
+                        && !file.getFileName().toString().endsWith(".jmod")
+                        && !file.endsWith("modules")) {
                     /* Not a recognized extension; open it to see if
                      it looks like a valid zip file. */
                     try {
+                        // TODO: use of ZipFile should be updated
                         ZipFile z = new ZipFile(file.toFile());
                         z.close();
                         if (warn) {
@@ -295,7 +331,7 @@
             super.add(file);
             canonicalValues.add(canonFile);
 
-            if (expandJarClassPaths && fsInfo.isFile(file) && !file.getFileName().toString().endsWith(".jimage")) {
+            if (expandJarClassPaths && fsInfo.isFile(file) && !file.endsWith("modules")) {
                 addJarClassPath(file, warn);
             }
         }
@@ -316,15 +352,74 @@
     }
 
     /**
-     * Base class for handling support for the representation of Locations. Implementations are
-     * responsible for handling the interactions between the command line options for a location,
-     * and API access via setLocation.
+     * Base class for handling support for the representation of Locations.
+     *
+     * Locations are (by design) opaque handles that can easily be implemented
+     * by enums like StandardLocation. Within JavacFileManager, each Location
+     * has an associated LocationHandler, which provides much of the appropriate
+     * functionality for the corresponding Location.
      *
      * @see #initHandlers
      * @see #getHandler
      */
     protected abstract class LocationHandler {
 
+        /**
+         * @see JavaFileManager#handleOption
+         */
+        abstract boolean handleOption(Option option, String value);
+
+        /**
+         * @see StandardJavaFileManager#hasLocation
+         */
+        boolean isSet() {
+            return (getPaths() != null);
+        }
+
+        /**
+         * @see StandardJavaFileManager#getLocation
+         */
+        abstract Collection<Path> getPaths();
+
+        /**
+         * @see StandardJavaFileManager#setLocation
+         */
+        abstract void setPaths(Iterable<? extends Path> files) throws IOException;
+
+        /**
+         * @see JavaFileManager#getModuleLocation(Location, String)
+         */
+        Location getModuleLocation(String moduleName) throws IOException {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#getModuleLocation(Location, JavaFileObject, String)
+         */
+        Location getModuleLocation(Path dir) {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#inferModuleName
+         */
+        String inferModuleName() {
+            return null;
+        }
+
+        /**
+         * @see JavaFileManager#listModuleLocations
+         */
+        Iterable<Set<Location>> listModuleLocations() throws IOException {
+            return null;
+        }
+    }
+
+    /**
+     * A LocationHandler for a given Location, and associated set of options.
+     */
+    private abstract class BasicLocationHandler extends LocationHandler {
+
         final Location location;
         final Set<Option> options;
 
@@ -336,37 +431,23 @@
          * @param options the options affecting this location
          * @see #initHandlers
          */
-        protected LocationHandler(Location location, Option... options) {
+        protected BasicLocationHandler(Location location, Option... options) {
             this.location = location;
             this.options = options.length == 0
                     ? EnumSet.noneOf(Option.class)
                     : EnumSet.copyOf(Arrays.asList(options));
         }
-
-        /**
-         * @see JavaFileManager#handleOption
-         */
-        abstract boolean handleOption(Option option, String value);
-
-        /**
-         * @see StandardJavaFileManager#getLocation
-         */
-        abstract Collection<Path> getLocation();
-
-        /**
-         * @see StandardJavaFileManager#setLocation
-         */
-        abstract void setLocation(Iterable<? extends Path> files) throws IOException;
     }
 
     /**
      * General purpose implementation for output locations, such as -d/CLASS_OUTPUT and
-     * -s/SOURCE_OUTPUT. All options are treated as equivalent (i.e. aliases.) The value is a single
-     * file, possibly null.
+     * -s/SOURCE_OUTPUT. All options are treated as equivalent (i.e. aliases.)
+     * The value is a single file, possibly null.
      */
-    private class OutputLocationHandler extends LocationHandler {
+    private class OutputLocationHandler extends BasicLocationHandler {
 
         private Path outputDir;
+        private Map<String, Location> moduleLocations;
 
         OutputLocationHandler(Location location, Option... options) {
             super(location, options);
@@ -387,12 +468,12 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             return (outputDir == null) ? null : Collections.singleton(outputDir);
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) throws IOException {
+        void setPaths(Iterable<? extends Path> files) throws IOException {
             if (files == null) {
                 outputDir = null;
             } else {
@@ -411,15 +492,32 @@
                 }
                 outputDir = dir;
             }
+            moduleLocations = null;
+        }
+
+        @Override
+        Location getModuleLocation(String name) {
+            if (moduleLocations == null)
+                moduleLocations = new HashMap<>();
+            Location l = moduleLocations.get(name);
+            if (l == null) {
+                l = new ModuleLocationHandler(location.getName() + "[" + name + "]",
+                        name,
+                        Collections.singleton(outputDir.resolve(name)),
+                        true, false);
+                moduleLocations.put(name, l);
+            }
+            return l;
         }
     }
 
     /**
-     * General purpose implementation for search path locations, such as -sourcepath/SOURCE_PATH and
-     * -processorPath/ANNOTATION_PROCESSOR_PATH. All options are treated as equivalent (i.e. aliases.)
+     * General purpose implementation for search path locations,
+     * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESSOR_PATH.
+     * All options are treated as equivalent (i.e. aliases.)
      * The value is an ordered set of files and/or directories.
      */
-    private class SimpleLocationHandler extends LocationHandler {
+    private class SimpleLocationHandler extends BasicLocationHandler {
 
         protected Collection<Path> searchPath;
 
@@ -438,12 +536,12 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) {
+        void setPaths(Iterable<? extends Path> files) {
             SearchPath p;
             if (files == null) {
                 p = computePath(null);
@@ -463,8 +561,8 @@
     }
 
     /**
-     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH. If no value is given, a default
-     * is provided, based on system properties and other values.
+     * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH.
+     * If no value is given, a default is provided, based on system properties and other values.
      */
     private class ClassPathLocationHandler extends SimpleLocationHandler {
 
@@ -474,7 +572,7 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             lazy();
             return searchPath;
         }
@@ -511,19 +609,22 @@
 
         private void lazy() {
             if (searchPath == null) {
-                setLocation(null);
+                setPaths(null);
             }
         }
     }
 
     /**
-     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH. Various options are supported for
-     * different components of the platform class path. Setting a value with setLocation overrides
-     * all existing option values. Setting any option overrides any value set with setLocation, and
-     * reverts to using default values for options that have not been set. Setting -bootclasspath or
-     * -Xbootclasspath overrides any existing value for -Xbootclasspath/p: and -Xbootclasspath/a:.
+     * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH.
+     * Various options are supported for different components of the
+     * platform class path.
+     * Setting a value with setLocation overrides all existing option values.
+     * Setting any option overrides any value set with setLocation, and
+     * reverts to using default values for options that have not been set.
+     * Setting -bootclasspath or -Xbootclasspath overrides any existing
+     * value for -Xbootclasspath/p: and -Xbootclasspath/a:.
      */
-    private class BootClassPathLocationHandler extends LocationHandler {
+    private class BootClassPathLocationHandler extends BasicLocationHandler {
 
         private Collection<Path> searchPath;
         final Map<Option, String> optionValues = new EnumMap<>(Option.class);
@@ -579,13 +680,13 @@
         }
 
         @Override
-        Collection<Path> getLocation() {
+        Collection<Path> getPaths() {
             lazy();
             return searchPath;
         }
 
         @Override
-        void setLocation(Iterable<? extends Path> files) {
+        void setPaths(Iterable<? extends Path> files) {
             if (files == null) {
                 searchPath = null;  // reset to "uninitialized"
             } else {
@@ -597,8 +698,6 @@
         }
 
         SearchPath computePath() throws IOException {
-            String java_home = System.getProperty("java.home");
-
             SearchPath path = new SearchPath();
 
             String bootclasspathOpt = optionValues.get(BOOTCLASSPATH);
@@ -618,7 +717,7 @@
                 path.addFiles(bootclasspathOpt);
             } else {
                 // Standard system classes for this compiler's release.
-                Collection<Path> systemClasses = systemClasses(java_home);
+                Collection<Path> systemClasses = systemClasses();
                 if (systemClasses != null) {
                     path.addFiles(systemClasses, false);
                 } else {
@@ -637,7 +736,7 @@
                 path.addDirectories(extdirsOpt);
             } else {
                 // Add lib/jfxrt.jar to the search path
-               Path jfxrt = Paths.get(java_home, "lib", "jfxrt.jar");
+               Path jfxrt = javaHome.resolve("lib/jfxrt.jar");
                 if (Files.exists(jfxrt)) {
                     path.addFile(jfxrt, false);
                 }
@@ -658,21 +757,14 @@
          *
          * @throws UncheckedIOException if an I/O errors occurs
          */
-        private Collection<Path> systemClasses(String java_home) throws IOException {
-            // Return .jimage files if available
-            Path libModules = Paths.get(java_home, "lib", "modules");
-            if (Files.exists(libModules)) {
-                try (Stream<Path> files = Files.list(libModules)) {
-                    boolean haveJImageFiles =
-                            files.anyMatch(f -> f.getFileName().toString().endsWith(".jimage"));
-                    if (haveJImageFiles) {
-                        return addAdditionalBootEntries(Collections.singleton(JRT_MARKER_FILE));
-                    }
-                }
+        private Collection<Path> systemClasses() throws IOException {
+            // Return "modules" jimage file if available
+            if (Files.isRegularFile(thisSystemModules)) {
+                return addAdditionalBootEntries(Collections.singleton(thisSystemModules));
             }
 
             // Exploded module image
-            Path modules = Paths.get(java_home, "modules");
+            Path modules = javaHome.resolve("modules");
             if (Files.isDirectory(modules.resolve("java.base"))) {
                 try (Stream<Path> listedModules = Files.list(modules)) {
                     return addAdditionalBootEntries(listedModules.collect(Collectors.toList()));
@@ -686,18 +778,18 @@
         //ensure bootclasspath prepends/appends are reflected in the systemClasses
         private Collection<Path> addAdditionalBootEntries(Collection<Path> modules) throws IOException {
             String files = System.getProperty("sun.boot.class.path");
-
             if (files == null)
                 return modules;
 
             Set<Path> paths = new LinkedHashSet<>();
 
+            // The JVM no longer supports -Xbootclasspath/p:, so any interesting
+            // entries should be appended to the set of modules.
+
+            paths.addAll(modules);
+
             for (String s : files.split(Pattern.quote(File.pathSeparator))) {
-                if (s.endsWith(".jimage")) {
-                    paths.addAll(modules);
-                } else if (!s.isEmpty()) {
-                    paths.add(Paths.get(s));
-                }
+                paths.add(Paths.get(s));
             }
 
             return paths;
@@ -715,6 +807,690 @@
         }
     }
 
+    /**
+     * A LocationHander to represent modules found from a module-oriented
+     * location such as MODULE_SOURCE_PATH, UPGRADE_MODULE_PATH,
+     * SYSTEM_MODULES and MODULE_PATH.
+     *
+     * The Location can be specified to accept overriding classes from the
+     * -Xpatch:dir parameter.
+     */
+    private class ModuleLocationHandler extends LocationHandler implements Location {
+        protected final String name;
+        protected final String moduleName;
+        protected final Collection<Path> searchPath;
+        protected final Collection<Path> searchPathWithOverrides;
+        protected final boolean output;
+
+        ModuleLocationHandler(String name, String moduleName, Collection<Path> searchPath,
+                boolean output, boolean allowOverrides) {
+            this.name = name;
+            this.moduleName = moduleName;
+            this.searchPath = searchPath;
+            this.output = output;
+
+            if (allowOverrides) {
+                if (patchMap != null) {
+                    SearchPath mPatch = patchMap.get(moduleName);
+                    if (mPatch != null) {
+                        SearchPath sp = new SearchPath();
+                        sp.addAll(mPatch);
+                        sp.addAll(searchPath);
+                        searchPathWithOverrides = sp;
+                    } else {
+                        searchPathWithOverrides = searchPath;
+                    }
+                } else {
+                     // for old style patch option; retained for transition
+                    Set<Path> overrides = new LinkedHashSet<>();
+                    if (moduleOverrideSearchPath != null) {
+                       for (Path p: moduleOverrideSearchPath) {
+                           Path o = p.resolve(moduleName);
+                           if (Files.isDirectory(o)) {
+                               overrides.add(o);
+                           }
+                       }
+                    }
+
+                    if (!overrides.isEmpty()) {
+                        overrides.addAll(searchPath);
+                        searchPathWithOverrides = overrides;
+                    } else {
+                        searchPathWithOverrides = searchPath;
+                    }
+                }
+            } else {
+                searchPathWithOverrides = searchPath;
+            }
+        }
+
+        @Override // defined by Location
+        public String getName() {
+            return name;
+        }
+
+        @Override // defined by Location
+        public boolean isOutputLocation() {
+            return output;
+        }
+
+        @Override // defined by LocationHandler
+        boolean handleOption(Option option, String value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override // defined by LocationHandler
+        Collection<Path> getPaths() {
+            // For now, we always return searchPathWithOverrides. This may differ from the
+            // JVM behavior if there is a module-info.class to be found in the overriding
+            // classes.
+            return searchPathWithOverrides;
+        }
+
+        @Override // defined by LocationHandler
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override // defined by LocationHandler
+        String inferModuleName() {
+            return moduleName;
+        }
+    }
+
+    /**
+     * A LocationHandler for simple module-oriented search paths,
+     * like UPGRADE_MODULE_PATH and MODULE_PATH.
+     */
+    private class ModulePathLocationHandler extends SimpleLocationHandler {
+        ModulePathLocationHandler(Location location, Option... options) {
+            super(location, options);
+        }
+
+        @Override
+        public boolean handleOption(Option option, String value) {
+            if (!options.contains(option)) {
+                return false;
+            }
+            setPaths(value == null ? null : getPathEntries(value));
+            return true;
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() {
+            if (searchPath == null)
+                return Collections.emptyList();
+
+            return () -> new ModulePathIterator();
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> paths) {
+            if (paths != null) {
+                for (Path p: paths) {
+                    checkValidModulePathEntry(p);
+                }
+            }
+            super.setPaths(paths);
+        }
+
+        private void checkValidModulePathEntry(Path p) {
+            if (Files.isDirectory(p)) {
+                // either an exploded module or a directory of modules
+                return;
+            }
+
+            String name = p.getFileName().toString();
+            int lastDot = name.lastIndexOf(".");
+            if (lastDot > 0) {
+                switch (name.substring(lastDot)) {
+                    case ".jar":
+                    case ".jmod":
+                        return;
+                }
+            }
+            throw new IllegalArgumentException(p.toString());
+        }
+
+        class ModulePathIterator implements Iterator<Set<Location>> {
+            Iterator<Path> pathIter = searchPath.iterator();
+            int pathIndex = 0;
+            Set<Location> next = null;
+
+            @Override
+            public boolean hasNext() {
+                if (next != null)
+                    return true;
+
+                while (next == null) {
+                    if (pathIter.hasNext()) {
+                        Path path = pathIter.next();
+                        if (Files.isDirectory(path)) {
+                            next = scanDirectory(path);
+                        } else {
+                            next = scanFile(path);
+                        }
+                        pathIndex++;
+                    } else
+                        return false;
+                }
+                return true;
+            }
+
+            @Override
+            public Set<Location> next() {
+                hasNext();
+                if (next != null) {
+                    Set<Location> result = next;
+                    next = null;
+                    return result;
+                }
+                throw new NoSuchElementException();
+            }
+
+            private Set<Location> scanDirectory(Path path) {
+                Set<Path> paths = new LinkedHashSet<>();
+                Path moduleInfoClass = null;
+                try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
+                    for (Path entry: stream) {
+                        if (entry.endsWith("module-info.class")) {
+                            moduleInfoClass = entry;
+                            break;  // no need to continue scanning
+                        }
+                        paths.add(entry);
+                    }
+                } catch (DirectoryIteratorException | IOException ignore) {
+                    log.error(Errors.LocnCantReadDirectory(path));
+                    return Collections.emptySet();
+                }
+
+                if (moduleInfoClass != null) {
+                    // It's an exploded module directly on the module path.
+                    // We can't infer module name from the directory name, so have to
+                    // read module-info.class.
+                    try {
+                        String moduleName = readModuleName(moduleInfoClass);
+                        String name = location.getName()
+                                + "[" + pathIndex + ":" + moduleName + "]";
+                        ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                                Collections.singleton(path), false, true);
+                        return Collections.singleton(l);
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(path));
+                        return Collections.emptySet();
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(path));
+                        return Collections.emptySet();
+                    }
+                }
+
+                // A directory of modules
+                Set<Location> result = new LinkedHashSet<>();
+                int index = 0;
+                for (Path entry : paths) {
+                    Pair<String,Path> module = inferModuleName(entry);
+                    if (module == null) {
+                        // diagnostic reported if necessary; skip to next
+                        continue;
+                    }
+                    String moduleName = module.fst;
+                    Path modulePath = module.snd;
+                    String name = location.getName()
+                            + "[" + pathIndex + "." + (index++) + ":" + moduleName + "]";
+                    ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                            Collections.singleton(modulePath), false, true);
+                    result.add(l);
+                }
+                return result;
+            }
+
+            private Set<Location> scanFile(Path path) {
+                Pair<String,Path> module = inferModuleName(path);
+                if (module == null) {
+                    // diagnostic reported if necessary
+                    return Collections.emptySet();
+                }
+                String moduleName = module.fst;
+                Path modulePath = module.snd;
+                String name = location.getName()
+                        + "[" + pathIndex + ":" + moduleName + "]";
+                ModuleLocationHandler l = new ModuleLocationHandler(name, moduleName,
+                        Collections.singleton(modulePath), false, true);
+                return Collections.singleton(l);
+            }
+
+            private Pair<String,Path> inferModuleName(Path p) {
+                if (Files.isDirectory(p)) {
+                    if (Files.exists(p.resolve("module-info.class"))) {
+                        String name = p.getFileName().toString();
+                        if (SourceVersion.isName(name))
+                            return new Pair<>(name, p);
+                    }
+                    return null;
+                }
+
+                if (p.getFileName().toString().endsWith(".jar")) {
+                    try (FileSystem fs = FileSystems.newFileSystem(p, null)) {
+                        Path moduleInfoClass = fs.getPath("module-info.class");
+                        if (Files.exists(moduleInfoClass)) {
+                            String moduleName = readModuleName(moduleInfoClass);
+                            return new Pair<>(moduleName, p);
+                        }
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(p));
+                        return null;
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    }
+
+                    //automatic module:
+                    String fn = p.getFileName().toString();
+                    //from ModulePath.deriveModuleDescriptor:
+
+                    // drop .jar
+                    String mn = fn.substring(0, fn.length()-4);
+
+                    // find first occurrence of -${NUMBER}. or -${NUMBER}$
+                    Matcher matcher = Pattern.compile("-(\\d+(\\.|$))").matcher(mn);
+                    if (matcher.find()) {
+                        int start = matcher.start();
+
+                        mn = mn.substring(0, start);
+                    }
+
+                    // finally clean up the module name
+                    mn =  mn.replaceAll("[^A-Za-z0-9]", ".")  // replace non-alphanumeric
+                            .replaceAll("(\\.)(\\1)+", ".")   // collapse repeating dots
+                            .replaceAll("^\\.", "")           // drop leading dots
+                            .replaceAll("\\.$", "");          // drop trailing dots
+
+
+                    if (!mn.isEmpty()) {
+                        return new Pair<>(mn, p);
+                    }
+
+                    log.error(Errors.LocnCantGetModuleNameForJar(p));
+                    return null;
+                }
+
+                if (p.getFileName().toString().endsWith(".jmod")) {
+                    try {
+                        FileSystem fs = fileSystems.get(p);
+                        if (fs == null) {
+                            URI uri = URI.create("jar:" + p.toUri());
+                            fs = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
+                            try {
+                                Path moduleInfoClass = fs.getPath("classes/module-info.class");
+                                String moduleName = readModuleName(moduleInfoClass);
+                                Path modulePath = fs.getPath("classes");
+                                fileSystems.put(p, fs);
+                                closeables.add(fs);
+                                fs = null; // prevent fs being closed in the finally clause
+                                return new Pair<>(moduleName, modulePath);
+                            } finally {
+                                if (fs != null)
+                                    fs.close();
+                            }
+                        }
+                    } catch (ProviderNotFoundException e) {
+                        // will be thrown if the file is not a valid zip file
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    } catch (ModuleNameReader.BadClassFile e) {
+                        log.error(Errors.LocnBadModuleInfo(p));
+                    } catch (IOException e) {
+                        log.error(Errors.LocnCantReadFile(p));
+                        return null;
+                    }
+                }
+
+                if (warn && false) {  // temp disable
+                    log.warning(Warnings.LocnUnknownFileOnModulePath(p));
+                }
+                return null;
+            }
+
+            private String readModuleName(Path path) throws IOException, ModuleNameReader.BadClassFile {
+                if (moduleNameReader == null)
+                    moduleNameReader = new ModuleNameReader();
+                return moduleNameReader.readModuleName(path);
+            }
+        }
+
+    }
+
+    private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
+
+        private Map<String, Location> moduleLocations;
+        private Map<Path, Location> pathLocations;
+
+
+        ModuleSourcePathLocationHandler() {
+            super(StandardLocation.MODULE_SOURCE_PATH,
+                    Option.MODULESOURCEPATH);
+        }
+
+        @Override
+        boolean handleOption(Option option, String value) {
+            init(value);
+            return true;
+        }
+
+        void init(String value) {
+            Collection<String> segments = new ArrayList<>();
+            for (String s: value.split(File.pathSeparator)) {
+                expandBraces(s, segments);
+            }
+
+            Map<String, Collection<Path>> map = new LinkedHashMap<>();
+            final String MARKER = "*";
+            for (String seg: segments) {
+                int markStart = seg.indexOf(MARKER);
+                if (markStart == -1) {
+                    add(map, Paths.get(seg), null);
+                } else {
+                    if (markStart == 0 || !isSeparator(seg.charAt(markStart - 1))) {
+                        throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
+                    }
+                    Path prefix = Paths.get(seg.substring(0, markStart - 1));
+                    Path suffix;
+                    int markEnd = markStart + MARKER.length();
+                    if (markEnd == seg.length()) {
+                        suffix = null;
+                    } else if (!isSeparator(seg.charAt(markEnd))
+                            || seg.indexOf(MARKER, markEnd) != -1) {
+                        throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
+                    } else {
+                        suffix = Paths.get(seg.substring(markEnd + 1));
+                    }
+                    add(map, prefix, suffix);
+                }
+            }
+
+            moduleLocations = new LinkedHashMap<>();
+            pathLocations = new LinkedHashMap<>();
+            map.forEach((k, v) -> {
+                String name = location.getName() + "[" + k + "]";
+                ModuleLocationHandler h = new ModuleLocationHandler(name, k, v, false, false);
+                moduleLocations.put(k, h);
+                v.forEach(p -> pathLocations.put(normalize(p), h));
+            });
+        }
+
+        private boolean isSeparator(char ch) {
+            // allow both separators on Windows
+            return (ch == File.separatorChar) || (ch == '/');
+        }
+
+        void add(Map<String, Collection<Path>> map, Path prefix, Path suffix) {
+            if (!Files.isDirectory(prefix)) {
+                if (warn) {
+                    String key = Files.exists(prefix)
+                            ? "dir.path.element.not.directory"
+                            : "dir.path.element.not.found";
+                    log.warning(Lint.LintCategory.PATH, key, prefix);
+                }
+                return;
+            }
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(prefix, path -> Files.isDirectory(path))) {
+                for (Path entry: stream) {
+                    Path path = (suffix == null) ? entry : entry.resolve(suffix);
+                    if (Files.isDirectory(path)) {
+                        String name = entry.getFileName().toString();
+                        Collection<Path> paths = map.get(name);
+                        if (paths == null)
+                            map.put(name, paths = new ArrayList<>());
+                        paths.add(path);
+                    }
+                }
+            } catch (IOException e) {
+                // TODO? What to do?
+                System.err.println(e);
+            }
+        }
+
+        private void expandBraces(String value, Collection<String> results) {
+            int depth = 0;
+            int start = -1;
+            String prefix = null;
+            String suffix = null;
+            for (int i = 0; i < value.length(); i++) {
+                switch (value.charAt(i)) {
+                    case '{':
+                        depth++;
+                        if (depth == 1) {
+                            prefix = value.substring(0, i);
+                            suffix = value.substring(getMatchingBrace(value, i) + 1);
+                            start = i + 1;
+                        }
+                        break;
+
+                    case ',':
+                        if (depth == 1) {
+                            String elem = value.substring(start, i);
+                            expandBraces(prefix + elem + suffix, results);
+                            start = i + 1;
+                        }
+                        break;
+
+                    case '}':
+                        switch (depth) {
+                            case 0:
+                                throw new IllegalArgumentException("mismatched braces");
+
+                            case 1:
+                                String elem = value.substring(start, i);
+                                expandBraces(prefix + elem + suffix, results);
+                                return;
+
+                            default:
+                                depth--;
+                        }
+                        break;
+                }
+            }
+            if (depth > 0)
+                throw new IllegalArgumentException("mismatched braces");
+            results.add(value);
+        }
+
+        int getMatchingBrace(String value, int offset) {
+            int depth = 1;
+            for (int i = offset + 1; i < value.length(); i++) {
+                switch (value.charAt(i)) {
+                    case '{':
+                        depth++;
+                        break;
+
+                    case '}':
+                        if (--depth == 0)
+                            return i;
+                        break;
+                }
+            }
+            throw new IllegalArgumentException("mismatched braces");
+        }
+
+        @Override
+        boolean isSet() {
+            return (moduleLocations != null);
+        }
+
+        @Override
+        Collection<Path> getPaths() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        Location getModuleLocation(String name) {
+            return (moduleLocations == null) ? null : moduleLocations.get(name);
+        }
+
+        @Override
+        Location getModuleLocation(Path dir) {
+            return (pathLocations == null) ? null : pathLocations.get(dir);
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() {
+            if (moduleLocations == null)
+                return Collections.emptySet();
+            Set<Location> locns = new LinkedHashSet<>();
+            moduleLocations.forEach((k, v) -> locns.add(v));
+            return Collections.singleton(locns);
+        }
+
+    }
+
+    private class SystemModulesLocationHandler extends BasicLocationHandler {
+        private Path javaHome;
+        private Path modules;
+        private Map<String, ModuleLocationHandler> systemModules;
+
+        SystemModulesLocationHandler() {
+            super(StandardLocation.SYSTEM_MODULES, Option.SYSTEM);
+            javaHome = Paths.get(System.getProperty("java.home"));
+        }
+
+        @Override
+        boolean handleOption(Option option, String value) {
+            if (!options.contains(option)) {
+                return false;
+            }
+
+            if (value == null) {
+                javaHome = Paths.get(System.getProperty("java.home"));
+            } else if (value.equals("none")) {
+                javaHome = null;
+            } else {
+                update(Paths.get(value));
+            }
+
+            modules = null;
+            return true;
+        }
+
+        @Override
+        Collection<Path> getPaths() {
+            return (javaHome == null) ? null : Collections.singleton(javaHome);
+        }
+
+        @Override
+        void setPaths(Iterable<? extends Path> files) throws IOException {
+            if (files == null) {
+                javaHome = null;
+            } else {
+                Iterator<? extends Path> pathIter = files.iterator();
+                if (!pathIter.hasNext()) {
+                    throw new IllegalArgumentException("empty path for directory"); // TODO: FIXME
+                }
+                Path dir = pathIter.next();
+                if (pathIter.hasNext()) {
+                    throw new IllegalArgumentException("path too long for directory"); // TODO: FIXME
+                }
+                if (!Files.exists(dir)) {
+                    throw new FileNotFoundException(dir + ": does not exist");
+                } else if (!Files.isDirectory(dir)) {
+                    throw new IOException(dir + ": not a directory");
+                }
+                update(dir);
+            }
+        }
+
+        private void update(Path p) {
+            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("jrt-fs.jar")) && !Files.exists(javaHome.resolve("modules")))
+                throw new IllegalArgumentException(p.toString());
+            javaHome = p;
+            modules = null;
+        }
+
+        private boolean isCurrentPlatform(Path p) {
+            Path jh = Paths.get(System.getProperty("java.home"));
+            try {
+                return Files.isSameFile(p, jh);
+            } catch (IOException ex) {
+                throw new IllegalArgumentException(p.toString(), ex);
+            }
+        }
+
+        @Override
+        Location getModuleLocation(String name) throws IOException {
+            initSystemModules();
+            return systemModules.get(name);
+        }
+
+        @Override
+        Iterable<Set<Location>> listModuleLocations() throws IOException {
+            initSystemModules();
+            Set<Location> locns = new LinkedHashSet<>();
+            for (Location l: systemModules.values())
+                locns.add(l);
+            return Collections.singleton(locns);
+        }
+
+        private void initSystemModules() throws IOException {
+            if (systemModules != null) {
+                return;
+            }
+
+            if (javaHome == null) {
+                systemModules = Collections.emptyMap();
+                return;
+            }
+
+            if (modules == null) {
+                try {
+                    URI jrtURI = URI.create("jrt:/");
+                    FileSystem jrtfs;
+
+                    if (isCurrentPlatform(javaHome)) {
+                        jrtfs = FileSystems.getFileSystem(jrtURI);
+                    } else {
+                        try {
+                            Map<String, String> attrMap =
+                                    Collections.singletonMap("java.home", javaHome.toString());
+                            jrtfs = FileSystems.newFileSystem(jrtURI, attrMap);
+                        } catch (ProviderNotFoundException ex) {
+                            URL javaHomeURL = javaHome.resolve("jrt-fs.jar").toUri().toURL();
+                            ClassLoader currentLoader = Locations.class.getClassLoader();
+                            URLClassLoader fsLoader =
+                                    new URLClassLoader(new URL[] {javaHomeURL}, currentLoader);
+
+                            jrtfs = FileSystems.newFileSystem(jrtURI, Collections.emptyMap(), fsLoader);
+
+                            closeables.add(fsLoader);
+                        }
+
+                        closeables.add(jrtfs);
+                    }
+
+                    modules = jrtfs.getPath("/modules");
+                } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
+                    modules = javaHome.resolve("modules");
+                    if (!Files.exists(modules))
+                        throw new IOException("can't find system classes", e);
+                }
+            }
+
+            systemModules = new LinkedHashMap<>();
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules, Files::isDirectory)) {
+                for (Path entry : stream) {
+                    String moduleName = entry.getFileName().toString();
+                    String name = location.getName() + "[" + moduleName + "]";
+                    ModuleLocationHandler h = new ModuleLocationHandler(name, moduleName,
+                            Collections.singleton(entry), false, true);
+                    systemModules.put(moduleName, h);
+                }
+            }
+        }
+    }
+
     Map<Location, LocationHandler> handlersForLocation;
     Map<Option, LocationHandler> handlersForOption;
 
@@ -722,17 +1498,23 @@
         handlersForLocation = new HashMap<>();
         handlersForOption = new EnumMap<>(Option.class);
 
-        LocationHandler[] handlers = {
+        BasicLocationHandler[] handlers = {
             new BootClassPathLocationHandler(),
             new ClassPathLocationHandler(),
             new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
             new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
-            new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D),
-            new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S),
-            new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
+            new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, Option.PROCESSORMODULEPATH),
+            new OutputLocationHandler(StandardLocation.CLASS_OUTPUT, Option.D),
+            new OutputLocationHandler(StandardLocation.SOURCE_OUTPUT, Option.S),
+            new OutputLocationHandler(StandardLocation.NATIVE_HEADER_OUTPUT, Option.H),
+            new ModuleSourcePathLocationHandler(),
+            // TODO: should UPGRADE_MODULE_PATH be merged with SYSTEM_MODULES?
+            new ModulePathLocationHandler(StandardLocation.UPGRADE_MODULE_PATH, Option.UPGRADEMODULEPATH),
+            new ModulePathLocationHandler(StandardLocation.MODULE_PATH, Option.MODULEPATH, Option.MP),
+            new SystemModulesLocationHandler(),
         };
 
-        for (LocationHandler h : handlers) {
+        for (BasicLocationHandler h : handlers) {
             handlersForLocation.put(h.location, h);
             for (Option o : h.options) {
                 handlersForOption.put(o, h);
@@ -740,14 +1522,56 @@
         }
     }
 
+    private SearchPath moduleOverrideSearchPath; // for old style patch option; retained for transition
+    private Map<String, SearchPath> patchMap;
+
     boolean handleOption(Option option, String value) {
-        LocationHandler h = handlersForOption.get(option);
-        return (h == null ? false : h.handleOption(option, value));
+        switch (option) {
+            case XPATCH:
+                if (value.contains("=")) {
+                    Map<String, SearchPath> map = new LinkedHashMap<>();
+                    for (String entry: value.split(",")) {
+                        int eq = entry.indexOf('=');
+                        if (eq > 0) {
+                            String mName = entry.substring(0, eq);
+                            SearchPath mPatchPath = new SearchPath()
+                                    .addFiles(entry.substring(eq + 1));
+                            boolean ok = true;
+                            for (Path p: mPatchPath) {
+                                Path mi = p.resolve("module-info.class");
+                                if (Files.exists(mi)) {
+                                    log.error(Errors.LocnModuleInfoNotAllowedOnPatchPath(mi));
+                                    ok = false;
+                                }
+                            }
+                            if (ok && !mPatchPath.isEmpty()) {
+                                map.computeIfAbsent(mName, (_x) -> new SearchPath())
+                                        .addAll(mPatchPath);
+                            }
+                        } else {
+                            log.error(Errors.LocnInvalidArgForXpatch(entry));
+                        }
+                    }
+                    patchMap = map;
+                } else {
+                     // for old style patch option; retained for transition
+                    moduleOverrideSearchPath = new SearchPath().addFiles(value);
+                }
+                return true;
+            default:
+                LocationHandler h = handlersForOption.get(option);
+                return (h == null ? false : h.handleOption(option, value));
+        }
+    }
+
+    boolean hasLocation(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? false : h.isSet());
     }
 
     Collection<Path> getLocation(Location location) {
         LocationHandler h = getHandler(location);
-        return (h == null ? null : h.getLocation());
+        return (h == null ? null : h.getPaths());
     }
 
     Path getOutputLocation(Location location) {
@@ -768,12 +1592,34 @@
             }
             handlersForLocation.put(location, h);
         }
-        h.setLocation(files);
+        h.setPaths(files);
+    }
+
+    Location getModuleLocation(Location location, String name) throws IOException {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.getModuleLocation(name));
+    }
+
+    Location getModuleLocation(Location location, Path dir) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.getModuleLocation(dir));
+    }
+
+    String inferModuleName(Location location) {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.inferModuleName());
+    }
+
+    Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+        LocationHandler h = getHandler(location);
+        return (h == null ? null : h.listModuleLocations());
     }
 
     protected LocationHandler getHandler(Location location) {
         Objects.requireNonNull(location);
-        return handlersForLocation.get(location);
+        return (location instanceof LocationHandler)
+                ? (LocationHandler) location
+                : handlersForLocation.get(location);
     }
 
     /**
@@ -785,4 +1631,12 @@
                 && (n.endsWith(".jar") || n.endsWith(".zip"));
     }
 
+    static Path normalize(Path p) {
+        try {
+            return p.toRealPath();
+        } catch (IOException e) {
+            return p.toAbsolutePath().normalize();
+        }
+    }
+
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java
new file mode 100644
index 0000000..558be48
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ModuleNameReader.java
@@ -0,0 +1,228 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.javac.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.sun.tools.javac.jvm.ClassFile;
+
+import static com.sun.tools.javac.jvm.ClassFile.*;
+
+
+/**
+ * Stripped down ClassReader, just sufficient to read module names from module-info.class files
+ * while analyzing the module path.
+ *
+ * <p>
+ * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
+ * your own risk. This code and its internal interfaces are subject to change or deletion without
+ * notice.</b>
+ */
+public class ModuleNameReader {
+    static class BadClassFile extends Exception {
+        private static final long serialVersionUID = 0;
+        BadClassFile(String msg) {
+            super(msg);
+        }
+    }
+
+    private static final int INITIAL_BUFFER_SIZE = 0x0fff0;
+
+    /** The buffer containing the currently read class file.
+     */
+    private byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+
+    /** The current input pointer.
+     */
+    private int bp;
+
+    /** The objects of the constant pool.
+     */
+    private Object[] poolObj;
+
+    /** For every constant pool entry, an index into buf where the
+     *  defining section of the entry is found.
+     */
+    private int[] poolIdx;
+
+    ModuleNameReader() {
+    }
+
+    String readModuleName(Path p) throws IOException, BadClassFile {
+        try (InputStream in = Files.newInputStream(p)) {
+            bp = 0;
+            buf = readInputStream(buf, in);
+
+            int magic = nextInt();
+            if (magic != JAVA_MAGIC)
+                throw new BadClassFile("illegal.start.of.class.file");
+
+            int minorVersion = nextChar();
+            int majorVersion = nextChar();
+
+            indexPool();
+
+            int accessflags = nextChar();
+            return readModuleInfoName(nextChar());
+        }
+    }
+
+    /** Extract a character at position bp from buf.
+     */
+    char getChar(int bp) {
+        return
+            (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
+    }
+
+    /** Read a character.
+     */
+    char nextChar() {
+        return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+    }
+
+    /** Read an integer.
+     */
+    int nextInt() {
+        return
+            ((buf[bp++] & 0xFF) << 24) +
+            ((buf[bp++] & 0xFF) << 16) +
+            ((buf[bp++] & 0xFF) << 8) +
+            (buf[bp++] & 0xFF);
+    }
+
+    /** Index all constant pool entries, writing their start addresses into
+     *  poolIdx.
+     */
+    void indexPool() throws BadClassFile {
+        poolIdx = new int[nextChar()];
+        poolObj = new Object[poolIdx.length];
+        int i = 1;
+        while (i < poolIdx.length) {
+            poolIdx[i++] = bp;
+            byte tag = buf[bp++];
+            switch (tag) {
+            case CONSTANT_Utf8: case CONSTANT_Unicode: {
+                int len = nextChar();
+                bp = bp + len;
+                break;
+            }
+            case CONSTANT_Class:
+            case CONSTANT_String:
+            case CONSTANT_MethodType:
+                bp = bp + 2;
+                break;
+            case CONSTANT_MethodHandle:
+                bp = bp + 3;
+                break;
+            case CONSTANT_Fieldref:
+            case CONSTANT_Methodref:
+            case CONSTANT_InterfaceMethodref:
+            case CONSTANT_NameandType:
+            case CONSTANT_Integer:
+            case CONSTANT_Float:
+            case CONSTANT_InvokeDynamic:
+                bp = bp + 4;
+                break;
+            case CONSTANT_Long:
+            case CONSTANT_Double:
+                bp = bp + 8;
+                i++;
+                break;
+            default:
+                throw new BadClassFile("malformed constant pool");
+            }
+        }
+    }
+
+    /** 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.
+     */
+    String readModuleInfoName(int i) throws BadClassFile {
+        int classIndex = poolIdx[i];
+        if (buf[classIndex] == CONSTANT_Class) {
+            int utf8Index = poolIdx[getChar(classIndex + 1)];
+            if (buf[utf8Index] == CONSTANT_Utf8) {
+                int len = getChar(utf8Index + 1);
+                int start = utf8Index + 3;
+                String suffix = "/module-info";
+                if (endsWith(buf, start, len, suffix))
+                    return new String(ClassFile.internalize(buf, start, len - suffix.length()));
+            }
+        }
+        throw new BadClassFile("bad module-info name");
+    }
+
+    private boolean endsWith(byte[] buf, int start, int len, String suffix) {
+        if (len <= suffix.length())
+            return false;
+        for (int i = 0; i < suffix.length(); i++) {
+            if (buf[start + len - suffix.length() + i] != suffix.charAt(i))
+                return false;
+        }
+        return true;
+    }
+
+    private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
+        try {
+            buf = ensureCapacity(buf, s.available());
+            int r = s.read(buf);
+            int bp = 0;
+            while (r != -1) {
+                bp += r;
+                buf = ensureCapacity(buf, bp);
+                r = s.read(buf, bp, buf.length - bp);
+            }
+            return buf;
+        } finally {
+            try {
+                s.close();
+            } catch (IOException e) {
+                /* Ignore any errors, as this stream may have already
+                 * thrown a related exception which is the one that
+                 * should be reported.
+                 */
+            }
+        }
+    }
+
+    /*
+     * ensureCapacity will increase the buffer as needed, taking note that
+     * the new buffer will always be greater than the needed and never
+     * exactly equal to the needed size or bp. If equal then the read (above)
+     * will infinitely loop as buf.length - bp == 0.
+     */
+    private static byte[] ensureCapacity(byte[] buf, int needed) {
+        if (buf.length <= needed) {
+            byte[] old = buf;
+            buf = new byte[Integer.highestOneBit(needed) << 1];
+            System.arraycopy(old, 0, buf, 0, old.length);
+        }
+        return buf;
+    }
+}
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 60f12fc..3ef115f 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
@@ -107,9 +107,8 @@
         V49(49, 0),   // JDK 1.5: enum, generics, annotations
         V50(50, 0),   // JDK 1.6: stackmaps
         V51(51, 0),   // JDK 1.7
-        V52(52, 0);   // JDK 1.8: lambda, type annos, param names
-        // JDK9 still marked as V52 // V53(53, 0);   // JDK 1.9
-
+        V52(52, 0),   // JDK 1.8: lambda, type annos, param names
+        V53(52, 0);   // JDK 1.9: modules  **** FIXME TO 53 BEFORE RELEASE *****
         Version(int major, int minor) {
             this.major = major;
             this.minor = minor;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
index 0d0ca8a..56bca42 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
@@ -44,6 +44,7 @@
 import com.sun.tools.javac.comp.Annotate;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.*;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -100,6 +101,10 @@
      */
     boolean allowSimplifiedVarargs;
 
+    /** Switch: allow modules.
+     */
+    boolean allowModules;
+
    /** Lint option: warn about classfile issues
      */
     boolean lintClassfile;
@@ -137,6 +142,9 @@
      */
     protected WriteableScope typevars;
 
+    private List<InterimUsesDirective> interimUses = List.nil();
+    private List<InterimProvidesDirective> interimProvides = List.nil();
+
     /** The path name of the class file currently being read.
      */
     protected JavaFileObject currentClassFile = null;
@@ -145,6 +153,10 @@
      */
     protected Symbol currentOwner = null;
 
+    /** The module containing the class currently being read.
+     */
+    protected ModuleSymbol currentModule = null;
+
     /** The buffer containing the currently read class file.
      */
     byte[] buf = new byte[INITIAL_BUFFER_SIZE];
@@ -228,6 +240,7 @@
 
         Source source = Source.instance(context);
         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
+        allowModules     = source.allowModules();
 
         saveParameterNames = options.isSet("save-parameter-names");
 
@@ -478,7 +491,7 @@
         // simplified to (buf[start] == '[')
         return (buf[start] == '[' || buf[start + len - 1] == ';')
             ? (Object)sigToType(buf, start, len)
-            : (Object)syms.enterClass(names.fromUtf(internalize(buf, start,
+            : (Object)enterClass(names.fromUtf(internalize(buf, start,
                                                            len)));
     }
 
@@ -500,6 +513,23 @@
         return (ClassSymbol)obj;
     }
 
+    Name readClassName(int i) {
+        int index = poolIdx[i];
+        if (index == 0) return null;
+        byte tag = buf[index];
+        if (tag != CONSTANT_Class) {
+            throw badClassFile("bad.const.pool.entry",
+                               currentClassFile.toString(),
+                               "CONSTANT_Class_info", i);
+        }
+        int nameIndex =  poolIdx[getChar(index + 1)];
+        int len = getChar(nameIndex + 1);
+        int start = nameIndex + 3;
+        if (buf[start] == '[' || buf[start + len - 1] == ';')
+            throw badClassFile("wrong class name"); //TODO: proper diagnostics
+        return names.fromUtf(internalize(buf, start, len));
+    }
+
     /** Read name.
      */
     Name readName(int i) {
@@ -522,6 +552,34 @@
         return (NameAndType)obj;
     }
 
+    /** 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.
+     */
+    Name readModuleInfoName(int i) {
+        int classIndex = poolIdx[i];
+        if (buf[classIndex] == CONSTANT_Class) {
+            int utf8Index = poolIdx[getChar(classIndex + 1)];
+            if (buf[utf8Index] == CONSTANT_Utf8) {
+                int len = getChar(utf8Index + 1);
+                int start = utf8Index + 3;
+                return names.fromUtf(internalize(buf, start, len));
+            }
+        }
+        throw badClassFile("bad.module-info.name");
+    }
+
+    /** Read requires_flags.
+     */
+    Set<RequiresFlag> readRequiresFlags(int flags) {
+        Set<RequiresFlag> set = EnumSet.noneOf(RequiresFlag.class);
+        for (RequiresFlag f: RequiresFlag.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
 /************************************************************************
  * Reading Types
  ***********************************************************************/
@@ -660,7 +718,7 @@
             switch (c) {
 
             case ';': {         // end
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
 
@@ -674,7 +732,7 @@
             }
 
             case '<':           // generic arguments
-                ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
+                ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
                 outer = new ClassType(outer, sigToTypes('>'), t) {
@@ -737,7 +795,7 @@
             case '.':
                 //we have seen an enclosing non-generic class
                 if (outer != Type.noType) {
-                    t = syms.enterClass(names.fromUtf(signatureBuffer,
+                    t = enterClass(names.fromUtf(signatureBuffer,
                                                  startSbp,
                                                  sbp - startSbp));
                     outer = new ClassType(outer, List.<Type>nil(), t);
@@ -941,7 +999,12 @@
             new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
-                    readInnerClasses(c);
+                    if (currentModule.module_info == c) {
+                        //prevent entering the classes too soon:
+                        skipInnerClasses();
+                    } else {
+                        readInnerClasses(c);
+                    }
                 }
             },
 
@@ -981,25 +1044,6 @@
                 }
             },
 
-            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
-                protected void read(Symbol sym, int attrlen) {
-                    int newbp = bp + attrlen;
-                    if (saveParameterNames) {
-                        sawMethodParameters = true;
-                        int numEntries = nextByte();
-                        parameterNameIndices = new int[numEntries];
-                        haveParameterNameIndices = true;
-                        for (int i = 0; i < numEntries; i++) {
-                            int nameIndex = nextChar();
-                            int flags = nextChar();
-                            parameterNameIndices[i] = nameIndex;
-                        }
-                    }
-                    bp = newbp;
-                }
-            },
-
-
             new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
                     ClassSymbol c = (ClassSymbol) sym;
@@ -1130,12 +1174,109 @@
                 }
             },
 
-
             // The following attributes for a Code attribute are not currently handled
             // StackMapTable
             // SourceDebugExtension
             // LineNumberTable
             // LocalVariableTypeTable
+
+            // standard v52 attributes
+
+            new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
+                protected void read(Symbol sym, int attrlen) {
+                    int newbp = bp + attrlen;
+                    if (saveParameterNames) {
+                        sawMethodParameters = true;
+                        int numEntries = nextByte();
+                        parameterNameIndices = new int[numEntries];
+                        haveParameterNameIndices = true;
+                        for (int i = 0; i < numEntries; i++) {
+                            int nameIndex = nextChar();
+                            int flags = nextChar();
+                            parameterNameIndices[i] = nameIndex;
+                        }
+                    }
+                    bp = newbp;
+                }
+            },
+
+            // standard v53 attributes
+
+            new AttributeReader(names.Module, V53, CLASS_ATTRIBUTE) {
+                @Override
+                protected boolean accepts(AttributeKind kind) {
+                    return super.accepts(kind) && allowModules;
+                }
+                protected void read(Symbol sym, int attrLen) {
+                    if (sym.kind == TYP && sym.owner.kind == MDL) {
+                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
+                        ListBuffer<Directive> directives = new ListBuffer<>();
+
+                        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+                        int nrequires = nextChar();
+                        for (int i = 0; i < nrequires; i++) {
+                            Name name = readName(nextChar());
+                            ModuleSymbol rsym = syms.enterModule(name);
+                            Set<RequiresFlag> flags = readRequiresFlags(nextChar());
+                            requires.add(new RequiresDirective(rsym, flags));
+                        }
+                        msym.requires = requires.toList();
+                        directives.addAll(msym.requires);
+
+                        ListBuffer<ExportsDirective> exports = new ListBuffer<>();
+                        int nexports = nextChar();
+                        for (int i = 0; i < nexports; i++) {
+                            Name n = readName(nextChar());
+                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            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(readName(nextChar())));
+                                to = lb.toList();
+                            }
+                            exports.add(new ExportsDirective(p, to));
+                        }
+                        msym.exports = exports.toList();
+                        directives.addAll(msym.exports);
+
+                        msym.directives = directives.toList();
+
+                        ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
+                        int nuses = nextChar();
+                        for (int i = 0; i < nuses; i++) {
+                            Name srvc = readClassName(nextChar());
+                            uses.add(new InterimUsesDirective(srvc));
+                        }
+                        interimUses = uses.toList();
+
+                        ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
+                        int nprovides = nextChar();
+                        for (int i = 0; i < nprovides; i++) {
+                            Name srvc = readClassName(nextChar());
+                            Name impl = readClassName(nextChar());
+                            provides.add(new InterimProvidesDirective(srvc, impl));
+                        }
+                        interimProvides = provides.toList();
+                    }
+                }
+            },
+
+            new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) {
+                @Override
+                protected boolean accepts(AttributeKind kind) {
+                    return super.accepts(kind) && allowModules;
+                }
+                protected void read(Symbol sym, int attrLen) {
+                    if (sym.kind == TYP && sym.owner.kind == MDL) {
+                        ModuleSymbol msym = (ModuleSymbol) sym.owner;
+                        msym.version = readName(nextChar());
+                    }
+                }
+            },
         };
 
         for (AttributeReader r: readers)
@@ -1388,7 +1529,7 @@
         int index = poolIdx[i];
         int length = getChar(index + 1);
         if (buf[index + length + 2] != ';')
-            return syms.enterClass(readName(i)).type;
+            return enterClass(readName(i)).type;
         return readType(i);
     }
 
@@ -2175,6 +2316,16 @@
         }
     }
 
+    void skipInnerClasses() {
+        int n = nextChar();
+        for (int i = 0; i < n; i++) {
+            nextChar();
+            nextChar();
+            nextChar();
+            nextChar();
+        }
+    }
+
     /** Enter type variables of this classtype and all enclosing ones in
      *  `typevars'.
      */
@@ -2193,6 +2344,14 @@
         enterTypevars(sym.type);
     }
 
+    protected ClassSymbol enterClass(Name name) {
+        return syms.enterClass(currentModule, name);
+    }
+
+    protected ClassSymbol enterClass(Name name, TypeSymbol owner) {
+        return syms.enterClass(currentModule, name, owner);
+    }
+
     /** Read contents of a given class symbol `c'. Both external and internal
      *  versions of an inner class are read.
      */
@@ -2208,14 +2367,27 @@
             enterTypevars(ct.getEnclosingType());
 
         // read flags, or skip if this is an inner class
-        long flags = adjustClassFlags(nextChar());
-        if (c.owner.kind == PCK) c.flags_field = flags;
-
-        // read own class name and check that it matches
-        ClassSymbol self = readClassSymbol(nextChar());
-        if (c != self)
-            throw badClassFile("class.file.wrong.class",
-                               self.flatname);
+        long f = nextChar();
+        long flags = adjustClassFlags(f);
+        if ((flags & MODULE) == 0) {
+            if (c.owner.kind == PCK) c.flags_field = flags;
+            // read own class name and check that it matches
+            currentModule = c.packge().modle;
+            ClassSymbol self = readClassSymbol(nextChar());
+            if (c != self) {
+                throw badClassFile("class.file.wrong.class",
+                                   self.flatname);
+            }
+        } else {
+            c.flags_field = flags;
+            Name modInfoName = readModuleInfoName(nextChar());
+            if (c.owner.name == null) {
+                syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName));
+            } else {
+                // TODO: validate name
+            }
+            currentModule = (ModuleSymbol) c.owner;
+        }
 
         // class attributes must be read before class
         // skip ahead to read class attributes
@@ -2272,7 +2444,7 @@
             if (outer != null) { // we have a member class
                 if (name == names.empty)
                     name = names.one;
-                ClassSymbol member = syms.enterClass(name, outer);
+                ClassSymbol member = enterClass(name, outer);
                 if ((flags & STATIC) == 0) {
                     ((ClassType)member.type).setEnclosingType(outer.type);
                     if (member.erasure_field != null)
@@ -2354,11 +2526,24 @@
             } else {
                 c.setAnnotationTypeMetadata(AnnotationTypeMetadata.notAnAnnotationType());
             }
+
+            if (c == currentModule.module_info) {
+                if (interimUses.nonEmpty() || interimProvides.nonEmpty()) {
+                    Assert.check(currentModule.isCompleted());
+                    currentModule.usesProvidesCompleter =
+                            new UsesProvidesCompleter(currentModule, interimUses, interimProvides);
+                } else {
+                    currentModule.uses = List.nil();
+                    currentModule.provides = List.nil();
+                }
+            }
         } catch (IOException ex) {
             throw badClassFile("unable.to.access.file", ex.getMessage());
         } catch (ArrayIndexOutOfBoundsException ex) {
             throw badClassFile("bad.class.file", c.flatname);
         } finally {
+            interimUses = List.nil();
+            interimProvides = List.nil();
             missingTypeVariables = List.nil();
             foundTypeVariables = List.nil();
             filling = false;
@@ -2429,6 +2614,10 @@
     }
 
     long adjustClassFlags(long flags) {
+        if ((flags & ACC_MODULE) != 0) {
+            flags &= ~ACC_MODULE;
+            flags |= MODULE;
+        }
         return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
     }
 
@@ -2580,4 +2769,58 @@
             sym.getAnnotationTypeMetadata().setRepeatable(theRepeatable);
         }
     }
+
+    private static final class InterimUsesDirective {
+        public final Name service;
+
+        public InterimUsesDirective(Name service) {
+            this.service = service;
+        }
+
+    }
+
+    private static final class InterimProvidesDirective {
+        public final Name service;
+        public final Name impl;
+
+        public InterimProvidesDirective(Name service, Name impl) {
+            this.service = service;
+            this.impl = impl;
+        }
+
+    }
+
+    private final class UsesProvidesCompleter implements Completer {
+        private final ModuleSymbol currentModule;
+        private final List<InterimUsesDirective> interimUsesCopy;
+        private final List<InterimProvidesDirective> interimProvidesCopy;
+
+        public UsesProvidesCompleter(ModuleSymbol currentModule, List<InterimUsesDirective> interimUsesCopy, List<InterimProvidesDirective> interimProvidesCopy) {
+            this.currentModule = currentModule;
+            this.interimUsesCopy = interimUsesCopy;
+            this.interimProvidesCopy = interimProvidesCopy;
+        }
+
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            ListBuffer<Directive> directives = new ListBuffer<>();
+            directives.addAll(currentModule.directives);
+            ListBuffer<UsesDirective> uses = new ListBuffer<>();
+            for (InterimUsesDirective interim : interimUsesCopy) {
+                UsesDirective d = new UsesDirective(syms.enterClass(currentModule, interim.service));
+                uses.add(d);
+                directives.add(d);
+            }
+            currentModule.uses = uses.toList();
+            ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
+            for (InterimProvidesDirective interim : interimProvidesCopy) {
+                ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
+                                                            syms.enterClass(currentModule, interim.impl));
+                provides.add(d);
+                directives.add(d);
+            }
+            currentModule.provides = provides.toList();
+            currentModule.directives = directives.toList();
+        }
+    }
 }
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 aa161b5..3322d0f 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
@@ -33,10 +33,12 @@
 
 import javax.tools.JavaFileManager;
 import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
+import com.sun.tools.javac.code.Directive.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Types.UniqueType;
@@ -97,6 +99,12 @@
     /** Type utilities. */
     private Types types;
 
+    /**
+     * If true, class files will be written in module-specific subdirectories
+     * of the CLASS_OUTPUT location.
+     */
+    public boolean multiModuleMode;
+
     /** The initial sizes of the data and constant pool buffers.
      *  Sizes are increased when buffers get full.
      */
@@ -935,6 +943,58 @@
     }
 
 /**********************************************************************
+ * Writing module attributes
+ **********************************************************************/
+
+    /** Write the Module attribute if needed.
+     *  Returns the number of attributes written (0 or 1).
+     */
+    int writeModuleAttribute(ClassSymbol c) {
+        ModuleSymbol m = (ModuleSymbol) c.owner;
+
+        int alenIdx = writeAttr(names.Module);
+        ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+        for (RequiresDirective r: m.requires) {
+            if (!r.flags.contains(RequiresFlag.EXTRA))
+                requires.add(r);
+        }
+        databuf.appendChar(requires.size());
+        for (RequiresDirective r: requires) {
+            databuf.appendChar(pool.put(r.module.name));
+            databuf.appendChar(RequiresFlag.value(r.flags));
+        }
+
+        List<ExportsDirective> exports = m.exports;
+        databuf.appendChar(exports.size());
+        for (ExportsDirective e: exports) {
+            databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName()))));
+            if (e.modules == null) {
+                databuf.appendChar(0);
+            } else {
+                databuf.appendChar(e.modules.size());
+                for (ModuleSymbol msym: e.modules)
+                    databuf.appendChar(pool.put(msym.name));
+            }
+        }
+
+        List<UsesDirective> uses = m.uses;
+        databuf.appendChar(uses.size());
+        for (UsesDirective s: uses) {
+            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));
+        }
+
+        endAttr(alenIdx);
+        return 1;
+    }
+
+/**********************************************************************
  * Writing Objects
  **********************************************************************/
 
@@ -1564,9 +1624,17 @@
     public JavaFileObject writeClass(ClassSymbol c)
         throws IOException, PoolOverflow, StringOverflow
     {
+        String name = (c.owner.kind == MDL ? c.name : c.flatname).toString();
+        Location outLocn;
+        if (multiModuleMode) {
+            ModuleSymbol msym = c.owner.kind == MDL ? (ModuleSymbol) c.owner : c.packge().modle;
+            outLocn = fileManager.getModuleLocation(CLASS_OUTPUT, msym.name.toString());
+        } else {
+            outLocn = CLASS_OUTPUT;
+        }
         JavaFileObject outFile
-            = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
-                                               c.flatname.toString(),
+            = fileManager.getJavaFileForOutput(outLocn,
+                                               name,
                                                JavaFileObject.Kind.CLASS,
                                                c.sourcefile);
         OutputStream out = outFile.openOutputStream();
@@ -1604,11 +1672,17 @@
         List<Type> interfaces = types.interfaces(c.type);
         List<Type> typarams = c.type.getTypeArguments();
 
-        int flags = adjustFlags(c.flags() & ~DEFAULT);
-        if ((flags & PROTECTED) != 0) flags |= PUBLIC;
-        flags = flags & ClassFlags & ~STRICTFP;
-        if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
-        if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL;
+        int flags;
+        if (c.owner.kind == MDL) {
+            flags = ACC_MODULE;
+        } else {
+            flags = adjustFlags(c.flags() & ~DEFAULT);
+            if ((flags & PROTECTED) != 0) flags |= PUBLIC;
+            flags = flags & ClassFlags & ~STRICTFP;
+            if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
+            if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL;
+        }
+
         if (dumpClassModifiers) {
             PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
             pw.println();
@@ -1693,6 +1767,9 @@
         acount += writeJavaAnnotations(c.getRawAttributes());
         acount += writeTypeAnnotations(c.getRawTypeAttributes(), false);
         acount += writeEnclosingMethodAttribute(c);
+        if (c.owner.kind == MDL) {
+            acount += writeModuleAttribute(c);
+        }
         acount += writeExtraClassAttributes(c);
 
         poolbuf.appendInt(JAVA_MAGIC);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
index 38f1134..31cbda2 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/JNIWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -33,12 +33,14 @@
 
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.tools.javac.code.Attribute;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
@@ -82,6 +84,12 @@
      */
     private boolean checkAll;
 
+    /**
+     * If true, class files will be written in module-specific subdirectories
+     * of the NATIVE_HEADER_OUTPUT location.
+     */
+    public boolean multiModuleMode;
+
     private Context context;
 
     private static final boolean isWindows =
@@ -168,8 +176,15 @@
      */
     public FileObject write(ClassSymbol c) throws IOException {
         String className = c.flatName().toString();
+        Location outLocn;
+        if (multiModuleMode) {
+            ModuleSymbol msym = c.owner.kind == MDL ? (ModuleSymbol) c.owner : c.packge().modle;
+            outLocn = fileManager.getModuleLocation(StandardLocation.NATIVE_HEADER_OUTPUT, msym.name.toString());
+        } else {
+            outLocn = StandardLocation.NATIVE_HEADER_OUTPUT;
+        }
         FileObject outFile
-            = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
+            = fileManager.getFileForOutput(outLocn,
                 "", className.replaceAll("[.$]", "_") + ".h", null);
         PrintWriter out = new PrintWriter(outFile.openWriter());
         try {
@@ -675,5 +690,10 @@
         public R visitType(Type t, P p) {
             return defaultAction(t, p);
         }
+
+        @Override
+        public R visitModuleType(Type.ModuleType t, P p) {
+            return defaultAction(t, p);
+        }
     }
 }
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 5d79556..ea5d075 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
@@ -29,17 +29,24 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 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;
 
@@ -53,6 +60,8 @@
 import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
 import com.sun.tools.javac.platform.PlatformDescription;
 import com.sun.tools.javac.platform.PlatformUtils;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -77,6 +86,7 @@
     private Set<Path> files;
     private Map<Option, String> deferredFileManagerOptions;
     private Set<JavaFileObject> fileObjects;
+    private boolean emptyAllowed;
     private final Options options;
 
     private JavaFileManager fileManager;
@@ -248,14 +258,12 @@
      */
     public Set<JavaFileObject> getFileObjects() {
         if (fileObjects == null) {
-            if (files == null) {
-                fileObjects = Collections.emptySet();
-            } else {
-                fileObjects = new LinkedHashSet<>();
-                JavacFileManager jfm = (JavacFileManager) getFileManager();
-                for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files))
-                    fileObjects.add(fo);
-            }
+            fileObjects = new LinkedHashSet<>();
+        }
+        if (files != null) {
+            JavacFileManager jfm = (JavacFileManager) getFileManager();
+            for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files))
+                fileObjects.add(fo);
         }
         return fileObjects;
     }
@@ -291,8 +299,10 @@
         checkOptionAllowed(platformString == null,
                 option -> error("err.release.bootclasspath.conflict", option.getText()),
                 Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
-                Option.XBOOTCLASSPATH_PREPEND, Option.ENDORSEDDIRS, Option.EXTDIRS, Option.SOURCE,
-                Option.TARGET);
+                Option.XBOOTCLASSPATH_PREPEND,
+                Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
+                Option.EXTDIRS, Option.DJAVA_EXT_DIRS,
+                Option.SOURCE, Option.TARGET);
 
         if (platformString != null) {
             PlatformDescription platformDescription = PlatformUtils.lookupPlatformDescription(platformString);
@@ -396,13 +406,53 @@
      *      ILLEGAL_STATE
      */
     public boolean validate() {
+        JavaFileManager fm = getFileManager();
+        if (options.isSet(Option.M)) {
+            if (!fm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                log.error(Errors.OutputDirMustBeSpecifiedWithDashMOption);
+            } else if (!fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+                log.error(Errors.ModulesourcepathMustBeSpecifiedWithDashMOption);
+            } else {
+                java.util.List<String> modules = Arrays.asList(options.get(Option.M).split(","));
+                try {
+                    for (String module : modules) {
+                        Location sourceLoc = fm.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH, module);
+                        if (sourceLoc == null) {
+                            log.error(Errors.ModuleNotFoundInModuleSourcePath(module));
+                        } else {
+                            Location classLoc = fm.getModuleLocation(StandardLocation.CLASS_OUTPUT, module);
+
+                            for (JavaFileObject file : fm.list(sourceLoc, "", EnumSet.of(JavaFileObject.Kind.SOURCE), true)) {
+                                String className = fm.inferBinaryName(sourceLoc, file);
+                                JavaFileObject classFile = fm.getJavaFileForInput(classLoc, className, Kind.CLASS);
+
+                                if (classFile == null || classFile.getLastModified() < file.getLastModified()) {
+                                    if (fileObjects == null)
+                                        fileObjects = new HashSet<>();
+                                    fileObjects.add(file);
+                                }
+                            }
+                        }
+                    }
+                } catch (IOException ex) {
+                    log.printLines(PrefixKind.JAVAC, "msg.io");
+                    ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
+                    return false;
+                }
+            }
+        }
+
         if (isEmpty()) {
             // It is allowed to compile nothing if just asking for help or version info.
             // But also note that none of these options are supported in API mode.
             if (options.isSet(Option.HELP)
                 || options.isSet(Option.X)
                 || options.isSet(Option.VERSION)
-                || options.isSet(Option.FULLVERSION))
+                || options.isSet(Option.FULLVERSION)
+                || options.isSet(Option.M))
+                return true;
+
+            if (emptyAllowed)
                 return true;
 
             if (JavaCompiler.explicitAnnotationProcessingRequested(options)) {
@@ -423,6 +473,32 @@
             return false;
         }
 
+        // The following checks are to help avoid accidental confusion between
+        // directories of modules and exploded module directories.
+        if (fm instanceof StandardJavaFileManager) {
+            StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
+            if (sfm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                Path outDir = sfm.getLocationAsPaths(StandardLocation.CLASS_OUTPUT).iterator().next();
+                if (sfm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+                    // multi-module mode
+                    if (Files.exists(outDir.resolve("module-info.class"))) {
+                        log.error(Errors.MultiModuleOutdirCannotBeExplodedModule(outDir));
+                    }
+                } else {
+                    // single-module or legacy mode
+                    boolean lintPaths = options.isUnset(Option.XLINT_CUSTOM,
+                            "-" + LintCategory.PATH.option);
+                    if (lintPaths) {
+                        Path outDirParent = outDir.getParent();
+                        if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
+                            log.warning(LintCategory.PATH, Warnings.OutdirIsInExplodedModule(outDir));
+                        }
+                    }
+                }
+            }
+        }
+
+
         String sourceString = options.get(Option.SOURCE);
         Source source = (sourceString != null)
                 ? Source.lookup(sourceString)
@@ -471,10 +547,13 @@
             }
         }
 
+        if (options.isSet(Option.SOURCEPATH) && options.isSet(Option.MODULESOURCEPATH)) {
+            error("err.sourcepath.modulesourcepath.conflict");
+        }
+
         boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
 
         if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
-            JavaFileManager fm = getFileManager();
             if (fm instanceof BaseFileManager) {
                 if (((BaseFileManager) fm).isDefaultBootClassPath())
                     log.warning(LintCategory.OPTIONS, "source.no.bootclasspath", source.name);
@@ -484,22 +563,106 @@
         boolean obsoleteOptionFound = false;
 
         if (source.compareTo(Source.MIN) < 0) {
-            log.error("option.removed.source", source.name, Source.MIN.name);
+            log.error(Errors.OptionRemovedSource(source.name, Source.MIN.name));
         } else if (source == Source.MIN && lintOptions) {
-            log.warning(LintCategory.OPTIONS, "option.obsolete.source", source.name);
+            log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteSource(source.name));
             obsoleteOptionFound = true;
         }
 
         if (target.compareTo(Target.MIN) < 0) {
-            log.error("option.removed.target", target.name, Target.MIN.name);
+            log.error(Errors.OptionRemovedTarget(target.name, Target.MIN.name));
         } else if (target == Target.MIN && lintOptions) {
-            log.warning(LintCategory.OPTIONS, "option.obsolete.target", target.name);
+            log.warning(LintCategory.OPTIONS, Warnings.OptionObsoleteTarget(target.name));
             obsoleteOptionFound = true;
         }
 
+        final Target t = target;
+        checkOptionAllowed(t.compareTo(Target.JDK1_8) <= 0,
+                option -> error("err.option.not.allowed.with.target", option.getText(), t.name),
+                Option.BOOTCLASSPATH,
+                Option.XBOOTCLASSPATH_PREPEND, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
+                Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
+                Option.EXTDIRS, Option.DJAVA_EXT_DIRS);
+
+        checkOptionAllowed(t.compareTo(Target.JDK1_9) >= 0,
+                option -> error("err.option.not.allowed.with.target", option.getText(), t.name),
+                Option.MODULESOURCEPATH, Option.UPGRADEMODULEPATH,
+                Option.SYSTEM, Option.MODULEPATH, Option.ADDMODS, Option.LIMITMODS,
+                Option.XPATCH);
+
+        if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) {
+            if (!options.isSet(Option.PROC, "only")
+                    && !fm.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                log.error(Errors.NoOutputDir);
+            }
+            if (options.isSet(Option.XMODULE)) {
+                log.error(Errors.XmoduleNoModuleSourcepath);
+            }
+        }
+
+        if (fm.hasLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH) &&
+            fm.hasLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH)) {
+            log.error(Errors.ProcessorpathNoProcessormodulepath);
+        }
+
         if (obsoleteOptionFound)
             log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
 
+        String addExports = options.get(Option.XADDEXPORTS);
+        if (addExports != null) {
+            // Each entry must be of the form module/package=target-list where target-list is a
+            // comma-separated list of module or ALL-UNNAMED.
+            // All module/package pairs must be unique.
+            Pattern p = Pattern.compile("([^/]+)/([^=]+)=(.*)");
+            Map<String,List<String>> map = new LinkedHashMap<>();
+            for (String e: addExports.split("\0")) {
+                Matcher m = p.matcher(e);
+                if (!m.matches()) {
+                    log.error(Errors.XaddexportsMalformedEntry(e));
+                    continue;
+                }
+                String eModule = m.group(1);  // TODO: check a valid dotted identifier
+                String ePackage = m.group(2); // TODO: check a valid dotted identifier
+                String eTargets = m.group(3);  // TODO: check a valid list of dotted identifier or ALL-UNNAMED
+                String eModPkg = eModule + '/' + ePackage;
+                List<String> l = map.get(eModPkg);
+                map.put(eModPkg, (l == null) ? List.of(eTargets) : l.prepend(eTargets));
+            }
+            map.forEach((key, value) -> {
+                if (value.size() > 1) {
+                    log.error(Errors.XaddexportsTooMany(key));
+                    // TODO: consider adding diag fragments for the entries
+                }
+            });
+        }
+
+        String addReads = options.get(Option.XADDREADS);
+        if (addReads != null) {
+            // Each entry must be of the form module=source-list where source-list is a
+            // comma separated list of module or ALL-UNNAMED.
+            // All target modules (i.e. on left of '=')  must be unique.
+            Pattern p = Pattern.compile("([^=]+)=(.*)");
+            Map<String,List<String>> map = new LinkedHashMap<>();
+            for (String e: addReads.split("\0")) {
+                Matcher m = p.matcher(e);
+                if (!m.matches()) {
+                    log.error(Errors.XaddreadsMalformedEntry(e));
+                    continue;
+                }
+                String eModule = m.group(1);  // TODO: check a valid dotted identifier
+                String eSources = m.group(2);  // TODO: check a valid list of dotted identifier or ALL-UNNAMED
+                List<String> l = map.get(eModule);
+                map.put(eModule, (l == null) ? List.of(eSources) : l.prepend(eSources));
+            }
+            map.forEach((key, value) -> {
+                if (value.size() > 1) {
+                    log.error(Errors.XaddreadsTooMany(key));
+                    // TODO: consider adding diag fragments for the entries
+                }
+            });
+        }
+
+
         return !errors;
     }
 
@@ -513,6 +676,10 @@
                 && classNames.isEmpty();
     }
 
+    public void allowEmpty() {
+        this.emptyAllowed = true;
+    }
+
     /**
      * Gets the file manager options which may have been deferred
      * during processArgs.
@@ -626,6 +793,7 @@
     }
 
     private void report(String key, Object... args) {
+        // Would be good to have support for -XDrawDiagnostics here
         log.printRawLines(ownName + ": " + log.localize(PrefixKind.JAVAC, key, args));
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 4d3bc8b..4e5f801 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -39,6 +39,7 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ElementVisitor;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
@@ -67,12 +68,20 @@
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.JCDiagnostic.Factory;
 import com.sun.tools.javac.util.Log.WriterKind;
 
 import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.main.Option.*;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
+
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 /** This class could be the main entry point for GJC when GJC is used as a
@@ -276,6 +285,18 @@
      */
     protected Flow flow;
 
+    /** The modules visitor
+     */
+    protected Modules modules;
+
+    /** The module finder
+     */
+    protected ModuleFinder moduleFinder;
+
+    /** The diagnostics factory
+     */
+    protected JCDiagnostic.Factory diags;
+
     /** The type eraser.
      */
     protected TransTypes transTypes;
@@ -336,6 +357,8 @@
      **/
     protected boolean implicitSourceFilesRead;
 
+    protected boolean enterDone;
+
     protected CompileStates compileStates;
 
     /** Construct a new compiler using a shared context.
@@ -382,6 +405,9 @@
         annotate = Annotate.instance(context);
         types = Types.instance(context);
         taskListener = MultiTaskListener.instance(context);
+        modules = Modules.instance(context);
+        moduleFinder = ModuleFinder.instance(context);
+        diags = Factory.instance(context);
 
         finder.sourceCompleter = sourceCompleter;
 
@@ -430,6 +456,18 @@
 
         if (platformProvider != null)
             closeables = closeables.prepend(platformProvider);
+
+        silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
+            @DefinedBy(Api.LANGUAGE_MODEL)
+            public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+                return v.visitUnknown(this, p);
+            }
+            @Override
+            public boolean exists() {
+                return false;
+            }
+        };
+
     }
 
     /* Switches:
@@ -512,6 +550,11 @@
      */
     protected Set<JavaFileObject> inputFiles = new HashSet<>();
 
+    /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
+     *  an error has already been produced about that.
+     */
+    private final Symbol silentFail;
+
     protected boolean shouldStop(CompileState cs) {
         CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
             ? shouldStopPolicyIfError
@@ -625,18 +668,44 @@
      * @param name      The name to resolve
      */
     public Symbol resolveBinaryNameOrIdent(String name) {
+        ModuleSymbol msym;
+        String typeName;
+        int sep = name.indexOf('/');
+        if (sep == -1) {
+            msym = modules.getDefaultModule();
+            typeName = name;
+        } else if (source.allowModules() && !options.isSet("noModules")) {
+            Name modName = names.fromString(name.substring(0, sep));
+
+            msym = moduleFinder.findModule(modName);
+            typeName = name.substring(sep + 1);
+        } else {
+            log.error(Errors.InvalidModuleSpecifier(name));
+            return silentFail;
+        }
+
+        return resolveBinaryNameOrIdent(msym, typeName);
+    }
+
+    /** Resolve an identifier which may be the binary name of a class or
+     * the Java name of a class or package.
+     * @param msym      The module in which the search should be performed
+     * @param name      The name to resolve
+     */
+    public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
         try {
             Name flatname = names.fromString(name.replace("/", "."));
-            return finder.loadClass(flatname);
+            return finder.loadClass(msym, flatname);
         } catch (CompletionFailure ignore) {
-            return resolveIdent(name);
+            return resolveIdent(msym, name);
         }
     }
 
     /** Resolve an identifier.
+     * @param msym      The module in which the search should be performed
      * @param name      The identifier to resolve
      */
-    public Symbol resolveIdent(String name) {
+    public Symbol resolveIdent(ModuleSymbol msym, String name) {
         if (name.equals(""))
             return syms.errSymbol;
         JavaFileObject prev = log.useSource(null);
@@ -650,7 +719,8 @@
             }
             JCCompilationUnit toplevel =
                 make.TopLevel(List.<JCTree>nil());
-            toplevel.packge = syms.unnamedPackage;
+            toplevel.modle = msym;
+            toplevel.packge = msym.unnamedPackage;
             return attr.attribIdent(tree, toplevel);
         } finally {
             log.useSource(prev);
@@ -737,6 +807,16 @@
             taskListener.started(e);
         }
 
+        // Process module declarations.
+        // If module resolution fails, ignore trees, and if trying to
+        // complete a specific symbol, throw CompletionFailure.
+        // Note that if module resolution failed, we may not even
+        // have enough modules available to access java.lang, and
+        // so risk getting FatalError("no.java.lang") from MemberEnter.
+        if (!modules.enter(List.of(tree), c)) {
+            throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
+        }
+
         enter.complete(List.of(tree), c);
 
         if (!taskListener.isEmpty()) {
@@ -748,7 +828,16 @@
             boolean isPkgInfo =
                 tree.sourcefile.isNameCompatible("package-info",
                                                  JavaFileObject.Kind.SOURCE);
-            if (isPkgInfo) {
+            boolean isModuleInfo =
+                tree.sourcefile.isNameCompatible("module-info",
+                                                 JavaFileObject.Kind.SOURCE);
+            if (isModuleInfo) {
+                if (enter.getEnv(tree.modle) == null) {
+                    JCDiagnostic diag =
+                        diagFactory.fragment("file.does.not.contain.module");
+                    throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+                }
+            } else if (isPkgInfo) {
                 if (enter.getEnv(tree.packge) == null) {
                     JCDiagnostic diag =
                         diagFactory.fragment("file.does.not.contain.package",
@@ -812,8 +901,12 @@
 
             // These method calls must be chained to avoid memory leaks
             processAnnotations(
-                enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))),
-                classnames);
+                enterTrees(
+                        stopIfError(CompileState.PARSE,
+                                initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
+                ),
+                classnames
+            );
 
             // If it's safe to do so, skip attr / flow / gen for implicit classes
             if (taskListener.isEmpty() &&
@@ -912,7 +1005,20 @@
     public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
        if (shouldStop(CompileState.ATTR))
            return List.nil();
-        return enterTrees(roots);
+        return enterTrees(initModules(roots));
+    }
+
+    public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
+        List<JCCompilationUnit> result = initModules(roots, null);
+        if (roots.isEmpty()) {
+            enterDone = true;
+        }
+        return result;
+    }
+
+    List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
+        modules.enter(roots, c);
+        return roots;
     }
 
     /**
@@ -931,6 +1037,8 @@
 
         enter.main(roots);
 
+        enterDone = true;
+
         if (!taskListener.isEmpty()) {
             for (JCCompilationUnit unit: roots) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
@@ -1085,7 +1193,8 @@
                         if (sym == null ||
                             (sym.kind == PCK && !processPcks) ||
                             sym.kind == ABSENT_TYP) {
-                            log.error("proc.cant.find.class", nameStr);
+                            if (sym != silentFail)
+                                log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1100,10 +1209,10 @@
                                 continue;
                             }
                             Assert.check(sym.kind == PCK);
-                            log.warning("proc.package.does.not.exist", nameStr);
+                            log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
                             pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
                         } catch (CompletionFailure e) {
-                            log.error("proc.cant.find.class", nameStr);
+                            log.error(Errors.ProcCantFindClass(nameStr));
                             errors = true;
                             continue;
                         }
@@ -1154,6 +1263,7 @@
         return
             options.isSet(PROCESSOR) ||
             options.isSet(PROCESSORPATH) ||
+            options.isSet(PROCESSORMODULEPATH) ||
             options.isSet(PROC, "only") ||
             options.isSet(XPRINT);
     }
@@ -1388,14 +1498,14 @@
             make.at(Position.FIRSTPOS);
             TreeMaker localMake = make.forToplevel(env.toplevel);
 
-            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
+            if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
                 if (!(sourceOutput)) {
                     if (shouldStop(CompileState.LOWER))
-                       return;
-                    List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
-                    if (pdef.head != null) {
-                        Assert.check(pdef.tail.isEmpty());
-                        results.add(new Pair<>(env, (JCClassDecl)pdef.head));
+                        return;
+                    List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
+                    if (def.head != null) {
+                        Assert.check(def.tail.isEmpty());
+                        results.add(new Pair<>(env, (JCClassDecl)def.head));
                     }
                 }
                 return;
@@ -1589,6 +1699,10 @@
         }
     }
 
+    public boolean isEnterDone() {
+        return enterDone;
+    }
+
     /** Close the compiler, flushing the logs
      */
     public void close() {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
index 4d42113..187f6f7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java
@@ -27,6 +27,7 @@
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.nio.file.NoSuchFileException;
@@ -144,7 +145,8 @@
             try {
                 // A fresh context was created above, so jfm must be a JavacFileManager
                 ((JavacFileManager)fileManager).close();
-            } catch (IOException ignore) {
+            } catch (IOException ex) {
+                bugMessage(ex);
             }
         }
         return result;
@@ -204,11 +206,13 @@
         if (batchMode)
             CacheFSInfo.preRegister(context);
 
+        boolean ok = true;
+
         // init file manager
         fileManager = context.get(JavaFileManager.class);
         if (fileManager instanceof BaseFileManager) {
             ((BaseFileManager) fileManager).setContext(context); // reinit with options
-            ((BaseFileManager) fileManager).handleOptions(args.getDeferredFileManagerOptions());
+            ok &= ((BaseFileManager) fileManager).handleOptions(args.getDeferredFileManagerOptions());
         }
 
         // handle this here so it works even if no other options given
@@ -219,7 +223,7 @@
             showClass(showClass);
         }
 
-        boolean ok = args.validate();
+        ok &= args.validate();
         if (!ok || log.nerrors > 0)
             return Result.CMDERR;
 
@@ -348,28 +352,28 @@
     void showClass(String className) {
         PrintWriter pw = log.getWriter(WriterKind.NOTICE);
         pw.println("javac: show class: " + className);
+
         URL url = getClass().getResource('/' + className.replace('.', '/') + ".class");
-        if (url == null)
-            pw.println("  class not found");
-        else {
+        if (url != null) {
             pw.println("  " + url);
-            try {
-                final String algorithm = "MD5";
-                byte[] digest;
-                MessageDigest md = MessageDigest.getInstance(algorithm);
-                try (DigestInputStream in = new DigestInputStream(url.openStream(), md)) {
-                    byte[] buf = new byte[8192];
-                    int n;
-                    do { n = in.read(buf); } while (n > 0);
-                    digest = md.digest();
-                }
-                StringBuilder sb = new StringBuilder();
-                for (byte b: digest)
-                    sb.append(String.format("%02x", b));
-                pw.println("  " + algorithm + " checksum: " + sb);
-            } catch (NoSuchAlgorithmException | IOException e) {
-                pw.println("  cannot compute digest: " + e);
+        }
+
+        try (InputStream in = getClass().getResourceAsStream('/' + className.replace('.', '/') + ".class")) {
+            final String algorithm = "MD5";
+            byte[] digest;
+            MessageDigest md = MessageDigest.getInstance(algorithm);
+            try (DigestInputStream din = new DigestInputStream(in, md)) {
+                byte[] buf = new byte[8192];
+                int n;
+                do { n = din.read(buf); } while (n > 0);
+                digest = md.digest();
             }
+            StringBuilder sb = new StringBuilder();
+            for (byte b: digest)
+                sb.append(String.format("%02x", b));
+            pw.println("  " + algorithm + " checksum: " + sb);
+        } catch (NoSuchAlgorithmException | IOException e) {
+            pw.println("  cannot compute digest: " + e);
         }
     }
 
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 b48f516..cddbda4 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
@@ -184,6 +184,23 @@
 
     SOURCEPATH("-sourcepath", "opt.arg.path", "opt.sourcepath", STANDARD, FILEMANAGER),
 
+    MODULESOURCEPATH("-modulesourcepath", "opt.arg.mspath", "opt.modulesourcepath", STANDARD, FILEMANAGER),
+
+    MODULEPATH("-modulepath", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER),
+
+    MP("-mp", "opt.arg.path", "opt.modulepath", STANDARD, FILEMANAGER) {
+        @Override
+        public boolean process(OptionHelper helper, String option, String arg) {
+            return super.process(helper, "-modulepath", arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", "opt.arg.path", "opt.upgrademodulepath", STANDARD, FILEMANAGER),
+
+    SYSTEM("-system", "opt.arg.jdk", "opt.system", STANDARD, FILEMANAGER),
+
+    XPATCH("-Xpatch:", "opt.arg.path", "opt.Xpatch", EXTENDED, FILEMANAGER),
+
     BOOTCLASSPATH("-bootclasspath", "opt.arg.path", "opt.bootclasspath", STANDARD, FILEMANAGER) {
         @Override
         public boolean process(OptionHelper helper, String option, String arg) {
@@ -230,6 +247,8 @@
 
     PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
 
+    PROCESSORMODULEPATH("-processormodulepath", "opt.arg.path", "opt.processormodulepath", STANDARD, FILEMANAGER),
+
     PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
 
     D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
@@ -478,9 +497,9 @@
     PLUGIN("-Xplugin:", "opt.arg.plugin", "opt.plugin", EXTENDED, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option) {
-            String p = option.substring(option.indexOf(':') + 1);
+            String p = option.substring(option.indexOf(':') + 1).trim();
             String prev = helper.get(PLUGIN);
-            helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p.trim());
+            helper.put(PLUGIN.text, (prev == null) ? p : prev + '\0' + p);
             return false;
         }
     },
@@ -507,6 +526,106 @@
         }
     },
 
+    XADDEXPORTS("-XaddExports:", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            if (option.matches(".*,.*=.*")) { // temporary, for backwards compatibility
+                return processOldStyle(helper, option);
+            }
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String prev = helper.get(XADDEXPORTS);
+            helper.put(XADDEXPORTS.text, (prev == null) ? p : prev + '\0' + p);
+            return false;
+        }
+
+        // convert old style option into a series of new-style options
+        private boolean processOldStyle(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String[] entries = p.split("[ ,]+");
+            Map<String, String> map = new LinkedHashMap<>();
+            for (String e: entries) {
+                // Each entry is of the form   module/package=target
+                // we must group values for the same module/package together
+                int eq = e.indexOf('=');
+                if (eq == -1) {
+                    // don't bother with error message for backwards compatible support
+                    continue;
+                }
+                String modPkg = e.substring(0, eq);
+                String target = e.substring(eq + 1);
+                String targets = map.get(modPkg);
+                map.put(modPkg, (targets == null) ? target : targets + "," + target);
+            }
+            boolean ok = true;
+            for (Map.Entry<String, String> e: map.entrySet()) {
+                // process as new-style options
+                String key = e.getKey();
+                String value = e.getValue();
+                ok = ok & process(helper, XADDEXPORTS.text + key + "=" + value);
+            };
+            return ok;
+        }
+    },
+
+    XADDREADS("-XaddReads:", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            if (option.matches(".*,.*=.*")) { // temporary, for backwards compatibility
+                return processOldStyle(helper, option);
+            }
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String prev = helper.get(XADDREADS);
+            helper.put(XADDREADS.text, (prev == null) ? p : prev + '\0' + p);
+            return false;
+        }
+
+        // convert old style option into a series of new-style options
+        private boolean processOldStyle(OptionHelper helper, String option) {
+            String p = option.substring(option.indexOf(':') + 1).trim();
+            String[] entries = p.split("[ ,]+");
+            Map<String, String> map = new LinkedHashMap<>();
+            for (String e: entries) {
+                // Each entry is of the form   module=target
+                // we must group values for the same module together
+                int eq = e.indexOf('=');
+                if (eq == -1) {
+                    // don't bother with error message for backwards compatible support
+                    continue;
+                }
+                String modPkg = e.substring(0, eq);
+                String target = e.substring(eq + 1);
+                String targets = map.get(modPkg);
+                map.put(modPkg, (targets == null) ? target : targets + "," + target);
+            }
+            boolean ok = true;
+            for (Map.Entry<String, String> e: map.entrySet()) {
+                // process as new-style options
+                String key = e.getKey();
+                String value = e.getValue();
+                ok = ok & process(helper, XADDEXPORTS.text + key + "=" + value);
+            };
+            return ok;
+        }
+    },
+
+    XMODULE("-Xmodule:", "opt.arg.module", "opt.module", EXTENDED, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option) {
+            String prev = helper.get(XMODULE);
+            if (prev != null) {
+                helper.error("err.option.too.many", XMODULE.text);
+            }
+            String p = option.substring(option.indexOf(':') + 1);
+            helper.put(XMODULE.text, p);
+            return false;
+        }
+    },
+
+    M("-m", "opt.arg.m", "opt.m", STANDARD, BASIC),
+
+    ADDMODS("-addmods", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC),
+    LIMITMODS("-limitmods", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC),
+
     // This option exists only for the purpose of documenting itself.
     // It's actually implemented by the CommandLine class.
     AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) {
@@ -516,19 +635,19 @@
         }
     },
 
-    /*
-     * TODO: With apt, the matches method accepts anything if
-     * -XclassAsDecls is used; code elsewhere does the lookup to
-     * see if the class name is both legal and found.
-     *
-     * In apt, the process method adds the candidate class file
-     * name to a separate list.
-     */
+    // Standalone positional argument: source file or type name.
     SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
         @Override
         public boolean matches(String s) {
-            return s.endsWith(".java")  // Java source file
-                || SourceVersion.isName(s);   // Legal type name
+            if (s.endsWith(".java"))  // Java source file
+                return true;
+            int sep = s.indexOf('/');
+            if (sep != -1) {
+                return SourceVersion.isName(s.substring(0, sep))
+                        && SourceVersion.isName(s.substring(sep + 1));
+            } else {
+                return SourceVersion.isName(s);   // Legal type name
+            }
         }
         @Override
         public boolean process(OptionHelper helper, String option) {
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 feb4f33..5ff7cb8 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -34,6 +34,8 @@
 import javax.tools.JavaFileObject;
 import static javax.lang.model.util.ElementFilter.methodsIn;
 
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
@@ -52,6 +54,9 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
+import com.sun.tools.javac.comp.CompileStates;
+import com.sun.tools.javac.comp.CompileStates.CompileState;
+import com.sun.tools.javac.comp.Modules;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /**
@@ -66,9 +71,12 @@
 
     private final JavaCompiler javaCompiler;
     private final Symtab syms;
+    private final Modules modules;
     private final Names names;
     private final Types types;
     private final Enter enter;
+    private final JavacTaskImpl javacTaskImpl;
+    private final CompileStates compileStates;
 
     public static JavacElements instance(Context context) {
         JavacElements instance = context.get(JavacElements.class);
@@ -81,43 +89,66 @@
         context.put(JavacElements.class, this);
         javaCompiler = JavaCompiler.instance(context);
         syms = Symtab.instance(context);
+        modules = Modules.instance(context);
         names = Names.instance(context);
         types = Types.instance(context);
         enter = Enter.instance(context);
+        JavacTask t = context.get(JavacTask.class);
+        javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null;
+        compileStates = CompileStates.instance(context);
+    }
+
+    @Override @DefinedBy(Api.LANGUAGE_MODEL)
+    public ModuleSymbol getModuleElement(CharSequence name) {
+        ensureEntered("getModuleElement");
+        String strName = name.toString();
+        if (strName.equals(""))
+            return syms.unnamedModule;
+        return modules.getObservableModule(names.fromString(strName));
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
     public PackageSymbol getPackageElement(CharSequence name) {
+        ensureEntered("getPackageElement");
+        return getPackageElement(modules.getDefaultModule(), name);
+    }
+
+    public PackageSymbol getPackageElement(ModuleElement module, CharSequence name) {
         String strName = name.toString();
         if (strName.equals(""))
-            return syms.unnamedPackage;
+            return syms.unnamedModule.unnamedPackage;
         return SourceVersion.isName(strName)
-            ? nameToSymbol(strName, PackageSymbol.class)
+            ? nameToSymbol((ModuleSymbol) module, strName, PackageSymbol.class)
             : null;
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
     public ClassSymbol getTypeElement(CharSequence name) {
+        ensureEntered("getTypeElement");
+        return getTypeElement(modules.getDefaultModule(), name);
+    }
+
+    public ClassSymbol getTypeElement(ModuleElement module, CharSequence name) {
         String strName = name.toString();
         return SourceVersion.isName(strName)
-            ? nameToSymbol(strName, ClassSymbol.class)
+            ? nameToSymbol((ModuleSymbol) module, strName, ClassSymbol.class)
             : null;
     }
 
     /**
-     * Returns a symbol given the type's or packages's canonical name,
+     * Returns a symbol given the type's or package's canonical name,
      * or null if the name isn't found.
      */
-    private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) {
+    private <S extends Symbol> S nameToSymbol(ModuleSymbol module, String nameStr, Class<S> clazz) {
         Name name = names.fromString(nameStr);
         // First check cache.
         Symbol sym = (clazz == ClassSymbol.class)
-                    ? syms.classes.get(name)
-                    : syms.packages.get(name);
+                    ? syms.getClass(module, name)
+                    : syms.lookupPackage(module, name);
 
         try {
             if (sym == null)
-                sym = javaCompiler.resolveIdent(nameStr);
+                sym = javaCompiler.resolveIdent(module, nameStr);
 
             sym.complete();
 
@@ -334,6 +365,12 @@
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
+    public ModuleElement getModuleOf(Element e) {
+        Symbol sym = cast(Symbol.class, e);
+        return (sym.kind == MDL) ? ((ModuleElement) e) : sym.packge().modle;
+    }
+
+    @DefinedBy(Api.LANGUAGE_MODEL)
     public boolean isDeprecated(Element e) {
         Symbol sym = cast(Symbol.class, e);
         return (sym.flags() & Flags.DEPRECATED) != 0;
@@ -601,6 +638,15 @@
                 : null;
     }
 
+    private void ensureEntered(String methodName) {
+        if (javacTaskImpl != null) {
+            javacTaskImpl.ensureEntered();
+        }
+        if (!javaCompiler.isEnterDone()) {
+            throw new IllegalStateException("Cannot use Elements." + methodName + " before the TaskEvent.Kind.ENTER finished event.");
+        }
+    }
+
     /**
      * Returns an object cast to the specified type.
      * @throws NullPointerException if the object is {@code null}
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 9af4c19..c0b69a9 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
@@ -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
@@ -34,6 +34,7 @@
 import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
 import com.sun.tools.javac.resources.CompilerProperties;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
@@ -158,6 +159,7 @@
         this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
         this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast();
         this.allowTypeAnnotations = source.allowTypeAnnotations();
+        this.allowModules = source.allowModules();
         this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams();
         this.allowUnderscoreIdentifier = source.allowUnderscoreIdentifier();
         this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods();
@@ -206,6 +208,10 @@
      */
     boolean allowMethodReferences;
 
+    /** Switch: should we recognize modules?
+     */
+    boolean allowModules;
+
     /** Switch: should we allow default methods in interfaces?
      */
     boolean allowDefaultMethods;
@@ -3096,59 +3102,65 @@
         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 == 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));
+        if (token.kind == IDENTIFIER && token.name() == names.module) {
+            defs.append(moduleDecl(token.comment(CommentStyle.JAVADOC)));
             consumedToplevelDoc = true;
-            storeEnd(pd, token.pos);
-            defs.append(pd);
+        } 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;
+                }
+            }
         }
 
-        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;
-            }
-        }
         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());
         if (!consumedToplevelDoc)
             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
@@ -3163,6 +3175,75 @@
         return toplevel;
     }
 
+    JCModuleDecl moduleDecl(Comment dc) {
+        int pos = token.pos;
+        if (!allowModules) {
+            log.error(pos, Errors.ModulesNotSupportedInSource(source.name));
+            allowModules = true;
+        }
+
+        nextToken();
+        JCExpression name = qualident(false);
+        List<JCDirective> directives = null;
+
+        accept(LBRACE);
+        directives = moduleDirectiveList();
+        accept(RBRACE);
+        accept(EOF);
+
+        JCModuleDecl result = toP(F.at(pos).ModuleDef(name, directives));
+        attach(result, dc);
+        return result;
+    }
+
+    List<JCDirective> moduleDirectiveList() {
+        ListBuffer<JCDirective> defs = new ListBuffer<>();
+        while (token.kind == IDENTIFIER) {
+            int pos = token.pos;
+            if (token.name() == names.requires) {
+                nextToken();
+                boolean isPublic = false;
+                if (token.kind == PUBLIC) {
+                    isPublic = true;
+                    nextToken();
+                }
+                JCExpression moduleName = qualident(false);
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Requires(isPublic, moduleName)));
+            } else if (token.name() == names.exports) {
+                nextToken();
+                JCExpression pkgName = qualident(false);
+                List<JCExpression> moduleNames = null;
+                if (token.kind == IDENTIFIER && token.name() == names.to) {
+                    nextToken();
+                    moduleNames = qualidentList();
+                }
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Exports(pkgName, moduleNames)));
+            } else if (token.name() == names.provides) {
+                nextToken();
+                JCExpression serviceName = qualident(false);
+                if (token.kind == IDENTIFIER && token.name() == names.with) {
+                    nextToken();
+                    JCExpression implName = qualident(false);
+                    accept(SEMI);
+                    defs.append(toP(F.at(pos).Provides(serviceName, implName)));
+                } else {
+                    error(token.pos, "expected", "'" + names.with + "'");
+                    skip(false, false, false, false);
+                }
+            } else if (token.name() == names.uses) {
+                nextToken();
+                JCExpression service = qualident(false);
+                accept(SEMI);
+                defs.append(toP(F.at(pos).Uses(service)));
+            } else {
+                break;
+            }
+        }
+        return defs.toList();
+    }
+
     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
      */
     protected JCTree importDeclaration() {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index 9165f9b..30da707 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -27,8 +27,10 @@
 
 import java.io.Closeable;
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.file.Path;
@@ -42,6 +44,7 @@
 import javax.lang.model.util.*;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
 import javax.tools.StandardJavaFileManager;
 
 import static javax.tools.StandardLocation.*;
@@ -49,6 +52,7 @@
 import com.sun.source.util.TaskEvent;
 import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Types;
@@ -56,12 +60,14 @@
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.model.JavacTypes;
 import com.sun.tools.javac.platform.PlatformDescription;
 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.Abort;
@@ -77,10 +83,10 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.MatchingUtils;
+import com.sun.tools.javac.util.ModuleHelper;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Options;
-import com.sun.tools.javac.util.ServiceLoader;
 
 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -112,8 +118,10 @@
     private final JavacMessager messager;
     private final JavacElements elementUtils;
     private final JavacTypes typeUtils;
-    private final Types types;
     private final JavaCompiler compiler;
+    private final Modules modules;
+    private final ModuleHelper moduleHelper;
+    private final Types types;
 
     /**
      * Holds relevant state history of which processors have been
@@ -154,7 +162,10 @@
     Source source;
 
     private ClassLoader processorClassLoader;
-    private SecurityException processorClassLoaderException;
+    private ServiceLoader<Processor> serviceLoader;
+    private SecurityException processorLoaderException;
+
+    private final JavaFileManager fileManager;
 
     /**
      * JavacMessages object used for localization
@@ -167,6 +178,7 @@
     private final Enter enter;
     private final Completer initialCompleter;
     private final Check chk;
+    private final ModuleSymbol defaultModule;
 
     private final Context context;
 
@@ -196,6 +208,7 @@
         fatalErrors = options.isSet("fatalEnterError");
         showResolveErrors = options.isSet("showResolveErrors");
         werror = options.isSet(WERROR);
+        fileManager = context.get(JavaFileManager.class);
         platformAnnotations = initPlatformAnnotations();
 
         // Initialize services before any processors are initialized
@@ -204,6 +217,7 @@
         messager = new JavacMessager(context, this);
         elementUtils = JavacElements.instance(context);
         typeUtils = JavacTypes.instance(context);
+        modules = Modules.instance(context);
         types = Types.instance(context);
         processorOptions = initProcessorOptions();
         unmatchedProcessorOptions = initUnmatchedProcessorOptions();
@@ -214,7 +228,11 @@
         enter = Enter.instance(context);
         initialCompleter = ClassFinder.instance(context).getCompleter();
         chk = Check.instance(context);
-        initProcessorClassLoader();
+        moduleHelper = ModuleHelper.instance(context);
+        initProcessorLoader();
+
+        defaultModule = source.allowModules() && options.isUnset("noModules")
+                ? symtab.unnamedModule : symtab.noModule;
     }
 
     public void setProcessors(Iterable<? extends Processor> processors) {
@@ -234,19 +252,28 @@
         return Collections.unmodifiableSet(platformAnnotations);
     }
 
-    private void initProcessorClassLoader() {
-        JavaFileManager fileManager = context.get(JavaFileManager.class);
+    private void initProcessorLoader() {
         try {
-            // If processorpath is not explicitly set, use the classpath.
-            processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
-                ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
-                : fileManager.getClassLoader(CLASS_PATH);
+            if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+                try {
+                    serviceLoader = fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, Processor.class);
+                } catch (IOException e) {
+                    throw new Abort(e);
+                }
+            } else {
+                // If processorpath is not explicitly set, use the classpath.
+                processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
+                    ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
+                    : fileManager.getClassLoader(CLASS_PATH);
 
-            if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
-                compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+                moduleHelper.addExports(processorClassLoader);
+
+                if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
+                    compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+                }
             }
         } catch (SecurityException e) {
-            processorClassLoaderException = e;
+            processorLoaderException = e;
         }
     }
 
@@ -266,14 +293,18 @@
         } else if (processors != null) {
             processorIterator = processors.iterator();
         } else {
-            String processorNames = options.get(PROCESSOR);
-            if (processorClassLoaderException == null) {
+            if (processorLoaderException == null) {
                 /*
                  * If the "-processor" option is used, search the appropriate
                  * path for the named class.  Otherwise, use a service
                  * provider mechanism to create the processor iterator.
                  */
-                if (processorNames != null) {
+                String processorNames = options.get(PROCESSOR);
+                if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+                    processorIterator = (processorNames == null) ?
+                            new ServiceIterator(serviceLoader, log) :
+                            new NameServiceIterator(serviceLoader, log, processorNames);
+                } else if (processorNames != null) {
                     processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
                 } else {
                     processorIterator = new ServiceIterator(processorClassLoader, log);
@@ -286,7 +317,7 @@
                  * in service configuration file.) Otherwise, we cannot continue.
                  */
                 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
-                        processorClassLoaderException);
+                        processorLoaderException);
             }
         }
         PlatformDescription platformProvider = context.get(PlatformDescription.class);
@@ -304,6 +335,18 @@
         discoveredProcs = new DiscoveredProcessors(compoundIterator);
     }
 
+    public <S> ServiceLoader<S> getServiceLoader(Class<S> service) {
+        if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+            try {
+                return fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, service);
+            } catch (IOException e) {
+                throw new Abort(e);
+            }
+        } else {
+            return ServiceLoader.load(service, getProcessorClassLoader());
+        }
+    }
+
     /**
      * Returns an empty processor iterator if no processors are on the
      * relevant path, otherwise if processors are present, logs an
@@ -316,8 +359,6 @@
      * @param e   If non-null, pass this exception to Abort
      */
     private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
-        JavaFileManager fileManager = context.get(JavaFileManager.class);
-
         if (fileManager instanceof JavacFileManager) {
             StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
             Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
@@ -355,9 +396,9 @@
      * needed but unavailable.
      */
     private class ServiceIterator implements Iterator<Processor> {
-        private Iterator<Processor> iterator;
-        private Log log;
-        private ServiceLoader<Processor> loader;
+        Iterator<Processor> iterator;
+        Log log;
+        ServiceLoader<Processor> loader;
 
         ServiceIterator(ClassLoader classLoader, Log log) {
             this.log = log;
@@ -375,9 +416,16 @@
             }
         }
 
+        ServiceIterator(ServiceLoader<Processor> loader, Log log) {
+            this.log = log;
+            this.loader = loader;
+            this.iterator = loader.iterator();
+        }
+
+        @Override
         public boolean hasNext() {
             try {
-                return iterator.hasNext();
+                return internalHasNext();
             } catch(ServiceConfigurationError sce) {
                 log.error("proc.bad.config.file", sce.getLocalizedMessage());
                 throw new Abort(sce);
@@ -386,9 +434,14 @@
             }
         }
 
+        boolean internalHasNext() {
+            return iterator.hasNext();
+        }
+
+        @Override
         public Processor next() {
             try {
-                return iterator.next();
+                return internalNext();
             } catch (ServiceConfigurationError sce) {
                 log.error("proc.bad.config.file", sce.getLocalizedMessage());
                 throw new Abort(sce);
@@ -397,6 +450,11 @@
             }
         }
 
+        Processor internalNext() {
+            return iterator.next();
+        }
+
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
@@ -412,6 +470,58 @@
         }
     }
 
+    private class NameServiceIterator extends ServiceIterator {
+        private Map<String, Processor> namedProcessorsMap = new HashMap<>();;
+        private Iterator<String> processorNames = null;
+        private Processor nextProc = null;
+
+        public NameServiceIterator(ServiceLoader<Processor> loader, Log log, String theNames) {
+            super(loader, log);
+            this.processorNames = Arrays.asList(theNames.split(",")).iterator();
+        }
+
+        @Override
+        boolean internalHasNext() {
+            if (nextProc != null) {
+                return true;
+            }
+            if (!processorNames.hasNext()) {
+                namedProcessorsMap = null;
+                return false;
+            }
+            String processorName = processorNames.next();
+            Processor theProcessor = namedProcessorsMap.get(processorName);
+            if (theProcessor != null) {
+                namedProcessorsMap.remove(processorName);
+                nextProc = theProcessor;
+                return true;
+            } else {
+                while (iterator.hasNext()) {
+                    theProcessor = iterator.next();
+                    String name = theProcessor.getClass().getName();
+                    if (name.equals(processorName)) {
+                        nextProc = theProcessor;
+                        return true;
+                    } else {
+                        namedProcessorsMap.put(name, theProcessor);
+                    }
+                }
+                log.error(Errors.ProcProcessorNotFound(processorName));
+                return false;
+            }
+        }
+
+        @Override
+        Processor internalNext() {
+            if (hasNext()) {
+                Processor p = nextProc;
+                nextProc = null;
+                return p;
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+    }
 
     private static class NameProcessIterator implements Iterator<Processor> {
         Processor nextProc = null;
@@ -437,8 +547,10 @@
                     Processor processor;
                     try {
                         try {
+                            Class<?> processorClass = processorCL.loadClass(processorName);
+                            ensureReadable(processorClass);
                             processor =
-                                (Processor) (processorCL.loadClass(processorName).newInstance());
+                                (Processor) (processorClass.newInstance());
                         } catch (ClassNotFoundException cnfe) {
                             log.error("proc.processor.not.found", processorName);
                             return false;
@@ -473,6 +585,26 @@
         public void remove () {
             throw new UnsupportedOperationException();
         }
+
+        /**
+         * Ensures that the module of the given class is readable to this
+         * module.
+         */
+        private void ensureReadable(Class<?> targetClass) {
+            try {
+                Method getModuleMethod = Class.class.getMethod("getModule");
+                Object thisModule = getModuleMethod.invoke(this.getClass());
+                Object targetModule = getModuleMethod.invoke(targetClass);
+
+                Class<?> moduleClass = getModuleMethod.getReturnType();
+                Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+                addReadsMethod.invoke(thisModule, targetModule);
+            } catch (NoSuchMethodException e) {
+                // ignore
+            } catch (Exception e) {
+                throw new InternalError(e);
+            }
+        }
     }
 
     public boolean atLeastOneProcessor() {
@@ -605,7 +737,7 @@
     // TODO: These two classes can probably be rewritten better...
     /**
      * This class holds information about the processors that have
-     * been discoverd so far as well as the means to discover more, if
+     * been discovered so far as well as the means to discover more, if
      * necessary.  A single iterator should be used per round of
      * annotation processing.  The iterator first visits already
      * discovered processors then fails over to the service provider
@@ -1000,21 +1132,24 @@
                 if (file.getKind() != JavaFileObject.Kind.CLASS)
                     throw new AssertionError(file);
                 ClassSymbol cs;
+                // TODO: for now, we assume that generated code is in a default module;
+                // in time, we need a way to be able to specify the module for generated code
                 if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
                     Name packageName = Convert.packagePart(name);
-                    PackageSymbol p = symtab.enterPackage(packageName);
+                    PackageSymbol p = symtab.enterPackage(defaultModule, packageName);
                     if (p.package_info == null)
-                        p.package_info = symtab.enterClass(Convert.shortName(name), p);
+                        p.package_info = symtab.enterClass(defaultModule, Convert.shortName(name), p);
                     cs = p.package_info;
                     cs.reset();
                     if (cs.classfile == null)
                         cs.classfile = file;
                     cs.completer = initialCompleter;
                 } else {
-                    cs = symtab.enterClass(name);
+                    cs = symtab.enterClass(defaultModule, name);
                     cs.reset();
                     cs.classfile = file;
                     cs.completer = initialCompleter;
+                    cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
                 }
                 list = list.prepend(cs);
             }
@@ -1023,7 +1158,7 @@
 
         /** Enter a set of syntax trees. */
         private void enterTrees(List<JCCompilationUnit> roots) {
-            compiler.enterTrees(roots);
+            compiler.enterTrees(compiler.initModules(roots));
         }
 
         /** Run a processing round. */
@@ -1099,11 +1234,12 @@
             filer.newRound();
             messager.newRound();
             compiler.newRound();
+            modules.newRound();
             types.newRound();
 
             boolean foundError = false;
 
-            for (ClassSymbol cs : symtab.classes.values()) {
+            for (ClassSymbol cs : symtab.getAllClasses()) {
                 if (cs.kind == ERR) {
                     foundError = true;
                     break;
@@ -1111,7 +1247,7 @@
             }
 
             if (foundError) {
-                for (ClassSymbol cs : symtab.classes.values()) {
+                for (ClassSymbol cs : symtab.getAllClasses()) {
                     if (cs.classfile != null || cs.kind == ERR) {
                         cs.reset();
                         cs.type = new ClassType(cs.type.getEnclosingType(), null, cs);
@@ -1350,6 +1486,13 @@
                     }
                     node.packge.reset();
                 }
+                boolean isModuleInfo = node.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
+                if (isModuleInfo) {
+                    node.modle.reset();
+                    node.modle.completer = sym -> modules.enter(List.of(node), node.modle.module_info);
+                    node.modle.module_info.reset();
+                    node.modle.module_info.members_field = WriteableScope.create(node.modle.module_info);
+                }
                 node.packge = null;
                 topLevel = node;
                 try {
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 2194546..db73116 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
@@ -1,4 +1,3 @@
-
 #
 # Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -814,6 +813,10 @@
     {0} is not an annotation type
 
 # 0: symbol, 1: symbol
+compiler.err.not.def.access.package.cant.access=\
+    {0} is not visible because package {1} is not visible
+
+# 0: symbol, 1: symbol
 compiler.err.not.def.access.class.intf.cant.access=\
     {0} in {1} is defined in an inaccessible class or interface
 
@@ -1176,6 +1179,43 @@
 compiler.err.plugin.not.found=\
     plug-in not found: {0}
 
+# 0: path
+compiler.warn.locn.unknown.file.on.module.path=\
+    unknown file on module path: {0}
+
+
+# 0: path
+compiler.err.locn.bad.module-info=\
+    problem reading module-info.class in {0}
+
+# 0: path
+compiler.err.locn.cant.read.directory=\
+    cannot read directory {0}
+
+# 0: path
+compiler.err.locn.cant.read.file=\
+    cannot read file {0}
+
+# 0: path
+compiler.err.locn.cant.get.module.name.for.jar=\
+    cannot determine module name for {0}
+
+# 0: path
+compiler.err.multi-module.outdir.cannot.be.exploded.module=\
+    in multi-module mode, the output directory cannot be an exploded module: {0}
+
+# 0: path
+compiler.warn.outdir.is.in.exploded.module=\
+    the output directory is within an exploded module: {0}
+
+# 0: path
+compiler.err.locn.module-info.not.allowed.on.patch.path=\
+    module-info.class not allowed on patch path: {0}
+
+# 0: string
+compiler.err.locn.invalid.arg.for.xpatch=\
+    invalid argument for -Xpatch option: {0}
+
 #####
 
 # Fatal Errors
@@ -1379,6 +1419,10 @@
 compiler.warn.dir.path.element.not.found=\
     bad path element "{0}": no such directory
 
+# 0: file name
+compiler.warn.dir.path.element.not.directory=\
+    bad path element "{0}": not a directory
+
 compiler.warn.finally.cannot.complete=\
     finally clause cannot complete normally
 
@@ -1492,7 +1536,7 @@
     {0} attribute introduced in version {1}.{2} class files is ignored in version {3}.{4} class files
 
 # Warnings related to annotation processing
-# 0: name
+# 0: string
 compiler.warn.proc.package.does.not.exist=\
     package {0} does not exist
 
@@ -1733,6 +1777,9 @@
 compiler.misc.unnamed.package=\
     unnamed package
 
+compiler.misc.unnamed.module=\
+    unnamed module
+
 #####
 
 # 0: symbol, 1: message segment
@@ -1789,6 +1836,9 @@
 compiler.misc.bad.type.annotation.value=\
     bad type annotation target type value: {0}
 
+compiler.misc.bad.module-info.name=\
+    bad class name
+
 compiler.misc.class.file.wrong.class=\
     class file contains wrong class: {0}
 
@@ -1810,6 +1860,9 @@
 compiler.misc.file.does.not.contain.package=\
     file does not contain package {0}
 
+compiler.misc.file.does.not.contain.module=\
+    file does not contain module declaration
+
 compiler.misc.illegal.start.of.class.file=\
     illegal start of class file
 
@@ -2176,6 +2229,9 @@
 compiler.misc.kindname.package=\
     package
 
+compiler.misc.kindname.module=\
+    module
+
 compiler.misc.kindname.static.init=\
     static initializer
 
@@ -2278,6 +2334,12 @@
 ########################################
 # Diagnostics for language feature changes
 ########################################
+
+# 0: string
+compiler.err.modules.not.supported.in.source=\
+   modules are not supported in -source {0}\n\
+    (use -source 9 or higher to enable modules)
+
 # 0: string
 compiler.misc.diamond.and.anon.class.not.supported.in.source=\
     cannot use ''<>'' with anonymous inner classes in -source {0}\n\
@@ -2608,4 +2670,170 @@
 compiler.err.dc.unterminated.string=\
     unterminated string
 
+###
+# errors related to modules
 
+compiler.err.expected.module=\
+    expected ''module''
+
+# 0: symbol
+compiler.err.module.not.found=\
+    module not found: {0}
+
+compiler.err.too.many.modules=\
+    too many module declarations found
+
+# 0: symbol
+compiler.err.duplicate.module=\
+    duplicate module: {0}
+
+# 0: symbol
+compiler.err.duplicate.requires=\
+    duplicate requires: {0}
+
+# 0: symbol
+compiler.err.duplicate.exports=\
+    duplicate export: {0}
+
+# 0: symbol, 1: symbol
+compiler.err.duplicate.provides=\
+    duplicate provides: service {0}, implementation {1}
+
+# 0: symbol
+compiler.err.duplicate.uses=\
+    duplicate uses: {0}
+
+# 0: symbol
+compiler.err.service.implementation.is.abstract=\
+    the service implementation is an abstract class: {0}
+
+# 0: symbol
+compiler.err.service.implementation.is.inner=\
+    the service implementation is an inner class: {0}
+
+# 0: symbol
+compiler.err.service.definition.is.inner=\
+    the service definition is an inner class: {0}
+
+# 0: symbol
+compiler.err.service.implementation.doesnt.have.a.no.args.constructor=\
+    the service implementation does not have a default constructor: {0}
+
+# 0: symbol
+compiler.err.service.implementation.no.args.constructor.not.public=\
+    the no arguments constructor of the service implementation is not public: {0}
+
+# 0: symbol
+compiler.err.package.empty.or.not.found=\
+    package is empty or does not exist: {0}
+
+compiler.err.no.output.dir=\
+    no class output directory specified
+
+compiler.err.unnamed.pkg.not.allowed.named.modules=\
+    unnamed package is not allowed in named modules
+
+# 0: name, 1: name
+compiler.err.module.name.mismatch=\
+    module name {0} does not match expected name {1}
+
+compiler.err.module.decl.sb.in.module-info.java=\
+    module declarations should be in a file named module-info.java
+
+compiler.err.unexpected.after.module=\
+    unexpected input after module declaration
+
+compiler.err.module-info.with.xmodule.sourcepath=\
+    illegal combination of -Xmodule and module-info on sourcepath
+
+compiler.err.module-info.with.xmodule.classpath=\
+    illegal combination of -Xmodule and module-info on classpath
+
+compiler.err.xmodule.no.module.sourcepath=\
+    illegal combination of -Xmodule and -modulesourcepath
+
+compiler.err.processorpath.no.processormodulepath=\
+    illegal combination of -processorpath and -processormodulepath
+
+# 0: symbol
+compiler.err.package.in.other.module=\
+    package exists in another module: {0}
+
+# 0: symbol, 1: name, 2: symbol, 3: symbol
+compiler.err.package.clash.from.requires=\
+    module {0} reads package {1} from both {2} and {3}
+
+# 0: string
+compiler.err.module.not.found.in.module.source.path=\
+    module {0} not found in module source path
+
+compiler.err.output.dir.must.be.specified.with.dash.m.option=\
+    class output directory must be specified if -m option is used
+
+compiler.err.modulesourcepath.must.be.specified.with.dash.m.option=\
+    module source path must be specified if -m option is used
+
+# 0: symbol
+compiler.err.service.implementation.not.in.right.module=\
+    service implementation must be defined in the same module as the provides directive
+
+# 0: symbol
+compiler.err.cyclic.requires=\
+    cyclic dependence involving {0}
+
+# 0: fragment, 1: name
+compiler.err.duplicate.module.on.path=\
+    duplicate module on {0}\nmodule in {1}
+
+# 0:  string
+compiler.err.xaddexports.malformed.entry=\
+    bad value for -XaddExports: {0}
+
+# 0: string
+compiler.err.xaddexports.too.many=\
+    multiple -XaddExports options for {0}
+
+# 0:  string
+compiler.err.xaddreads.malformed.entry=\
+    bad value for -XaddReads: {0}
+
+# 0: string
+compiler.err.xaddreads.too.many=\
+    multiple -XaddReads options for {0}
+
+compiler.err.addmods.all.module.path.invalid=\
+    -addmods ALL-MODULE-PATH can only be used when compiling the unnamed module
+
+compiler.misc.locn.module_source_path=\
+    module source path
+
+compiler.misc.locn.upgrade_module_path=\
+    upgrade module path
+
+compiler.misc.locn.system_modules=\
+    system modules
+
+compiler.misc.locn.module_path=\
+    application module path
+
+compiler.misc.cant.resolve.modules=\
+    cannot resolve modules
+
+# 0: symbol
+compiler.err.cant.find.module=\
+    cannot find module: {0}
+
+# 0: string
+compiler.err.invalid.module.specifier=\
+    module specifier not allowed: {0}
+
+# 0: symbol
+compiler.warn.service.provided.but.not.exported.or.used=\
+    service interface provided but not exported or used
+
+###
+# errors related to options
+
+# 0: string, 1: string
+compiler.err.illegal.argument.for.option=\
+    illegal argument for {0}: {1}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
index 7246acf..3df72ad 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
@@ -39,20 +39,34 @@
     Output source locations where deprecated APIs are used
 javac.opt.classpath=\
     Specify where to find user class files and annotation processors
+javac.opt.modulepath=\
+    Specify where to find application modules
 javac.opt.sourcepath=\
     Specify where to find input source files
+javac.opt.m=\
+    Compile only the specified module, check timestamps
+javac.opt.modulesourcepath=\
+    Specify where to find input source files for multiple modules
 javac.opt.bootclasspath=\
     Override location of bootstrap class files
+javac.opt.system=\
+    Override location of system modules
+javac.opt.upgrademodulepath=\
+    Override location of upgradeable modules
 javac.opt.Xbootclasspath.p=\
     Prepend to the bootstrap class path
 javac.opt.Xbootclasspath.a=\
     Append to the bootstrap class path
+javac.opt.Xpatch=\
+    Specify location of module class files to patch
 javac.opt.endorseddirs=\
     Override location of endorsed standards path
 javac.opt.extdirs=\
     Override location of installed extensions
 javac.opt.processorpath=\
     Specify where to find annotation processors
+javac.opt.processormodulepath=\
+    Specify a module path where to find annotation processors
 javac.opt.processor=\
     Names of the annotation processors to run; bypasses default discovery process
 javac.opt.parameters=\
@@ -95,6 +109,12 @@
     key[=value]
 javac.opt.arg.path=\
     <path>
+javac.opt.arg.mspath=\
+    <module-source-path>
+javac.opt.arg.m=\
+    <module-name>
+javac.opt.arg.jdk=\
+    <jdk>|none
 javac.opt.arg.dirs=\
     <dirs>
 javac.opt.arg.directory=\
@@ -252,6 +272,29 @@
     Read options and filenames from file
 javac.opt.diags=\
     Select a diagnostic mode
+javac.opt.addExports=\n\
+\        Specify a package to be considered as exported from its defining module\n\
+\        to additional modules, or to all unnamed modules if <other-module> is ALL-UNNAMED.
+javac.opt.arg.addExports=\
+    <module>/<package>=<other-module>(,<other-module>)*
+javac.opt.addReads=\n\
+\        Specify additional modules to be considered as required by a given module.\n\
+\        <other-module> may be ALL-UNNAMED to require the unnamed module.
+javac.opt.arg.addReads=\
+    <module>=<other-module>(,<other-module>)*
+javac.opt.module=\
+    Specify a module to which the classes being compiled belong.
+javac.opt.arg.module=\
+    <module-name>
+javac.opt.addmods=\n\
+\        Root modules to resolve in addition to the initial modules, or all modules\n\
+\        on the module path if <module> is ALL-MODULE-PATH.
+javac.opt.arg.addmods=\
+    <module>(,<module>)*
+javac.opt.limitmods=\
+    Limit the universe of observable modules
+javac.opt.arg.limitmods=\
+    <module>(,<module>)*
 
 ## errors
 
@@ -269,6 +312,10 @@
     invalid profile: {0}
 javac.err.invalid.target=\
     invalid target release: {0}
+javac.err.option.not.allowed.with.target=\
+    option {0} not allowed with target {1}
+javac.err.option.too.many=\
+    option {0} can only be specified once
 javac.err.no.source.files=\
     no source files
 javac.err.no.source.files.classes=\
@@ -279,6 +326,8 @@
     invalid source release: {0}
 javac.err.error.writing.file=\
     error writing {0}; {1}
+javac.err.sourcepath.modulesourcepath.conflict=\
+    cannot specify both -sourcepath and -modulesourcepath
 javac.warn.source.target.conflict=\
     source release {0} requires target release {1}
 javac.warn.target.default.source.conflict=\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java
deleted file mode 100644
index acfb5bd..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/CreateSymbols.java
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.sym;
-
-import com.sun.tools.javac.api.JavacTaskImpl;
-import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Attribute;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.jvm.ClassWriter;
-import com.sun.tools.javac.jvm.Pool;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Names;
-import com.sun.tools.javac.util.Pair;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedOptions;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import static javax.tools.JavaFileObject.Kind.CLASS;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/**
- * Used to generate a "symbol file" representing rt.jar that only
- * includes supported or legacy proprietary API.  Valid annotation
- * processor options:
- *
- * <dl>
- * <dt>com.sun.tools.javac.sym.Jar</dt>
- * <dd>Specifies the location of rt.jar.</dd>
- * <dt>com.sun.tools.javac.sym.Dest</dt>
- * <dd>Specifies the destination directory.</dd>
- * </dl>
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own
- * risk.  This code and its internal interfaces are subject to change
- * or deletion without notice.</b></p>
- *
- * @author Peter von der Ah\u00e9
- */
-@SupportedOptions({
-    "com.sun.tools.javac.sym.Jar",
-    "com.sun.tools.javac.sym.Dest",
-    "com.sun.tools.javac.sym.Profiles"})
-@SupportedAnnotationTypes("*")
-public class CreateSymbols extends AbstractProcessor {
-
-    static Set<String> getLegacyPackages() {
-        ResourceBundle legacyBundle
-            = ResourceBundle.getBundle("com.sun.tools.javac.resources.legacy");
-        Set<String> keys = new HashSet<>();
-        for (Enumeration<String> e = legacyBundle.getKeys(); e.hasMoreElements(); )
-            keys.add(e.nextElement());
-        return keys;
-    }
-
-    @DefinedBy(Api.ANNOTATION_PROCESSING)
-    public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
-        try {
-            if (renv.processingOver())
-                createSymbols();
-        } catch (IOException e) {
-            CharSequence msg = e.getLocalizedMessage();
-            if (msg == null)
-                msg = e.toString();
-            processingEnv.getMessager()
-                .printMessage(Diagnostic.Kind.ERROR, msg);
-        } catch (Throwable t) {
-            t.printStackTrace();
-            Throwable cause = t.getCause();
-            if (cause == null)
-                cause = t;
-            CharSequence msg = cause.getLocalizedMessage();
-            if (msg == null)
-                msg = cause.toString();
-            processingEnv.getMessager()
-                .printMessage(Diagnostic.Kind.ERROR, msg);
-        }
-        return true;
-    }
-
-    void createSymbols() throws IOException {
-        Set<String> legacy = getLegacyPackages();
-        Set<String> legacyProprietary = getLegacyPackages();
-        Set<String> documented = new HashSet<>();
-        Set<PackageSymbol> packages =
-            ((JavacProcessingEnvironment)processingEnv).getSpecifiedPackages();
-        Map<String,String> pOptions = processingEnv.getOptions();
-        String jarName = pOptions.get("com.sun.tools.javac.sym.Jar");
-        if (jarName == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR");
-        String destName = pOptions.get("com.sun.tools.javac.sym.Dest");
-        if (destName == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR");
-        String profileSpec=pOptions.get("com.sun.tools.javac.sym.Profiles");
-        if (profileSpec == null)
-            throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Profiles=PROFILES_SPEC");
-        Profiles profiles = Profiles.read(new File(profileSpec));
-
-        for (PackageSymbol psym : packages) {
-            String name = psym.getQualifiedName().toString();
-            legacyProprietary.remove(name);
-            documented.add(name);
-        }
-
-        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
-        Location jarLocation = StandardLocation.locationFor(jarName);
-        File jarFile = new File(jarName);
-        fm.setLocation(jarLocation, List.of(jarFile));
-        fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil());
-        fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil());
-        {
-            ArrayList<File> bootClassPath = new ArrayList<>();
-            bootClassPath.add(jarFile);
-            for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
-                if (!new File(path.getName()).equals(new File("rt.jar")))
-                    bootClassPath.add(path);
-            }
-            System.err.println("Using boot class path = " + bootClassPath);
-            fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
-        }
-        // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));
-        File destDir = new File(destName);
-        if (!destDir.exists())
-            if (!destDir.mkdirs())
-                throw new RuntimeException("Could not create " + destDir);
-        fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir));
-        Set<String> hiddenPackages = new HashSet<>();
-        Set<String> crisp = new HashSet<>();
-        List<String> options = List.of("-XDdev");
-        // options = options.prepend("-doe");
-        // options = options.prepend("-verbose");
-        JavacTaskImpl task = (JavacTaskImpl)
-            tool.getTask(null, fm, null, options, null, null);
-        com.sun.tools.javac.main.JavaCompiler compiler =
-            com.sun.tools.javac.main.JavaCompiler.instance(task.getContext());
-        ClassWriter writer = ClassWriter.instance(task.getContext());
-        Symtab syms = Symtab.instance(task.getContext());
-        Names names = Names.instance(task.getContext());
-        Attribute.Compound proprietaryAnno =
-            new Attribute.Compound(syms.proprietaryType,
-                                   List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
-        Attribute.Compound[] profileAnnos = new Attribute.Compound[profiles.getProfileCount() + 1];
-        Symbol.MethodSymbol profileValue = (MethodSymbol) syms.profileType.tsym.members().findFirst(names.value);
-        for (int i = 1; i < profileAnnos.length; i++) {
-            profileAnnos[i] = new Attribute.Compound(syms.profileType,
-                    List.<Pair<Symbol.MethodSymbol, Attribute>>of(
-                        new Pair<Symbol.MethodSymbol, Attribute>(profileValue,
-                        new Attribute.Constant(syms.intType, i))));
-        }
-
-        Type.moreInfo = true;
-        Types types = Types.instance(task.getContext());
-        Pool pool = new Pool(types);
-        for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
-            String className = fm.inferBinaryName(jarLocation, file);
-            int index = className.lastIndexOf('.');
-            String pckName = index == -1 ? "" : className.substring(0, index);
-            boolean addLegacyAnnotation = false;
-            if (documented.contains(pckName)) {
-                if (!legacy.contains(pckName))
-                    crisp.add(pckName);
-                // System.out.println("Documented: " + className);
-            } else if (legacyProprietary.contains(pckName)) {
-                addLegacyAnnotation = true;
-                // System.out.println("Legacy proprietary: " + className);
-            } else {
-                // System.out.println("Hidden " + className);
-                hiddenPackages.add(pckName);
-                continue;
-            }
-            TypeSymbol sym = (TypeSymbol)compiler.resolveIdent(className);
-            if (sym.kind != TYP) {
-                if (className.indexOf('$') < 0) {
-                    System.err.println("Ignoring (other) " + className + " : " + sym);
-                    System.err.println("   " + sym.getClass().getSimpleName() + " " + sym.type);
-                }
-                continue;
-            }
-            sym.complete();
-            if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
-                System.err.println("Ignoring (bad) " + sym.getQualifiedName());
-                continue;
-            }
-            ClassSymbol cs = (ClassSymbol) sym;
-            if (addLegacyAnnotation) {
-                cs.prependAttributes(List.of(proprietaryAnno));
-            }
-            int p = profiles.getProfile(cs.fullname.toString().replace(".", "/"));
-            if (0 < p && p < profileAnnos.length)
-                cs.prependAttributes(List.of(profileAnnos[p]));
-            writeClass(pool, cs, writer);
-        }
-
-        if (false) {
-            for (String pckName : crisp)
-                System.out.println("Crisp: " + pckName);
-            for (String pckName : hiddenPackages)
-                System.out.println("Hidden: " + pckName);
-            for (String pckName : legacyProprietary)
-                System.out.println("Legacy proprietary: " + pckName);
-            for (String pckName : documented)
-                System.out.println("Documented: " + pckName);
-        }
-    }
-
-    void writeClass(final Pool pool, final ClassSymbol cs, final ClassWriter writer)
-        throws IOException
-    {
-        try {
-            pool.reset();
-            cs.pool = pool;
-            writer.writeClass(cs);
-            for (Symbol sym : cs.members().getSymbols(NON_RECURSIVE)) {
-                if (sym.kind == TYP) {
-                    ClassSymbol nestedClass = (ClassSymbol)sym;
-                    nestedClass.complete();
-                    writeClass(pool, nestedClass, writer);
-                }
-            }
-        } catch (ClassWriter.StringOverflow | ClassWriter.PoolOverflow ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @DefinedBy(Api.ANNOTATION_PROCESSING)
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-    // used for debugging
-    public static void main(String... args) {
-        String rt_jar = args[0];
-        String dest = args[1];
-        args = new String[] {
-            "-Xbootclasspath:" + rt_jar,
-            "-XDprocess.packages",
-            "-proc:only",
-            "-processor",
-            "com.sun.tools.javac.sym.CreateSymbols",
-            "-Acom.sun.tools.javac.sym.Jar=" + rt_jar,
-            "-Acom.sun.tools.javac.sym.Dest=" + dest,
-            // <editor-fold defaultstate="collapsed">
-            "java.applet",
-            "java.awt",
-            "java.awt.color",
-            "java.awt.datatransfer",
-            "java.awt.dnd",
-            "java.awt.event",
-            "java.awt.font",
-            "java.awt.geom",
-            "java.awt.im",
-            "java.awt.im.spi",
-            "java.awt.image",
-            "java.awt.image.renderable",
-            "java.awt.print",
-            "java.beans",
-            "java.beans.beancontext",
-            "java.io",
-            "java.lang",
-            "java.lang.annotation",
-            "java.lang.instrument",
-            "java.lang.management",
-            "java.lang.ref",
-            "java.lang.reflect",
-            "java.math",
-            "java.net",
-            "java.nio",
-            "java.nio.channels",
-            "java.nio.channels.spi",
-            "java.nio.charset",
-            "java.nio.charset.spi",
-            "java.rmi",
-            "java.rmi.activation",
-            "java.rmi.dgc",
-            "java.rmi.registry",
-            "java.rmi.server",
-            "java.security",
-            "java.security.acl",
-            "java.security.cert",
-            "java.security.interfaces",
-            "java.security.spec",
-            "java.sql",
-            "java.text",
-            "java.text.spi",
-            "java.util",
-            "java.util.concurrent",
-            "java.util.concurrent.atomic",
-            "java.util.concurrent.locks",
-            "java.util.jar",
-            "java.util.logging",
-            "java.util.prefs",
-            "java.util.regex",
-            "java.util.spi",
-            "java.util.zip",
-            "javax.accessibility",
-            "javax.activation",
-            "javax.activity",
-            "javax.annotation",
-            "javax.annotation.processing",
-            "javax.crypto",
-            "javax.crypto.interfaces",
-            "javax.crypto.spec",
-            "javax.imageio",
-            "javax.imageio.event",
-            "javax.imageio.metadata",
-            "javax.imageio.plugins.jpeg",
-            "javax.imageio.plugins.bmp",
-            "javax.imageio.spi",
-            "javax.imageio.stream",
-            "javax.jws",
-            "javax.jws.soap",
-            "javax.lang.model",
-            "javax.lang.model.element",
-            "javax.lang.model.type",
-            "javax.lang.model.util",
-            "javax.management",
-            "javax.management.loading",
-            "javax.management.monitor",
-            "javax.management.relation",
-            "javax.management.openmbean",
-            "javax.management.timer",
-            "javax.management.modelmbean",
-            "javax.management.remote",
-            "javax.management.remote.rmi",
-            "javax.naming",
-            "javax.naming.directory",
-            "javax.naming.event",
-            "javax.naming.ldap",
-            "javax.naming.spi",
-            "javax.net",
-            "javax.net.ssl",
-            "javax.print",
-            "javax.print.attribute",
-            "javax.print.attribute.standard",
-            "javax.print.event",
-            "javax.rmi",
-            "javax.rmi.CORBA",
-            "javax.rmi.ssl",
-            "javax.script",
-            "javax.security.auth",
-            "javax.security.auth.callback",
-            "javax.security.auth.kerberos",
-            "javax.security.auth.login",
-            "javax.security.auth.spi",
-            "javax.security.auth.x500",
-            "javax.security.cert",
-            "javax.security.sasl",
-            "javax.sound.sampled",
-            "javax.sound.sampled.spi",
-            "javax.sound.midi",
-            "javax.sound.midi.spi",
-            "javax.sql",
-            "javax.sql.rowset",
-            "javax.sql.rowset.serial",
-            "javax.sql.rowset.spi",
-            "javax.swing",
-            "javax.swing.border",
-            "javax.swing.colorchooser",
-            "javax.swing.filechooser",
-            "javax.swing.event",
-            "javax.swing.table",
-            "javax.swing.text",
-            "javax.swing.text.html",
-            "javax.swing.text.html.parser",
-            "javax.swing.text.rtf",
-            "javax.swing.tree",
-            "javax.swing.undo",
-            "javax.swing.plaf",
-            "javax.swing.plaf.basic",
-            "javax.swing.plaf.metal",
-            "javax.swing.plaf.multi",
-            "javax.swing.plaf.synth",
-            "javax.tools",
-            "javax.transaction",
-            "javax.transaction.xa",
-            "javax.xml.parsers",
-            "javax.xml.bind",
-            "javax.xml.bind.annotation",
-            "javax.xml.bind.annotation.adapters",
-            "javax.xml.bind.attachment",
-            "javax.xml.bind.helpers",
-            "javax.xml.bind.util",
-            "javax.xml.soap",
-            "javax.xml.ws",
-            "javax.xml.ws.handler",
-            "javax.xml.ws.handler.soap",
-            "javax.xml.ws.http",
-            "javax.xml.ws.soap",
-            "javax.xml.ws.spi",
-            "javax.xml.transform",
-            "javax.xml.transform.sax",
-            "javax.xml.transform.dom",
-            "javax.xml.transform.stax",
-            "javax.xml.transform.stream",
-            "javax.xml",
-            "javax.xml.crypto",
-            "javax.xml.crypto.dom",
-            "javax.xml.crypto.dsig",
-            "javax.xml.crypto.dsig.dom",
-            "javax.xml.crypto.dsig.keyinfo",
-            "javax.xml.crypto.dsig.spec",
-            "javax.xml.datatype",
-            "javax.xml.validation",
-            "javax.xml.namespace",
-            "javax.xml.xpath",
-            "javax.xml.stream",
-            "javax.xml.stream.events",
-            "javax.xml.stream.util",
-            "org.ietf.jgss",
-            "org.omg.CORBA",
-            "org.omg.CORBA.DynAnyPackage",
-            "org.omg.CORBA.ORBPackage",
-            "org.omg.CORBA.TypeCodePackage",
-            "org.omg.stub.java.rmi",
-            "org.omg.CORBA.portable",
-            "org.omg.CORBA_2_3",
-            "org.omg.CORBA_2_3.portable",
-            "org.omg.CosNaming",
-            "org.omg.CosNaming.NamingContextExtPackage",
-            "org.omg.CosNaming.NamingContextPackage",
-            "org.omg.SendingContext",
-            "org.omg.PortableServer",
-            "org.omg.PortableServer.CurrentPackage",
-            "org.omg.PortableServer.POAPackage",
-            "org.omg.PortableServer.POAManagerPackage",
-            "org.omg.PortableServer.ServantLocatorPackage",
-            "org.omg.PortableServer.portable",
-            "org.omg.PortableInterceptor",
-            "org.omg.PortableInterceptor.ORBInitInfoPackage",
-            "org.omg.Messaging",
-            "org.omg.IOP",
-            "org.omg.IOP.CodecFactoryPackage",
-            "org.omg.IOP.CodecPackage",
-            "org.omg.Dynamic",
-            "org.omg.DynamicAny",
-            "org.omg.DynamicAny.DynAnyPackage",
-            "org.omg.DynamicAny.DynAnyFactoryPackage",
-            "org.w3c.dom",
-            "org.w3c.dom.events",
-            "org.w3c.dom.bootstrap",
-            "org.w3c.dom.ls",
-            "org.xml.sax",
-            "org.xml.sax.ext",
-            "org.xml.sax.helpers",
-            "org.w3c.dom",
-            "org.w3c.dom.bootstrap",
-            "org.w3c.dom.ls",
-            "org.w3c.dom.ranges",
-            "org.w3c.dom.traversal",
-            "org.w3c.dom.html",
-            "org.w3c.dom.stylesheets",
-            "org.w3c.dom.css",
-            "org.w3c.dom.events",
-            "org.w3c.dom.views",
-            "com.sun.management",
-            "com.sun.security.auth",
-            "com.sun.security.auth.callback",
-            "com.sun.security.auth.login",
-            "com.sun.security.auth.module",
-            "com.sun.security.jgss",
-            "com.sun.net.httpserver",
-            "com.sun.net.httpserver.spi",
-            "javax.smartcardio"
-            // </editor-fold>
-        };
-        com.sun.tools.javac.Main.compile(args);
-    }
-
-}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java
deleted file mode 100644
index 6e8d447..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.sym;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import com.sun.tools.javac.util.Assert;
-
-/**
- * Provide details about profile contents.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own
- * risk.  This code and its internal interfaces are subject to change
- * or deletion without notice.</b></p>
- */
-public abstract class Profiles {
-    // for debugging
-    public static void main(String[] args) throws IOException {
-        Profiles p = Profiles.read(new File(args[0]));
-        if (args.length >= 2) {
-            Map<Integer,Set<String>> lists = new TreeMap<>();
-            for (int i = 1; i <= 4; i++)
-                lists.put(i, new TreeSet<String>());
-
-            File rt_jar_lst = new File(args[1]);
-            for (String line: Files.readAllLines(rt_jar_lst.toPath(), Charset.defaultCharset())) {
-                if (line.endsWith(".class")) {
-                    String type = line.substring(0, line.length() - 6);
-                    int profile = p.getProfile(type);
-                    for (int i = profile; i <= 4; i++)
-                        lists.get(i).add(type);
-                }
-            }
-
-            for (int i = 1; i <= 4; i++) {
-                try (BufferedWriter out = new BufferedWriter(new FileWriter(i + ".txt"))) {
-                    for (String type : lists.get(i)) {
-                        out.write(type);
-                        out.newLine();
-                    }
-                }
-            }
-        }
-    }
-
-    public static Profiles read(File file) throws IOException {
-        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
-            Properties p = new Properties();
-            p.load(in);
-            if (p.containsKey("java/lang/Object"))
-                return new SimpleProfiles(p);
-            else
-                return new MakefileProfiles(p);
-        }
-    }
-
-    public abstract int getProfileCount();
-
-    public abstract int getProfile(String typeName);
-
-    public abstract Set<String> getPackages(int profile);
-
-    private static class MakefileProfiles extends Profiles {
-        static class Package {
-            final Package parent;
-            final String name;
-
-            Map<String, Package> subpackages = new TreeMap<>();
-
-            int profile;
-            Map<String, Integer> includedTypes = new TreeMap<>();
-            Map<String, Integer> excludedTypes = new TreeMap<>();
-
-            Package(Package parent, String name) {
-                this.parent = parent;
-                this.name = name;
-            }
-
-            int getProfile() {
-                return (parent == null) ? profile : Math.max(parent.getProfile(), profile);
-            }
-
-            int getProfile(String simpleTypeName) {
-                Integer i;
-                if ((i = includedTypes.get(simpleTypeName)) != null)
-                    return i;
-                if ((i = includedTypes.get("*")) != null)
-                    return i;
-                if ((i = excludedTypes.get(simpleTypeName)) != null)
-                    return i + 1;
-                if ((i = excludedTypes.get("*")) != null)
-                    return i + 1;
-                return getProfile();
-            }
-
-            String getName() {
-                return (parent == null) ? name : (parent.getName() + "/" + name);
-            }
-
-            void getPackages(int profile, Set<String> results) {
-                int prf = getProfile();
-                if (prf != 0 && profile >= prf)
-                    results.add(getName());
-                for (Package pkg: subpackages.values())
-                    pkg.getPackages(profile, results);
-            }
-        }
-
-        final Map<String, Package> packages = new TreeMap<>();
-
-        final int maxProfile = 4;  // Three compact profiles plus full JRE
-
-        MakefileProfiles(Properties p) {
-            // consider crypto, only if java/lang package exists
-            boolean foundJavaLang = false;
-            for (int profile = 1; profile <= maxProfile; profile++) {
-                String prefix = (profile < maxProfile ? "PROFILE_" + profile : "FULL_JRE");
-                String inclPackages = p.getProperty(prefix + "_RTJAR_INCLUDE_PACKAGES");
-                if (inclPackages == null)
-                    break;
-                for (String pkg: inclPackages.substring(1).trim().split("\\s+")) {
-                    if (pkg.endsWith("/"))
-                        pkg = pkg.substring(0, pkg.length() - 1);
-                    if (foundJavaLang == false && pkg.equals("java/lang"))
-                        foundJavaLang = true;
-                    includePackage(profile, pkg);
-                }
-                String inclTypes =  p.getProperty(prefix + "_RTJAR_INCLUDE_TYPES");
-                if (inclTypes != null) {
-                    for (String type: inclTypes.replace("$$", "$").split("\\s+")) {
-                        if (type.endsWith(".class"))
-                            includeType(profile, type.substring(0, type.length() - 6));
-                    }
-                }
-                String exclTypes =  p.getProperty(prefix + "_RTJAR_EXCLUDE_TYPES");
-                if (exclTypes != null) {
-                    for (String type: exclTypes.replace("$$", "$").split("\\s+")) {
-                        if (type.endsWith(".class"))
-                            excludeType(profile, type.substring(0, type.length() - 6));
-                    }
-                }
-            }
-            /*
-             * A hack to force javax/crypto package into the compact1 profile,
-             * because this package exists in jce.jar, and therefore not in
-             * ct.sym. Note javax/crypto should exist in a profile along with
-             * javax/net/ssl package. Thus, this package is added to compact1,
-             * implying that it should exist in all three profiles.
-             */
-            if (foundJavaLang)
-                includePackage(1, "javax/crypto");
-        }
-
-        @Override
-        public int getProfileCount() {
-            return maxProfile;
-        }
-
-        @Override
-        public int getProfile(String typeName) {
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            return p.getProfile(simpleName);
-        }
-
-        @Override
-        public Set<String> getPackages(int profile) {
-            Set<String> results = new TreeSet<>();
-            for (Package p: packages.values())
-                p.getPackages(profile, results);
-            return results;
-        }
-
-        private void includePackage(int profile, String packageName) {
-//            System.err.println("include package " + packageName);
-            Package p = getPackage(packageName);
-            Assert.check(p.profile == 0);
-            p.profile = profile;
-        }
-
-        private void includeType(int profile, String typeName) {
-//            System.err.println("include type " + typeName);
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            Assert.check(!p.includedTypes.containsKey(simpleName));
-            p.includedTypes.put(simpleName, profile);
-        }
-
-        private void excludeType(int profile, String typeName) {
-//            System.err.println("exclude type " + typeName);
-            int sep = typeName.lastIndexOf("/");
-            String packageName = typeName.substring(0, sep);
-            String simpleName = typeName.substring(sep + 1);
-
-            Package p = getPackage(packageName);
-            Assert.check(!p.excludedTypes.containsKey(simpleName));
-            p.excludedTypes.put(simpleName, profile);
-        }
-
-        private Package getPackage(String packageName) {
-            int sep = packageName.lastIndexOf("/");
-            Package parent;
-            Map<String, Package> parentSubpackages;
-            String simpleName;
-            if (sep == -1) {
-                parent = null;
-                parentSubpackages = packages;
-                simpleName = packageName;
-            } else {
-                parent = getPackage(packageName.substring(0, sep));
-                parentSubpackages = parent.subpackages;
-                simpleName = packageName.substring(sep + 1);
-            }
-
-            Package p = parentSubpackages.get(simpleName);
-            if (p == null) {
-                parentSubpackages.put(simpleName, p = new Package(parent, simpleName));
-            }
-            return p;
-        }
-    }
-
-    private static class SimpleProfiles extends Profiles {
-        private final Map<String, Integer> map;
-        private final int profileCount;
-
-        SimpleProfiles(Properties p) {
-            int max = 0;
-            map = new HashMap<>();
-            for (Map.Entry<Object,Object> e: p.entrySet()) {
-                String typeName = (String) e.getKey();
-                int profile = Integer.valueOf((String) e.getValue());
-                map.put(typeName, profile);
-                max = Math.max(max, profile);
-            }
-            profileCount = max;
-        }
-
-        @Override
-        public int getProfileCount() {
-            return profileCount;
-        }
-
-        @Override
-        public int getProfile(String typeName) {
-            return map.get(typeName);
-        }
-
-        @Override
-        public Set<String> getPackages(int profile) {
-            Set<String> results = new TreeSet<>();
-            for (Map.Entry<String,Integer> e: map.entrySet()) {
-                String tn = e.getKey();
-                int prf = e.getValue();
-                int sep = tn.lastIndexOf("/");
-                if (sep > 0 && profile >= prf)
-                    results.add(tn);
-            }
-            return results;
-        }
-    }
-}
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 3016af5..2787963 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
@@ -35,14 +35,20 @@
 
 import com.sun.source.tree.*;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Scope.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
+
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
+import javax.tools.JavaFileManager.Location;
+
+import com.sun.tools.javac.code.Directive.ExportsDirective;
+
 /**
  * Root class for abstract syntax tree nodes. It provides definitions
  * for specific tree nodes as subclasses nested inside.
@@ -344,6 +350,12 @@
         DIV_ASG(DIV),                    // /=
         MOD_ASG(MOD),                    // %=
 
+        MODULEDEF,
+        EXPORTS,
+        PROVIDES,
+        REQUIRES,
+        USES,
+
         /** A synthetic let expression, of type LetExpr.
          */
         LETEXPR;                         // ala scheme
@@ -484,8 +496,12 @@
     public static class JCCompilationUnit extends JCTree implements CompilationUnitTree {
         /** All definitions in this file (ClassDef, Import, and Skip) */
         public List<JCTree> defs;
-        /* The source file name. */
+        /** The source file name. */
         public JavaFileObject sourcefile;
+        /** The module to which this compilation unit belongs. */
+        public ModuleSymbol modle;
+        /** The location in which this compilation unit was found. */
+        public Location locn;
         /** The package to which this compilation unit belongs. */
         public PackageSymbol packge;
         /** A scope containing top level classes. */
@@ -2593,8 +2609,202 @@
         }
     }
 
+    public static abstract class JCDirective extends JCTree
+        implements DirectiveTree {
+    }
+
+    public static class JCModuleDecl extends JCTree implements ModuleTree {
+        public JCExpression qualId;
+        public List<JCDirective> directives;
+        public ModuleSymbol sym;
+
+        protected JCModuleDecl(JCExpression qualId, List<JCDirective> directives) {
+            this.qualId = qualId;
+            this.directives = directives;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitModuleDef(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.MODULE;
+        }
+
+//        @Override
+        public JCExpression getName() {
+            return qualId;
+        }
+
+        @Override
+        public List<JCDirective> getDirectives() {
+            return directives;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitModule(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return MODULEDEF;
+        }
+    }
+
+    public static class JCExports extends JCDirective
+            implements ExportsTree {
+        public JCExpression qualid;
+        public List<JCExpression> moduleNames;
+        public ExportsDirective directive;
+
+        protected JCExports(JCExpression qualId, List<JCExpression> moduleNames) {
+            this.qualid = qualId;
+            this.moduleNames = moduleNames;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitExports(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.EXPORTS;
+        }
+
+        @Override
+        public JCExpression getExportName() {
+            return qualid;
+        }
+
+        @Override
+        public List<JCExpression> getModuleNames() {
+            return moduleNames;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitExports(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return EXPORTS;
+        }
+    }
+
+    public static class JCProvides extends JCDirective
+            implements ProvidesTree {
+        public JCExpression serviceName;
+        public JCExpression implName;
+
+        protected JCProvides(JCExpression serviceName, JCExpression implName) {
+            this.serviceName = serviceName;
+            this.implName = implName;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitProvides(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.PROVIDES;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitProvides(this, d);
+        }
+
+        @Override
+        public JCExpression getServiceName() {
+            return serviceName;
+        }
+
+        @Override
+        public JCExpression getImplementationName() {
+            return implName;
+        }
+
+        @Override
+        public Tag getTag() {
+            return PROVIDES;
+        }
+    }
+
+    public static class JCRequires extends JCDirective
+            implements RequiresTree {
+        public boolean isPublic;
+        public JCExpression moduleName;
+        public RequiresDirective directive;
+
+        protected JCRequires(boolean isPublic, JCExpression moduleName) {
+            this.isPublic = isPublic;
+            this.moduleName = moduleName;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitRequires(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.REQUIRES;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitRequires(this, d);
+        }
+
+        @Override
+        public boolean isPublic() {
+            return isPublic;
+        }
+
+        @Override
+        public JCExpression getModuleName() {
+            return moduleName;
+        }
+
+        @Override
+        public Tag getTag() {
+            return REQUIRES;
+        }
+    }
+
+    public static class JCUses extends JCDirective
+            implements UsesTree {
+        public JCExpression qualid;
+
+        protected JCUses(JCExpression qualId) {
+            this.qualid = qualId;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitUses(this); }
+
+        @Override
+        public Kind getKind() {
+            return Kind.USES;
+        }
+
+        @Override
+        public JCExpression getServiceName() {
+            return qualid;
+        }
+
+        @Override
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitUses(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return USES;
+        }
+    }
+
     public static class JCErroneous extends JCExpression
-            implements com.sun.source.tree.ErroneousTree {
+            implements ErroneousTree {
         public List<? extends JCTree> errs;
         protected JCErroneous(List<? extends JCTree> errs) {
             this.errs = errs;
@@ -2731,6 +2941,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);
+        JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames);
+        JCProvides Provides(JCExpression serviceName, JCExpression implName);
+        JCRequires Requires(boolean isPublic, JCExpression qualId);
+        JCUses Uses(JCExpression qualId);
         LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr);
     }
 
@@ -2791,6 +3006,11 @@
         public void visitModifiers(JCModifiers that)         { visitTree(that); }
         public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); }
         public void visitErroneous(JCErroneous that)         { visitTree(that); }
+        public void visitModuleDef(JCModuleDecl that)        { visitTree(that); }
+        public void visitExports(JCExports that)             { visitTree(that); }
+        public void visitProvides(JCProvides that)           { visitTree(that); }
+        public void visitRequires(JCRequires that)           { visitTree(that); }
+        public void visitUses(JCUses that)                   { visitTree(that); }
         public void visitLetExpr(LetExpr that)               { visitTree(that); }
 
         public void visitTree(JCTree that)                   { Assert.error(); }
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 15d9ca5..6457bc4 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -438,6 +438,74 @@
         }
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        try {
+            print("module ");
+            printExpr(tree.qualId);
+            if (tree.directives == null) {
+                print(";");
+            } else {
+                printBlock(tree.directives);
+            }
+            println();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitExports(JCExports tree) {
+        try {
+            print("exports ");
+            printExpr(tree.qualid);
+            if (tree.moduleNames != null) {
+                print(" to ");
+                printExprs(tree.moduleNames);
+            }
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitProvides(JCProvides tree) {
+        try {
+            print("provides ");
+            printExpr(tree.serviceName);
+            print(" with ");
+            printExpr(tree.implName);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitRequires(JCRequires tree) {
+        try {
+            print("requires ");
+            if (tree.isPublic)
+                print("public ");
+            printExpr(tree.moduleName);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    @Override
+    public void visitUses(JCUses tree) {
+        try {
+            print("uses ");
+            printExpr(tree.qualid);
+            print(";");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
     public void visitImport(JCImport tree) {
         try {
             print("import ");
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 e36cbaa..20638f7 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -505,6 +505,44 @@
         return M.at(t.pos).Wildcard(kind, inner);
     }
 
+    @Override
+    public JCTree visitModule(ModuleTree node, P p) {
+        JCModuleDecl t = (JCModuleDecl) node;
+        JCExpression qualId = copy(t.qualId);
+        List<JCDirective> directives = copy(t.directives);
+        return M.at(t.pos).ModuleDef(qualId, directives);
+    }
+
+    @Override
+    public JCExports visitExports(ExportsTree node, P p) {
+        JCExports t = (JCExports) node;
+        JCExpression qualId = copy(t.qualid, p);
+        List<JCExpression> moduleNames = copy(t.moduleNames, p);
+        return M.at(t.pos).Exports(qualId, moduleNames);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    public JCUses visitUses(UsesTree node, P p) {
+        JCUses t = (JCUses) node;
+        JCExpression serviceName = copy(t.qualid, p);
+        return M.at(t.pos).Uses(serviceName);
+    }
+
     @DefinedBy(Api.COMPILER_TREE)
     public JCTree visitOther(Tree node, P p) {
         JCTree tree = (JCTree) node;
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 af23690..e22fb64 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
@@ -42,6 +42,7 @@
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK;
 import static com.sun.tools.javac.tree.JCTree.Tag.SYNCHRONIZED;
+import javax.tools.JavaFileObject;
 
 /** Utility class containing inspector methods for trees.
  *
@@ -762,7 +763,12 @@
         node = skipParens(node);
         switch (node.getTag()) {
         case TOPLEVEL:
-            return ((JCCompilationUnit) node).packge;
+            JCCompilationUnit cut = (JCCompilationUnit) node;
+            if (isModuleInfo(cut) && cut.defs.nonEmpty() && cut.defs.head.hasTag(MODULEDEF))
+                return symbolFor(cut.defs.head);
+            return cut.packge;
+        case MODULEDEF:
+            return ((JCModuleDecl) node).sym;
         case PACKAGEDEF:
             return ((JCPackageDecl) node).packge;
         case CLASSDEF:
@@ -1144,4 +1150,21 @@
         finder.scan(e);
         return finder.foundTypeAnno;
     }
+
+    public static boolean isModuleInfo(JCCompilationUnit tree) {
+        return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE);
+    }
+
+    public static JCModuleDecl getModule(JCCompilationUnit t) {
+        if (t.defs.nonEmpty()) {
+            JCTree def = t.defs.head;
+            if (def.hasTag(MODULEDEF))
+                return (JCModuleDecl) def;
+        }
+        return null;
+    }
+
+    public static boolean isPackageInfo(JCCompilationUnit tree) {
+        return tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
+    }
 }
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 959d812..59d3945 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
@@ -125,6 +125,7 @@
             Assert.check(node instanceof JCClassDecl
                 || node instanceof JCPackageDecl
                 || node instanceof JCImport
+                || node instanceof JCModuleDecl
                 || node instanceof JCSkip
                 || node instanceof JCErroneous
                 || (node instanceof JCExpressionStatement
@@ -536,6 +537,41 @@
         return Modifiers(flags, List.<JCAnnotation>nil());
     }
 
+    @Override
+    public JCModuleDecl ModuleDef(JCExpression qualid, List<JCDirective> directives) {
+        JCModuleDecl tree = new JCModuleDecl(qualid, directives);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames) {
+        JCExports tree = new JCExports(qualId, moduleNames);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCProvides Provides(JCExpression serviceName, JCExpression implName) {
+        JCProvides tree = new JCProvides(serviceName, implName);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCRequires Requires(boolean isPublic, JCExpression qualId) {
+        JCRequires tree = new JCRequires(isPublic, qualId);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCUses Uses(JCExpression qualId) {
+        JCUses tree = new JCUses(qualId);
+        tree.pos = pos;
+        return tree;
+    }
+
     public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
         JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType);
         tree.pos = pos;
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 2ef47d3..506925c 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, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,6 +71,34 @@
         scan(tree.pid);
     }
 
+    @Override
+    public void visitModuleDef(JCModuleDecl tree) {
+        scan(tree.qualId);
+        scan(tree.directives);
+    }
+
+    @Override
+    public void visitExports(JCExports tree) {
+        scan(tree.qualid);
+        scan(tree.moduleNames);
+    }
+
+    @Override
+    public void visitProvides(JCProvides tree) {
+        scan(tree.serviceName);
+        scan(tree.implName);
+    }
+
+    @Override
+    public void visitRequires(JCRequires tree) {
+        scan(tree.moduleName);
+    }
+
+    @Override
+    public void visitUses(JCUses tree) {
+        scan(tree.qualid);
+    }
+
     public void visitImport(JCImport tree) {
         scan(tree.qualid);
     }
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
new file mode 100644
index 0000000..2b34d09
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
@@ -0,0 +1,112 @@
+/*
+ * 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 com.sun.tools.javac.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ModuleHelper {
+    /** The context key for the module helper. */
+    protected static final Context.Key<ModuleHelper> moduleHelperKey = new Context.Key<>();
+
+    /** Get the JavaCompiler instance for this context. */
+    public static ModuleHelper instance(Context context) {
+        ModuleHelper instance = context.get(moduleHelperKey);
+        if (instance == null)
+            instance = new ModuleHelper(context);
+        return instance;
+    }
+
+    public ModuleHelper(Context context) {
+        context.put(moduleHelperKey, this);
+        Options options = Options.instance(context);
+        allowAccessToInternalAPI = options.isSet("accessInternalAPI");
+    }
+
+    final boolean allowAccessToInternalAPI;
+
+    private void exportPackageToModule(String packageName, Object target)
+            throws ClassNotFoundException, NoSuchMethodException, IllegalArgumentException,
+                   InvocationTargetException, IllegalAccessException {
+        if (addExportsMethod == null) {
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            addExportsMethod = moduleClass.getDeclaredMethod("addExports",
+                    new Class<?>[] { String.class, moduleClass });
+        }
+        addExportsMethod.invoke(from, new Object[] { packageName, target });
+    }
+
+    static final String[] javacInternalPackages = new String[] {
+        "com.sun.tools.javac.api",
+        "com.sun.tools.javac.code",
+        "com.sun.tools.javac.comp",
+        "com.sun.tools.javac.file",
+        "com.sun.tools.javac.jvm",
+        "com.sun.tools.javac.main",
+        "com.sun.tools.javac.model",
+        "com.sun.tools.javac.parser",
+        "com.sun.tools.javac.platform",
+        "com.sun.tools.javac.processing",
+        "com.sun.tools.javac.tree",
+        "com.sun.tools.javac.util",
+
+        "com.sun.tools.doclint",
+    };
+
+    public void addExports(ClassLoader classLoader) {
+        try {
+            if (allowAccessToInternalAPI) {
+                if (from == null) {
+                    if (getModuleMethod == null) {
+                        getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class<?>[0]);
+                    }
+                    from = getModuleMethod.invoke(getClass(), new Object[0]);
+                }
+                if (getUnnamedModuleMethod == null) {
+                    getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class<?>[0]);
+                }
+                Object target = getUnnamedModuleMethod.invoke(classLoader, new Object[0]);
+                for (String pack: javacInternalPackages) {
+                    exportPackageToModule(pack, target);
+                }
+            }
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+
+    // a module instance
+    private Object from = null;
+
+    // on java.lang.reflect.Module
+    private static Method addExportsMethod = null;
+
+    // on java.lang.ClassLoader
+    private static Method getUnnamedModuleMethod = null;
+
+    // on java.lang.Class
+    private static Method getModuleMethod = null;
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java
new file mode 100644
index 0000000..7e7accc
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleWrappers.java
@@ -0,0 +1,284 @@
+/*
+ * 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 com.sun.tools.javac.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.ServiceLoader;
+
+/** This class provides wrappers for classes and methods that are new in JDK 9, and which are not
+ *  available on older versions of the platform on which javac may be compiled and run.
+ *  In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers
+ *  can be replaced by use of the real underlying classes.
+ */
+public class ModuleWrappers {
+    public static final class ServiceLoaderHelper {
+        @SuppressWarnings("unchecked")
+        public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) {
+            try {
+                Class<?> layerClass = LayerHelper.getLayerClass();
+                Method loadMethod = ServiceLoader.class
+                        .getDeclaredMethod("load", layerClass, Class.class);
+                Object result = loadMethod.invoke(ServiceLoader.class, layer.theRealLayer, service);
+                return (ServiceLoader<S>)result;
+            } catch (NoSuchMethodException |
+                    SecurityException |
+                    IllegalArgumentException |
+                    IllegalAccessException |
+                    InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    public static class ModuleFinder {
+        Object theRealModuleFinder;
+
+        private ModuleFinder(Object moduleFinder) {
+            this.theRealModuleFinder = moduleFinder;
+        }
+
+        public static ModuleFinder of(Path... dirs) {
+            try {
+                Object result = ModuleFinderHelper.getOfMethod()
+                        .invoke(ModuleFinderHelper.moduleFinderInterface, (Object)dirs);
+                ModuleFinder mFinder = new ModuleFinder(result);
+                return mFinder;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public static ModuleFinder empty() {
+            try {
+                Object result = ModuleFinderHelper.getEmptyMethod()
+                        .invoke(ModuleFinderHelper.moduleFinderInterface);
+                ModuleFinder mFinder = new ModuleFinder(result);
+                return mFinder;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    private static class ModuleFinderHelper {
+        static Method ofMethod = null;
+        static Method emptyMethod = null;
+        static Class<?> moduleFinderInterface;
+
+        static Method getOfMethod() {
+            if (ModuleFinderHelper.ofMethod == null) {
+                try {
+                    getModuleFinderInterface();
+                    ofMethod = moduleFinderInterface.getDeclaredMethod("of", Path[].class);
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return ofMethod;
+        }
+
+        static Method getEmptyMethod() {
+            if (emptyMethod == null) {
+                try {
+                    getModuleFinderInterface();
+                    emptyMethod = moduleFinderInterface.getDeclaredMethod("empty");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return emptyMethod;
+        }
+
+        static Class<?> getModuleFinderInterface() {
+            if (moduleFinderInterface == null) {
+                try {
+                    moduleFinderInterface = Class.forName("java.lang.module.ModuleFinder", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return moduleFinderInterface;
+        }
+    }
+
+    public static final class Configuration {
+        Object theRealConfiguration;
+
+        private Configuration(Object configuration) {
+            this.theRealConfiguration = configuration;
+        }
+
+        public Configuration resolveRequiresAndUses(
+                ModuleFinder beforeFinder,
+                ModuleFinder afterFinder,
+                Collection<String> roots) {
+            try {
+                Object result = ConfigurationHelper.getResolveRequiresAndUses()
+                        .invoke(theRealConfiguration,
+                                    beforeFinder.theRealModuleFinder,
+                                    afterFinder.theRealModuleFinder,
+                                    roots
+                                );
+                Configuration configuration = new Configuration(result);
+                return configuration;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+    }
+
+    private static class ConfigurationHelper {
+        static Method resolveRequiresAndUsesMethod;
+        static Class<?> configurationClass;
+
+        static Method getResolveRequiresAndUses() {
+            if (resolveRequiresAndUsesMethod == null) {
+                try {
+                    getConfigurationClass();
+                    Class<?> moduleFinderInterface = ModuleFinderHelper.getModuleFinderInterface();
+                    Class<?> configurationClass = ConfigurationHelper.getConfigurationClass();
+                    resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses",
+                                moduleFinderInterface,
+                                moduleFinderInterface,
+                                Collection.class
+                    );
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return resolveRequiresAndUsesMethod;
+        }
+
+        static Class<?> getConfigurationClass() {
+            if (configurationClass == null) {
+                try {
+                    configurationClass = Class.forName("java.lang.module.Configuration", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return configurationClass;
+        }
+    }
+
+    public static final class Layer {
+        Object theRealLayer;
+
+        private Layer(Object layer) {
+            this.theRealLayer = layer;
+        }
+
+        public static Layer boot() {
+            try {
+                Object result = LayerHelper.getBootMethod().invoke(LayerHelper.getLayerClass());
+                Layer layer = new Layer(result);
+                return layer;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public Configuration configuration() {
+            try {
+                Object result = LayerHelper.getConfigurationMethod().invoke(theRealLayer);
+                Layer layer = new Layer(result);
+                return new Configuration(result);
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+        public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) {
+            try {
+                Object result = LayerHelper.getDefineModulesWithOneLoaderMethod()
+                        .invoke(theRealLayer, configuration.theRealConfiguration, parentClassLoader);
+                Layer layer = new Layer(result);
+                return layer;
+            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
+                throw new Abort(ex);
+            }
+        }
+
+    }
+
+    private static class LayerHelper {
+        static Class<?> layerClass;
+        static Method bootMethod;
+        static Method defineModulesWithOneLoaderMethod = null;
+        static Method configurationMethod;
+
+        static Class<?> getLayerClass() {
+            if (layerClass == null) {
+                try {
+                    layerClass = Class.forName("java.lang.reflect.Layer", false, ClassLoader.getSystemClassLoader());
+                } catch (ClassNotFoundException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return layerClass;
+        }
+
+        static Method getBootMethod() {
+            if (bootMethod == null) {
+                try {
+                    bootMethod = getLayerClass().getDeclaredMethod("boot");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return bootMethod;
+        }
+
+        static Method getDefineModulesWithOneLoaderMethod() {
+            if (defineModulesWithOneLoaderMethod == null) {
+                try {
+                    defineModulesWithOneLoaderMethod = getLayerClass().getDeclaredMethod("defineModulesWithOneLoader",
+                                ConfigurationHelper.getConfigurationClass(),
+                                ClassLoader.class
+                    );
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return defineModulesWithOneLoaderMethod;
+        }
+
+        static Method getConfigurationMethod() {
+            if (configurationMethod == null) {
+                try {
+                    configurationMethod =  getLayerClass().getDeclaredMethod("configuration");
+                } catch (NoSuchMethodException | SecurityException ex) {
+                    throw new Abort(ex);
+                }
+            }
+            return configurationMethod;
+        }
+    }
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
index b033f63..b1321f8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -127,9 +127,11 @@
         int prefixOffset   = prefix.getByteOffset();
         int prefixLength   = prefix.getByteLength();
 
+        if (thisLength < prefixLength)
+            return false;
+
         int i = 0;
         while (i < prefixLength &&
-               i < thisLength &&
                thisBytes[thisOffset + i] == prefixBytes[prefixOffset + i])
             i++;
         return i == prefixLength;
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 2132774..63866a6 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -63,6 +63,13 @@
     public final Name _default;
     public final Name _super;
     public final Name _this;
+    public final Name exports;
+    public final Name module;
+    public final Name provides;
+    public final Name requires;
+    public final Name to;
+    public final Name uses;
+    public final Name with;
 
     // field and method names
     public final Name _name;
@@ -116,6 +123,9 @@
     // package names
     public final Name java_lang;
 
+    // module names
+    public final Name java_base;
+
     // attribute names
     public final Name Annotation;
     public final Name AnnotationDefault;
@@ -134,6 +144,7 @@
     public final Name LocalVariableTable;
     public final Name LocalVariableTypeTable;
     public final Name MethodParameters;
+    public final Name Module;
     public final Name RuntimeInvisibleAnnotations;
     public final Name RuntimeInvisibleParameterAnnotations;
     public final Name RuntimeInvisibleTypeAnnotations;
@@ -148,6 +159,7 @@
     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;
@@ -170,10 +182,11 @@
     public final Name T;
     public final Name deprecated;
     public final Name ex;
+    public final Name module_info;
     public final Name package_info;
     public final Name requireNonNull;
 
-    //lambda-related
+    // lambda-related
     public final Name lambda;
     public final Name metafactory;
     public final Name altMetafactory;
@@ -205,6 +218,13 @@
         _default = fromString("default");
         _super = fromString("super");
         _this = fromString("this");
+        exports = fromString("exports");
+        module = fromString("module");
+        provides = fromString("provides");
+        requires = fromString("requires");
+        to = fromString("to");
+        uses = fromString("uses");
+        with = fromString("with");
 
         // field and method names
         _name = fromString("name");
@@ -259,6 +279,9 @@
         // package names
         java_lang = fromString("java.lang");
 
+        // module names
+        java_base = fromString("java.base");
+
         // attribute names
         Annotation = fromString("Annotation");
         AnnotationDefault = fromString("AnnotationDefault");
@@ -277,6 +300,7 @@
         LocalVariableTable = fromString("LocalVariableTable");
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
         MethodParameters = fromString("MethodParameters");
+        Module = fromString("Module");
         RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
         RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
         RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
@@ -291,6 +315,7 @@
         Synthetic = fromString("Synthetic");
         Value = fromString("Value");
         Varargs = fromString("Varargs");
+        Version = fromString("Version");
 
         // members of java.lang.annotation.ElementType
         ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@@ -313,6 +338,7 @@
         T = fromString("T");
         deprecated = fromString("deprecated");
         ex = fromString("ex");
+        module_info = fromString("module-info");
         package_info = fromString("package-info");
         requireNonNull = fromString("requireNonNull");
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java
deleted file mode 100644
index 9820ebe..0000000
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ServiceLoader.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.ServiceConfigurationError;
-
-
-/**
- * This is a temporary, modified copy of java.util.ServiceLoader, for use by
- * javac, to work around bug JDK-8004082.
- *
- * The bug describes problems in the interaction between ServiceLoader and
- * URLClassLoader, such that references to a jar file passed to URLClassLoader
- * may be retained after calling URLClassLoader.close(), preventing the jar
- * file from being deleted on Windows.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-
-public 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 Class<S> service;
-
-    // The class loader used to locate, load, and instantiate providers
-    private ClassLoader loader;
-
-    // Cached providers, in instantiation order
-    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
-
-    // The current lazy-lookup iterator
-    private LazyIterator lookupIterator;
-
-    /**
-     * 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();
-        lookupIterator = new LazyIterator(service, loader);
-    }
-
-    private ServiceLoader(Class<S> svc, ClassLoader cl) {
-        service = Objects.requireNonNull(svc, "Service interface cannot be null");
-        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
-        reload();
-    }
-
-    private static void fail(Class<?> service, String msg, Throwable cause)
-        throws ServiceConfigurationError
-    {
-        throw new ServiceConfigurationError(service.getName() + ": " + msg,
-                                            cause);
-    }
-
-    private static void fail(Class<?> service, String msg)
-        throws ServiceConfigurationError
-    {
-        throw new ServiceConfigurationError(service.getName() + ": " + msg);
-    }
-
-    private static void fail(Class<?> service, URL u, int line, String msg)
-        throws ServiceConfigurationError
-    {
-        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 (!providers.containsKey(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
-    //
-    // @throws ServiceConfigurationError
-    //         If an I/O error occurs while reading from the given URL, or
-    //         if a configuration-file format error is detected
-    //
-    private Iterator<String> parse(Class<?> service, URL u)
-        throws ServiceConfigurationError
-    {
-        InputStream in = null;
-        ArrayList<String> names = new ArrayList<>();
-        try {
-            // The problem is that by default, streams opened with
-            // u.openInputStream use a cached reference to a JarFile, which
-            // is separate from the reference used by URLClassLoader, and
-            // which is not closed by URLClassLoader.close().
-            // The workaround is to disable caching for this specific jar file,
-            // so that the reference to the jar file can be closed when the
-            // file has been read.
-            // Original code:
-            // in = u.openStream();
-            // Workaround ...
-            URLConnection uc = u.openConnection();
-            uc.setUseCaches(false);
-            in = uc.getInputStream();
-            // ... end of workaround.
-            try (BufferedReader r = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
-                int lc = 1;
-                while ((lc = parseLine(service, u, r, lc, names)) >= 0);
-            }
-        } catch (IOException x) {
-            fail(service, "Error reading configuration file", x);
-        } finally {
-            try {
-                if (in != null) in.close();
-            } catch (IOException y) {
-                fail(service, "Error closing configuration file", y);
-            }
-        }
-        return names.iterator();
-    }
-
-    // Private inner class implementing fully-lazy provider lookup
-    //
-    private class LazyIterator
-        implements Iterator<S>
-    {
-
-        Class<S> service;
-        ClassLoader loader;
-        Enumeration<URL> configs = null;
-        Iterator<String> pending = null;
-        String nextName = null;
-
-        private LazyIterator(Class<S> service, ClassLoader loader) {
-            this.service = service;
-            this.loader = loader;
-        }
-
-        public boolean hasNext() {
-            if (nextName != null) {
-                return true;
-            }
-            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(service, configs.nextElement());
-            }
-            nextName = pending.next();
-            return true;
-        }
-
-        public S next() {
-            if (!hasNext()) {
-                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");
-            }
-            if (!service.isAssignableFrom(c)) {
-                fail(service,
-                     "Provider " + cn  + " not a subtype");
-            }
-            try {
-                S p = service.cast(c.newInstance());
-                providers.put(cn, p);
-                return p;
-            } catch (Throwable x) {
-                fail(service,
-                     "Provider " + cn + " could not be instantiated: " + x,
-                     x);
-            }
-            throw new Error();          // This cannot happen
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-    /**
-     * Lazily loads 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.
-     *
-     * <p> To achieve laziness the actual work of parsing the available
-     * provider-configuration files 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-configuration file
-     * violates the specified format, or if it names a provider class that
-     * cannot be found and instantiated, or if the result of instantiating the
-     * class is not assignable 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
-     * available provider, but in general such recovery cannot be guaranteed.
-     *
-     * <blockquote style="font-size: smaller; line-height: 1.2"><span
-     * style="padding-right: 1em; font-weight: bold">Design Note</span>
-     * Throwing an error in these cases may seem extreme.  The rationale for
-     * this behavior is that a malformed provider-configuration file, like a
-     * malformed class file, indicates a serious problem with the way the Java
-     * virtual machine is configured or is being used.  As such it is
-     * preferable to throw an error rather than try to recover or, even worse,
-     * fail silently.</blockquote>
-     *
-     * <p> The iterator returned by this method does not support removal.
-     * Invoking its {@link java.util.Iterator#remove() remove} method will
-     * cause an {@link UnsupportedOperationException} to be thrown.
-     *
-     * @return  An iterator that lazily loads providers for this loader's
-     *          service
-     */
-    public Iterator<S> iterator() {
-        return new Iterator<S>() {
-
-            Iterator<Map.Entry<String,S>> knownProviders
-                = providers.entrySet().iterator();
-
-            public boolean hasNext() {
-                if (knownProviders.hasNext())
-                    return true;
-                return lookupIterator.hasNext();
-            }
-
-            public S next() {
-                if (knownProviders.hasNext())
-                    return knownProviders.next().getValue();
-                return lookupIterator.next();
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-
-        };
-    }
-
-    /**
-     * Creates a new service loader for the given service type and class
-     * loader.
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @param  loader
-     *         The class loader to be used to load provider-configuration files
-     *         and provider classes, or <tt>null</tt> if the system class
-     *         loader (or, failing that, the bootstrap class loader) is to be
-     *         used
-     *
-     * @return A new service loader
-     */
-    public static <S> ServiceLoader<S> load(Class<S> service,
-                                            ClassLoader loader)
-    {
-        return new ServiceLoader<>(service, loader);
-    }
-
-    /**
-     * Creates a new service loader for the given service type, using the
-     * current thread's {@linkplain java.lang.Thread#getContextClassLoader
-     * context class loader}.
-     *
-     * <p> An invocation of this convenience method of the form
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>)</pre></blockquote>
-     *
-     * is equivalent to
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>,
-     *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @return A new service loader
-     */
-    public static <S> ServiceLoader<S> load(Class<S> service) {
-        ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        return ServiceLoader.load(service, cl);
-    }
-
-    /**
-     * Creates a new service loader for the given service type, using the
-     * extension class loader.
-     *
-     * <p> This convenience method simply locates the extension class loader,
-     * call it <tt><i>extClassLoader</i></tt>, and then returns
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
-     *
-     * <p> If the extension class loader cannot be found then the system class
-     * loader is used; if there is no system class loader then the bootstrap
-     * class loader is used.
-     *
-     * <p> This method is intended for use when only installed providers are
-     * desired.  The resulting service will only find and load providers that
-     * have been installed into the current Java virtual machine; providers on
-     * the application's class path will be ignored.
-     *
-     * @param  service
-     *         The interface or abstract class representing the service
-     *
-     * @return A new service loader
-     */
-    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 ServiceLoader.load(service, prev);
-    }
-
-    /**
-     * Returns a string describing this service.
-     *
-     * @return  A descriptive string
-     */
-    public String toString() {
-        return "java.util.ServiceLoader[" + service.getName() + "]";
-    }
-
-}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
index 789069b..96d6dc1 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
@@ -497,7 +497,15 @@
         List<String> opts = new ArrayList<>();
         opts.add("-proc:only");
         opts.addAll(javac_extras);
-        CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null);
+
+        CompilationTask t;
+        try {
+            t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null);
+        } catch (IllegalArgumentException e) {
+            util.error("bad.arg", e.getMessage());
+            return false;
+        }
+
         JavahProcessor p = new JavahProcessor(g);
         t.setProcessors(Collections.singleton(p));
 
@@ -505,15 +513,7 @@
         if (p.exit != null)
             throw new Util.Exit(p.exit);
         return ok;
-    }
 
-    private List<File> pathToFiles(String path) {
-        List<File> files = new ArrayList<>();
-        for (String f: path.split(File.pathSeparator)) {
-            if (f.length() > 0)
-                files.add(new File(f));
-        }
-        return files;
     }
 
     static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
index 875816b..6aa92c1 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/resources/l10n.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1998, 2013, 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
@@ -35,6 +35,8 @@
 at.args.io.exception=\
         The following I/O problem was encountered when processing an @ \
         argument on the command line: {0}.
+bad.arg=\
+        Bad argument: {0}
 old.jni.mixed=\
         Can''t mix options -jni and -old.  Try -help.
 old.llni.mixed=\
@@ -78,7 +80,8 @@
 -help                 Print this help message and exit\n\t\
 -classpath <path>     Path from which to load classes\n\t\
 -cp <path>            Path from which to load classes\n\t\
--bootclasspath <path> Path from which to load bootstrap classes\n\t\
+-modulepath <path>    Path from which to load application modules\n\t\
+-system <path>        JDK directory from which to load system modules\n\t\
 -d <dir>              Output directory\n\t\
 -o <file>             Output file (only one of -d or -o may be used)\n\t\
 -jni                  Generate JNI-style header file (default)\n\t\
@@ -86,8 +89,10 @@
 -verbose              Enable verbose output\n\t\
 -force                Always write output files\n\
 \n\
-<classes> are specified with their fully qualified names (for\n\
-instance, java.lang.Object).\n
+<classes> are specified with their fully qualified names, optionally\n\
+prefixed by a module name followed by '/'. Examples:\n\
+    java.lang.Object\n\
+    java.base/java.io.File\n\
 
 main.usage=\
 Usage: \n\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
index 2bd1cac..d5cb4ea 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java
@@ -35,8 +35,10 @@
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.sjavac.comp.PubapiVisitor;
@@ -77,10 +79,11 @@
     }
 
     public PubApi getPubApi(String fullyQualifiedClassName) {
+        Symtab syms = Symtab.instance(context);
         ClassFinder cr = ClassFinder.instance(context);
         Names ns = Names.instance(context);
         Name n = ns.fromString(fullyQualifiedClassName);
-        ClassSymbol cs = cr.loadClass(n);
+        ClassSymbol cs = cr.loadClass(syms.inferModule(Convert.packagePart(n)), n);
         PubapiVisitor v = new PubapiVisitor();
         v.visit(cs);
         return v.getCollectedPubApi();
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java
index b288955..83ebed6 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.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
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
index b1b7715..4c39a70 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java
@@ -53,6 +53,7 @@
 import com.sun.tools.sjavac.options.Options;
 import com.sun.tools.sjavac.options.SourceLocation;
 import com.sun.tools.sjavac.server.Sjavac;
+import java.io.UncheckedIOException;
 
 import javax.tools.JavaFileManager;
 
@@ -123,8 +124,8 @@
             if (fileManager instanceof JavacFileManager) {
                 try {
                     ((JavacFileManager) fileManager).close();
-                } catch (IOException e) {
-                    return RC_FATAL;
+                } catch (IOException es) {
+                    throw new UncheckedIOException(es);
                 }
             }
             return result.exitCode;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
index 496f039..5a67380 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -131,7 +133,7 @@
             return file;
         }
 
-        if (visibleSources.contains(file.toUri())) {
+        if (visibleSources.contains(file.toUri()) || isModuleInfo(file)) {
             return file;
         }
         return null;
@@ -166,12 +168,21 @@
             return file;
         }
 
-        if (visibleSources.contains(file.toUri())) {
+        if (visibleSources.contains(file.toUri()) || isModuleInfo(file)) {
             return file;
         }
         return null;
     }
 
+    private boolean isModuleInfo(FileObject fo) {
+        if (fo instanceof JavaFileObject) {
+            JavaFileObject jfo = (JavaFileObject) fo;
+            return jfo.isNameCompatible("module-info", Kind.SOURCE)
+                || jfo.isNameCompatible("module-info", Kind.CLASS);
+        }
+        return false;
+    }
+
     @Override @DefinedBy(Api.COMPILER)
     public FileObject getFileForOutput(Location location,
                                        String packageName,
@@ -192,6 +203,11 @@
         return file;
     }
 
+    @Override
+    public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+        return super.getModuleLocation(location, locUnwrap(fo), pkgName);
+    }
+
     private static String packageNameFromFileName(String fn) {
         StringBuilder sb = new StringBuilder();
         int p = fn.indexOf('_'), pp = 0;
diff --git a/langtools/src/jdk.compiler/share/classes/module-info.java b/langtools/src/jdk.compiler/share/classes/module-info.java
new file mode 100644
index 0000000..91a0e22
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/module-info.java
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * 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.
+ */
+
+module jdk.compiler {
+    requires public java.compiler;
+
+    exports com.sun.source.doctree;
+    exports com.sun.source.tree;
+    exports com.sun.source.util;
+    exports com.sun.tools.javac;
+    exports com.sun.tools.javah;
+    exports com.sun.tools.doclint to
+        jdk.javadoc;
+    exports com.sun.tools.javac.api to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.code to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.comp to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.file to
+        jdk.jdeps,
+        jdk.javadoc;
+    exports com.sun.tools.javac.jvm to
+        jdk.javadoc;
+    exports com.sun.tools.javac.main to
+        jdk.javadoc;
+    exports com.sun.tools.javac.model to
+        jdk.javadoc;
+    exports com.sun.tools.javac.parser to
+        jdk.jshell;
+    exports com.sun.tools.javac.platform to
+        jdk.javadoc;
+    exports com.sun.tools.javac.tree to
+        jdk.javadoc,
+        jdk.jshell;
+    exports com.sun.tools.javac.util to
+        jdk.jdeps,
+        jdk.javadoc,
+        jdk.jshell;
+
+    uses javax.annotation.processing.Processor;
+    uses com.sun.source.util.Plugin;
+    uses com.sun.tools.javac.platform.PlatformProvider;
+
+    provides com.sun.tools.javac.platform.PlatformProvider
+        with com.sun.tools.javac.platform.JDKPlatformProvider;
+
+    provides javax.tools.JavaCompiler
+        with com.sun.tools.javac.api.JavacTool;
+}
+
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
index 9378865..3adbee4 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -155,15 +155,8 @@
             htmlTree.addStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
-            if (configuration.showProfiles) {
-                addAllProfilesLink(ul);
-            }
             htmlTree.addContent(ul);
             body.addContent(htmlTree);
-            if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
-                Content profileSummary = configuration.getResource("doclet.Profiles");
-                addProfilesList(profileSummary, body);
-            }
             addPackagesList(packages, text, tableSummary, body);
         }
     }
@@ -201,21 +194,4 @@
      */
     protected void addAllClassesLink(Content div) {
     }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param div the document tree to which the all profiles link will be added
-     */
-    protected void addAllProfilesLink(Content div) {
-    }
-
-    /**
-     * Do nothing. This will be overridden.
-     *
-     * @param profileSummary the profile summary heading
-     * @param body the content tree to which the profiles list will be added
-     */
-    protected void addProfilesList(Content profileSummary, Content body) {
-    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java
deleted file mode 100644
index f8928c2..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.DocPath;
-
-/**
- * Abstract class to generate the profile overview files in
- * Frame and Non-Frame format. This will be sub-classed to
- * generate profile-overview-frame.html as well as profile-overview-summary.html.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public abstract class AbstractProfileIndexWriter extends HtmlDocletWriter {
-
-    /**
-     * Profiles to be documented.
-     */
-    protected Profiles profiles;
-
-    /**
-     * Constructor. Also initializes the profiles variable.
-     *
-     * @param configuration  The current configuration
-     * @param filename Name of the profile index file to be generated.
-     */
-    public AbstractProfileIndexWriter(ConfigurationImpl configuration,
-                                      DocPath filename) throws IOException {
-        super(configuration, filename);
-        profiles = configuration.profiles;
-    }
-
-    /**
-     * Adds the navigation bar header to the documentation tree.
-     *
-     * @param body the document tree to which the navigation bar header will be added
-     */
-    protected abstract void addNavigationBarHeader(Content body);
-
-    /**
-     * Adds the navigation bar footer to the documentation tree.
-     *
-     * @param body the document tree to which the navigation bar footer will be added
-     */
-    protected abstract void addNavigationBarFooter(Content body);
-
-    /**
-     * Adds the overview header to the documentation tree.
-     *
-     * @param body the document tree to which the overview header will be added
-     */
-    protected abstract void addOverviewHeader(Content body);
-
-    /**
-     * Adds the profiles list to the documentation tree.
-     *
-     * @param profiles profiles object
-     * @param text caption for the table
-     * @param tableSummary summary for the table
-     * @param body the document tree to which the profiles list will be added
-     */
-    protected abstract void addProfilesList(Profiles profiles, String text,
-            String tableSummary, Content body);
-
-    /**
-     * Adds the profile packages list to the documentation tree.
-     *
-     * @param profiles profiles object
-     * @param text caption for the table
-     * @param tableSummary summary for the table
-     * @param body the document tree to which the profiles list will be added
-     * @param profileName the name for the profile being documented
-     */
-    protected abstract void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName);
-
-    /**
-     * Generate and prints the contents in the profile index file. Call appropriate
-     * methods from the sub-class in order to generate Frame or Non
-     * Frame format.
-     *
-     * @param title the title of the window.
-     * @param includeScript boolean set true if windowtitle script is to be included
-     */
-    protected void buildProfileIndexFile(String title, boolean includeScript) throws IOException {
-        String windowOverview = configuration.getText(title);
-        Content body = getBody(includeScript, getWindowTitle(windowOverview));
-        addNavigationBarHeader(body);
-        addOverviewHeader(body);
-        addIndex(body);
-        addOverview(body);
-        addNavigationBarFooter(body);
-        printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title,
-                configuration.doctitle), includeScript, body);
-    }
-
-    /**
-     * Generate and prints the contents in the profile packages index file. Call appropriate
-     * methods from the sub-class in order to generate Frame or Non
-     * Frame format.
-     *
-     * @param title the title of the window.
-     * @param includeScript boolean set true if windowtitle script is to be included
-     * @param profileName the name of the profile being documented
-     */
-    protected void buildProfilePackagesIndexFile(String title,
-            boolean includeScript, String profileName) throws IOException {
-        String windowOverview = configuration.getText(title);
-        Content body = getBody(includeScript, getWindowTitle(windowOverview));
-        addNavigationBarHeader(body);
-        addOverviewHeader(body);
-        addProfilePackagesIndex(body, profileName);
-        addOverview(body);
-        addNavigationBarFooter(body);
-        printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title,
-                configuration.doctitle), includeScript, body);
-    }
-
-    /**
-     * Default to no overview, override to add overview.
-     *
-     * @param body the document tree to which the overview will be added
-     */
-    protected void addOverview(Content body) throws IOException {
-    }
-
-    /**
-     * Adds the frame or non-frame profile index to the documentation tree.
-     *
-     * @param body the document tree to which the index will be added
-     */
-    protected void addIndex(Content body) {
-        addIndexContents(profiles, "doclet.Profile_Summary",
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Profile_Summary"),
-                configuration.getText("doclet.profiles")), body);
-    }
-
-    /**
-     * Adds the frame or non-frame profile packages index to the documentation tree.
-     *
-     * @param body the document tree to which the index will be added
-     * @param profileName  the name of the profile being documented
-     */
-    protected void addProfilePackagesIndex(Content body, String profileName) {
-        addProfilePackagesIndexContents(profiles, "doclet.Profile_Summary",
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Profile_Summary"),
-                configuration.getText("doclet.profiles")), body, profileName);
-    }
-
-    /**
-     * Adds profile index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param profiles profiles to be documented
-     * @param text string which will be used as the heading
-     * @param tableSummary summary for the table
-     * @param body the document tree to which the index contents will be added
-     */
-    protected void addIndexContents(Profiles profiles, String text,
-            String tableSummary, Content body) {
-        if (profiles.getProfileCount() > 0) {
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
-                    ? HtmlTree.NAV()
-                    : new HtmlTree(HtmlTag.DIV);
-            htmlTree.addStyle(HtmlStyle.indexNav);
-            HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            addAllClassesLink(ul);
-            addAllPackagesLink(ul);
-            htmlTree.addContent(ul);
-            body.addContent(htmlTree);
-            addProfilesList(profiles, text, tableSummary, body);
-        }
-    }
-
-    /**
-     * Adds profile packages index contents. Call appropriate methods from
-     * the sub-classes. Adds it to the body HtmlTree
-     *
-     * @param profiles profiles to be documented
-     * @param text string which will be used as the heading
-     * @param tableSummary summary for the table
-     * @param body the document tree to which the index contents will be added
-     * @param profileName the name of the profile being documented
-     */
-    protected void addProfilePackagesIndexContents(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
-                ? HtmlTree.NAV()
-                : new HtmlTree(HtmlTag.DIV);
-        htmlTree.addStyle(HtmlStyle.indexNav);
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        addAllClassesLink(ul);
-        addAllPackagesLink(ul);
-        addAllProfilesLink(ul);
-        htmlTree.addContent(ul);
-        body.addContent(htmlTree);
-        addProfilePackagesList(profiles, text, tableSummary, body, profileName);
-    }
-
-    /**
-     * Adds the doctitle to the documentation tree, if it is specified on the command line.
-     *
-     * @param body the document tree to which the title will be added
-     */
-    protected void addConfigurationTitle(Content body) {
-        if (configuration.doctitle.length() > 0) {
-            Content title = new RawHtml(configuration.doctitle);
-            Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING,
-                    HtmlStyle.title, title);
-            Content div = HtmlTree.DIV(HtmlStyle.header, heading);
-            body.addContent(div);
-        }
-    }
-
-    /**
-     * Returns highlighted "Overview", in the navigation bar as this is the
-     * overview page.
-     *
-     * @return a Content object to be added to the documentation tree
-     */
-    protected Content getNavLinkContents() {
-        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, overviewLabel);
-        return li;
-    }
-
-    /**
-     * Do nothing. This will be overridden in ProfileIndexFrameWriter.
-     *
-     * @param div the document tree to which the all classes link will be added
-     */
-    protected void addAllClassesLink(Content div) {
-    }
-
-    /**
-     * Do nothing. This will be overridden in ProfileIndexFrameWriter.
-     *
-     * @param div the document tree to which the all packages link will be added
-     */
-    protected void addAllPackagesLink(Content div) {
-    }
-
-    /**
-     * Do nothing. This will be overridden in ProfilePackageIndexFrameWriter.
-     *
-     * @param div the document tree to which the all profiles link will be added
-     */
-    protected void addAllProfilesLink(Content div) {
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
index d9dafe9..6eac715 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.javadoc.RootDocImpl;
 import com.sun.tools.doclets.formats.html.markup.*;
 import com.sun.tools.doclets.internal.toolkit.*;
@@ -173,23 +172,13 @@
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
-        if (configuration.showProfiles) {
-            String sep = "";
-            int profile = configuration.profiles.getProfile(getTypeNameForProfile(classDoc));
-            if (profile > 0) {
-                Content profNameContent = new StringContent();
-                for (int i = profile; i < configuration.profiles.getProfileCount(); i++) {
-                    profNameContent.addContent(sep);
-                    profNameContent.addContent(Profile.lookup(i).name);
-                    sep = ", ";
-                }
-                Content profileNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, profNameContent);
-                div.addContent(profileNameDiv);
-            }
-        }
         if (pkgname.length() > 0) {
-            Content pkgNameContent = new StringContent(pkgname);
-            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent);
+            Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel);
+            Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
+            pkgNameDiv.addContent(getSpace());
+            Content pkgNameContent = getTargetPackageLink(classDoc.containingPackage(),
+                    "classFrame", new StringContent(pkgname));
+            pkgNameDiv.addContent(pkgNameContent);
             div.addContent(pkgNameDiv);
         }
         LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
index b4e3440..5751a70 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -29,6 +29,8 @@
 import java.util.*;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardLocation;
 
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.formats.html.markup.*;
@@ -641,6 +643,12 @@
         return new ContentBuilder();
     }
 
+    @Override
+    public Location getLocationForPackage(PackageDoc pd) {
+        JavaFileManager fm = getFileManager();
+        return StandardLocation.SOURCE_PATH;
+    }
+
     protected void buildSearchTagIndex() {
         for (SearchIndexItem sii : tagSearchIndex) {
             String tagLabel = sii.getLabel();
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
index 4f0ce43..edae147 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.builders.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -238,6 +237,7 @@
             } catch (IOException e) {
                 throw new DocletAbortException(e);
             } catch (DocletAbortException de) {
+                de.printStackTrace();
                 throw de;
             } catch (Exception e) {
                 e.printStackTrace();
@@ -246,51 +246,6 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    protected void generateProfileFiles() throws Exception {
-        if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
-            ProfileIndexFrameWriter.generate(configuration);
-            Profile prevProfile = null, nextProfile;
-            String profileName;
-            for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
-                profileName = Profile.lookup(i).name;
-                // Generate profile package pages only if there are any packages
-                // in a profile to be documented. The profilePackages map will not
-                // contain an entry for the profile if there are no packages to be documented.
-                if (!configuration.shouldDocumentProfile(profileName))
-                    continue;
-                ProfilePackageIndexFrameWriter.generate(configuration, profileName);
-                List<PackageDoc> packages = configuration.profilePackages.get(
-                        profileName);
-                PackageDoc prev = null, next;
-                for (int j = 0; j < packages.size(); j++) {
-                    // if -nodeprecated option is set and the package is marked as
-                    // deprecated, do not generate the profilename-package-summary.html
-                    // and profilename-package-frame.html pages for that package.
-                    PackageDoc pkg = packages.get(j);
-                    if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                        ProfilePackageFrameWriter.generate(configuration, pkg, i);
-                        next = getNamedPackage(packages, j + 1);
-                        AbstractBuilder profilePackageSummaryBuilder =
-                                configuration.getBuilderFactory().getProfilePackageSummaryBuilder(
-                                pkg, prev, next, Profile.lookup(i));
-                        profilePackageSummaryBuilder.build();
-                        prev = pkg;
-                    }
-                }
-                nextProfile = (i + 1 < configuration.profiles.getProfileCount()) ?
-                        Profile.lookup(i + 1) : null;
-                AbstractBuilder profileSummaryBuilder =
-                        configuration.getBuilderFactory().getProfileSummaryBuilder(
-                        Profile.lookup(i), prevProfile, nextProfile);
-                profileSummaryBuilder.build();
-                prevProfile = Profile.lookup(i);
-            }
-        }
-    }
-
     PackageDoc getNamedPackage(List<PackageDoc> list, int idx) {
         if (idx < list.size()) {
             PackageDoc pkg = list.get(idx);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
index 63a64a0..e2a6046 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -287,106 +287,6 @@
     }
 
     /**
-     * Get Profile Package link, with target frame.
-     *
-     * @param pd the packageDoc object
-     * @param target name of the target frame
-     * @param label tag for the link
-     * @param profileName the name of the profile being documented
-     * @return a content for the target profile packages link
-     */
-    public Content getTargetProfilePackageLink(PackageDoc pd, String target,
-            Content label, String profileName) {
-        return getHyperLink(pathString(pd, DocPaths.profilePackageSummary(profileName)),
-                label, "", target);
-    }
-
-    /**
-     * Get Profile link, with target frame.
-     *
-     * @param target name of the target frame
-     * @param label tag for the link
-     * @param profileName the name of the profile being documented
-     * @return a content for the target profile link
-     */
-    public Content getTargetProfileLink(String target, Content label,
-            String profileName) {
-        return getHyperLink(pathToRoot.resolve(
-                DocPaths.profileSummary(profileName)), label, "", target);
-    }
-
-    /**
-     * Get the type name for profile search.
-     *
-     * @param cd the classDoc object for which the type name conversion is needed
-     * @return a type name string for the type
-     */
-    public String getTypeNameForProfile(ClassDoc cd) {
-        StringBuilder typeName =
-                new StringBuilder((cd.containingPackage()).name().replace(".", "/"));
-        typeName.append("/")
-                .append(cd.name().replace(".", "$"));
-        return typeName.toString();
-    }
-
-    /**
-     * Check if a type belongs to a profile.
-     *
-     * @param cd the classDoc object that needs to be checked
-     * @param profileValue the profile in which the type needs to be checked
-     * @return true if the type is in the profile
-     */
-    public boolean isTypeInProfile(ClassDoc cd, int profileValue) {
-        return (configuration.profiles.getProfile(getTypeNameForProfile(cd)) <= profileValue);
-    }
-
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content summaryContentTree,
-            int profileValue) {
-        if(classes.length > 0) {
-            Arrays.sort(classes);
-            Content caption = getTableCaption(new RawHtml(label));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
-            table.addContent(getSummaryTableHeader(tableHeader, "col"));
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            for (int i = 0; i < classes.length; i++) {
-                if (!isTypeInProfile(classes[i], profileValue)) {
-                    continue;
-                }
-                if (!utils.isCoreClass(classes[i]) ||
-                    !configuration.isGeneratedDoc(classes[i])) {
-                    continue;
-                }
-                Content classContent = getLink(new LinkInfoImpl(
-                        configuration, LinkInfoImpl.Kind.PACKAGE, classes[i]));
-                Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
-                HtmlTree tr = HtmlTree.TR(tdClass);
-                if (i%2 == 0)
-                    tr.addStyle(HtmlStyle.altColor);
-                else
-                    tr.addStyle(HtmlStyle.rowColor);
-                HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
-                tdClassDescription.addStyle(HtmlStyle.colLast);
-                if (utils.isDeprecated(classes[i])) {
-                    tdClassDescription.addContent(deprecatedLabel);
-                    if (classes[i].tags("deprecated").length > 0) {
-                        addSummaryDeprecatedComment(classes[i],
-                            classes[i].tags("deprecated")[0], tdClassDescription);
-                    }
-                }
-                else
-                    addSummaryComment(classes[i], tdClassDescription);
-                tr.addContent(tdClassDescription);
-                tbody.addContent(tr);
-            }
-            table.addContent(tbody);
-            summaryContentTree.addContent(table);
-        }
-    }
-
-    /**
      * Generates the HTML document tree and prints it out.
      *
      * @param metakeywords Array of String keywords for META tag. Each element
@@ -593,6 +493,8 @@
                 fixedNavDiv.addContent(subDiv);
                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
                 tree.addContent(fixedNavDiv);
+                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, getSpace());
+                tree.addContent(paddingDiv);
             } else {
                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
                 tree.addContent(subDiv);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
index e24d25f..10b0a8b 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -158,19 +158,6 @@
     }
 
     /**
-     * Adds "All Profiles" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the "All Profiles" link should be added
-     */
-    protected void addAllProfilesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.PROFILE_OVERVIEW_FRAME,
-                allprofilesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
      * {@inheritDoc}
      */
     protected void addNavigationBarFooter(Content body) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
index 93070da..6cf48e4 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.formats.html.markup.*;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -127,34 +126,6 @@
     /**
      * {@inheritDoc}
      */
-    protected void addProfilesList(Content profileSummary, Content body) {
-        Content h2 = HtmlTree.HEADING(HtmlTag.H2, profileSummary);
-        Content profilesDiv = HtmlTree.DIV(h2);
-        Content ul = new HtmlTree(HtmlTag.UL);
-        String profileName;
-        for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
-            profileName = Profile.lookup(i).name;
-            // If the profile has valid packages to be documented, add it to the
-            // profiles list on overview-summary.html page.
-            if (configuration.shouldDocumentProfile(profileName)) {
-                Content profileLinkContent = getTargetProfileLink("classFrame",
-                        new StringContent(profileName), profileName);
-                Content li = HtmlTree.LI(profileLinkContent);
-                ul.addContent(li);
-            }
-        }
-        profilesDiv.addContent(ul);
-        Content div = HtmlTree.DIV(HtmlStyle.contentContainer, profilesDiv);
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            htmlTree.addContent(div);
-        } else {
-            body.addContent(div);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     protected void addPackagesList(Collection<PackageDoc> packages, String text,
             String tableSummary, Content body) {
         Content table = (configuration.isOutputHtml5())
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java
deleted file mode 100644
index 18f45c0..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-import com.sun.tools.javac.jvm.Profile;
-
-/**
- * Generate the profile index for the left-hand frame in the generated output.
- * A click on the profile name in this frame will update the page in the top
- * left hand frame with the listing of packages of the clicked profile.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter {
-
-    /**
-     * Construct the ProfileIndexFrameWriter object.
-     *
-     * @param configuration the configuration object
-     * @param filename Name of the profile index file to be generated.
-     */
-    public ProfileIndexFrameWriter(ConfigurationImpl configuration,
-                                   DocPath filename) throws IOException {
-        super(configuration, filename);
-    }
-
-    /**
-     * Generate the profile index file named "profile-overview-frame.html".
-     * @throws DocletAbortException
-     * @param configuration the configuration object
-     */
-    public static void generate(ConfigurationImpl configuration) {
-        ProfileIndexFrameWriter profilegen;
-        DocPath filename = DocPaths.PROFILE_OVERVIEW_FRAME;
-        try {
-            profilegen = new ProfileIndexFrameWriter(configuration, filename);
-            profilegen.buildProfileIndexFile("doclet.Window_Overview", false);
-            profilegen.close();
-        } catch (IOException exc) {
-            configuration.standardmessage.error(
-                        "doclet.exception_encountered",
-                        exc.toString(), filename);
-            throw new DocletAbortException(exc);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addProfilesList(Profiles profiles, String text,
-            String tableSummary, Content body) {
-        Content heading = HtmlTree.HEADING(HtmlConstants.PROFILE_HEADING, true,
-                profilesLabel);
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
-                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
-                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setTitle(profilesLabel);
-        String profileName;
-        for (int i = 1; i < profiles.getProfileCount(); i++) {
-            profileName = (Profile.lookup(i)).name;
-            // If the profile has valid packages to be documented, add it to the
-            // left-frame generated for profile index.
-            if (configuration.shouldDocumentProfile(profileName))
-                ul.addContent(getProfile(profileName));
-        }
-        htmlTree.addContent(ul);
-        body.addContent(htmlTree);
-    }
-
-    /**
-     * Returns each profile name as a separate link.
-     *
-     * @param profileName the profile being documented
-     * @return content for the profile link
-     */
-    protected Content getProfile(String profileName) {
-        Content profileLinkContent;
-        Content profileLabel;
-        profileLabel = new StringContent(profileName);
-        profileLinkContent = getHyperLink(DocPaths.profileFrame(profileName), profileLabel, "",
-                    "packageListFrame");
-        Content li = HtmlTree.LI(profileLinkContent);
-        return li;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarHeader(Content body) {
-        Content headerContent;
-        if (configuration.packagesheader.length() > 0) {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
-        } else {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
-        }
-        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.bar, headerContent);
-        body.addContent(heading);
-    }
-
-    /**
-     * Do nothing as there is no overview information in this page.
-     */
-    protected void addOverviewHeader(Content body) {
-    }
-
-    /**
-     * Adds "All Classes" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all classes link should be added
-     */
-    protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
-                allclassesLabel, "", "packageFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * Adds "All Packages" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all packages link should be added
-     */
-    protected void addAllPackagesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
-                allpackagesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarFooter(Content body) {
-        Content p = HtmlTree.P(getSpace());
-        body.addContent(p);
-    }
-
-    protected void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java
deleted file mode 100644
index cbe23cf..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageFrameWriter.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-import java.util.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each package contents of a profile in the left-hand bottom
- * frame. This will list all the Class Kinds in the package for a profile. A click on any
- * class-kind will update the right-hand frame with the clicked class-kind page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageFrameWriter extends HtmlDocletWriter {
-
-    /**
-     * The package being documented.
-     */
-    private PackageDoc packageDoc;
-
-    /**
-     * Constructor to construct ProfilePackageFrameWriter object and to generate
-     * "profilename-package-frame.html" file in the respective package directory.
-     * For example for profile compact1 and package "java.lang" this will generate file
-     * "compact1-package-frame.html" file in the "java/lang" directory. It will also
-     * create "java/lang" directory in the current or the destination directory
-     * if it doesn't exist.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param packageDoc PackageDoc under consideration.
-     * @param profileName the name of the profile being documented
-     */
-    public ProfilePackageFrameWriter(ConfigurationImpl configuration,
-            PackageDoc packageDoc, String profileName)
-            throws IOException {
-        super(configuration, DocPath.forPackage(packageDoc).resolve(
-                DocPaths.profilePackageFrame(profileName)));
-        this.packageDoc = packageDoc;
-    }
-
-    /**
-     * Generate a profile package summary page for the left-hand bottom frame. Construct
-     * the ProfilePackageFrameWriter object and then uses it generate the file.
-     *
-     * @param configuration the current configuration of the doclet.
-     * @param packageDoc The package for which "profilename-package-frame.html" is to be generated.
-     * @param profileValue the value of the profile being documented
-     */
-    public static void generate(ConfigurationImpl configuration,
-            PackageDoc packageDoc, int profileValue) {
-        ProfilePackageFrameWriter profpackgen;
-        try {
-            String profileName = Profile.lookup(profileValue).name;
-            profpackgen = new ProfilePackageFrameWriter(configuration, packageDoc,
-                    profileName);
-            StringBuilder winTitle = new StringBuilder(profileName);
-            String sep = " - ";
-            winTitle.append(sep);
-            String pkgName = configuration.utils.getPackageName(packageDoc);
-            winTitle.append(pkgName);
-            HtmlTree body = profpackgen.getBody(false,
-                    profpackgen.getWindowTitle(winTitle.toString()));
-            Content profName = new StringContent(profileName);
-            Content sepContent = new StringContent(sep);
-            Content pkgNameContent = new RawHtml(pkgName);
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
-                    ? HtmlTree.MAIN()
-                    : body;
-            Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, HtmlStyle.bar,
-                    profpackgen.getTargetProfileLink("classFrame", profName, profileName));
-            heading.addContent(sepContent);
-            heading.addContent(profpackgen.getTargetProfilePackageLink(packageDoc,
-                    "classFrame", pkgNameContent, profileName));
-            htmlTree.addContent(heading);
-            HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.indexContainer);
-            profpackgen.addClassListing(div, profileValue);
-            htmlTree.addContent(div);
-            if (configuration.allowTag(HtmlTag.MAIN)) {
-                body.addContent(htmlTree);
-            }
-            profpackgen.printHtmlDocument(
-                    configuration.metakeywords.getMetaKeywords(packageDoc), false, body);
-            profpackgen.close();
-        } catch (IOException exc) {
-            configuration.standardmessage.error(
-                    "doclet.exception_encountered",
-                    exc.toString(), DocPaths.PACKAGE_FRAME.getPath());
-            throw new DocletAbortException(exc);
-        }
-    }
-
-    /**
-     * Add class listing for all the classes in this package. Divide class
-     * listing as per the class kind and generate separate listing for
-     * Classes, Interfaces, Exceptions and Errors.
-     *
-     * @param contentTree the content tree to which the listing will be added
-     * @param profileValue the value of the profile being documented
-     */
-    protected void addClassListing(HtmlTree contentTree, int profileValue) {
-        if (packageDoc.isIncluded()) {
-            addClassKindListing(packageDoc.interfaces(),
-                getResource("doclet.Interfaces"), contentTree, profileValue);
-            addClassKindListing(packageDoc.ordinaryClasses(),
-                getResource("doclet.Classes"), contentTree, profileValue);
-            addClassKindListing(packageDoc.enums(),
-                getResource("doclet.Enums"), contentTree, profileValue);
-            addClassKindListing(packageDoc.exceptions(),
-                getResource("doclet.Exceptions"), contentTree, profileValue);
-            addClassKindListing(packageDoc.errors(),
-                getResource("doclet.Errors"), contentTree, profileValue);
-            addClassKindListing(packageDoc.annotationTypes(),
-                getResource("doclet.AnnotationTypes"), contentTree, profileValue);
-        }
-    }
-
-    /**
-     * Add specific class kind listing. Also add label to the listing.
-     *
-     * @param arr Array of specific class kinds, namely Class or Interface or Exception or Error
-     * @param labelContent content tree of the label to be added
-     * @param contentTree the content tree to which the class kind listing will be added
-     * @param profileValue the value of the profile being documented
-     */
-    protected void addClassKindListing(ClassDoc[] arr, Content labelContent,
-            HtmlTree contentTree, int profileValue) {
-        if(arr.length > 0) {
-            Arrays.sort(arr);
-            boolean printedHeader = false;
-            HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                    ? HtmlTree.SECTION()
-                    : contentTree;
-            HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            ul.setTitle(labelContent);
-            for (ClassDoc classDoc : arr) {
-                if (!isTypeInProfile(classDoc, profileValue)) {
-                    continue;
-                }
-                if (!utils.isCoreClass(classDoc) || !
-                        configuration.isGeneratedDoc(classDoc)) {
-                    continue;
-                }
-                if (!printedHeader) {
-                    Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
-                                                       true, labelContent);
-                    htmlTree.addContent(heading);
-                    printedHeader = true;
-                }
-                Content arr_i_name = new StringContent(classDoc.name());
-                if (classDoc.isInterface())
-                    arr_i_name = HtmlTree.SPAN(HtmlStyle.interfaceName, arr_i_name);
-                Content link = getLink(new LinkInfoImpl(configuration,
-                                                        LinkInfoImpl.Kind.PACKAGE_FRAME, classDoc).label(arr_i_name).target("classFrame"));
-                Content li = HtmlTree.LI(link);
-                ul.addContent(li);
-            }
-            htmlTree.addContent(ul);
-            if (configuration.allowTag(HtmlTag.SECTION)) {
-                contentTree.addContent(htmlTree);
-            }
-        }
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java
deleted file mode 100644
index 9a705d5..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageIndexFrameWriter.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Generate the profile package index for the left-hand frame in the generated output.
- * A click on the package name in this frame will update the page in the bottom
- * left hand frame with the listing of contents of the clicked profile package.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageIndexFrameWriter extends AbstractProfileIndexWriter {
-
-    /**
-     * Construct the ProfilePackageIndexFrameWriter object.
-     *
-     * @param configuration the configuration object
-     * @param filename Name of the package index file to be generated.
-     */
-    public ProfilePackageIndexFrameWriter(ConfigurationImpl configuration,
-                                   DocPath filename) throws IOException {
-        super(configuration, filename);
-    }
-
-    /**
-     * Generate the profile package index file.
-     * @throws DocletAbortException
-     * @param configuration the configuration object
-     * @param profileName the name of the profile being documented
-     */
-    public static void generate(ConfigurationImpl configuration, String profileName) {
-        ProfilePackageIndexFrameWriter profpackgen;
-        DocPath filename = DocPaths.profileFrame(profileName);
-        try {
-            profpackgen = new ProfilePackageIndexFrameWriter(configuration, filename);
-            profpackgen.buildProfilePackagesIndexFile("doclet.Window_Overview", false, profileName);
-            profpackgen.close();
-        } catch (IOException exc) {
-            configuration.standardmessage.error(
-                        "doclet.exception_encountered",
-                        exc.toString(), filename);
-            throw new DocletAbortException(exc);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addProfilePackagesList(Profiles profiles, String text,
-            String tableSummary, Content body, String profileName) {
-        Content profNameContent = new StringContent(profileName);
-        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
-                getTargetProfileLink("classFrame", profNameContent, profileName));
-        heading.addContent(getSpace());
-        heading.addContent(packagesLabel);
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
-                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
-                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.setTitle(packagesLabel);
-        List<PackageDoc> packages = configuration.profilePackages.get(profileName);
-        for (PackageDoc packageDoc : packages) {
-            if ((!(configuration.nodeprecated && utils.isDeprecated(packageDoc)))) {
-                ul.addContent(getPackage(packageDoc, profileName));
-            }
-        }
-        htmlTree.addContent(ul);
-        body.addContent(htmlTree);
-    }
-
-    /**
-     * Returns each package name as a separate link.
-     *
-     * @param pd PackageDoc
-     * @param profileName the name of the profile being documented
-     * @return content for the package link
-     */
-    protected Content getPackage(PackageDoc pd, String profileName) {
-        Content packageLinkContent;
-        Content pkgLabel;
-        if (pd.name().length() > 0) {
-            pkgLabel = getPackageLabel(pd.name());
-            packageLinkContent = getHyperLink(pathString(pd,
-                     DocPaths.profilePackageFrame(profileName)), pkgLabel, "",
-                    "packageFrame");
-        } else {
-            pkgLabel = new StringContent("<unnamed package>");
-            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
-                    pkgLabel, "", "packageFrame");
-        }
-        Content li = HtmlTree.LI(packageLinkContent);
-        return li;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarHeader(Content body) {
-        Content headerContent;
-        if (configuration.packagesheader.length() > 0) {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
-        } else {
-            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
-        }
-        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.bar, headerContent);
-        body.addContent(heading);
-    }
-
-    /**
-     * Do nothing as there is no overview information in this page.
-     */
-    protected void addOverviewHeader(Content body) {
-    }
-
-    protected void addProfilesList(Profiles profiles, String text,
-            String tableSummary, Content body) {
-    }
-
-    /**
-     * Adds "All Classes" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all classes link should be added
-     */
-    protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
-                allclassesLabel, "", "packageFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * Adds "All Packages" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all packages link should be added
-     */
-    protected void addAllPackagesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
-                allpackagesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * Adds "All Profiles" link for the top of the left-hand frame page to the
-     * documentation tree.
-     *
-     * @param ul the Content object to which the all profiles link should be added
-     */
-    protected void addAllProfilesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.PROFILE_OVERVIEW_FRAME,
-                allprofilesLabel, "", "packageListFrame");
-        Content li = HtmlTree.LI(linkContent);
-        ul.addContent(li);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void addNavigationBarFooter(Content body) {
-        Content p = HtmlTree.P(getSpace());
-        body.addContent(p);
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java
deleted file mode 100644
index 903bcf9..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfilePackageWriterImpl.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each profile package contents in the right-hand
- * frame. This will list all the Class Kinds in the package. A click on any
- * class-kind will update the frame with the clicked class-kind page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageWriterImpl extends HtmlDocletWriter
-    implements ProfilePackageSummaryWriter {
-
-    /**
-     * The prev package name in the alpha-order list.
-     */
-    protected PackageDoc prev;
-
-    /**
-     * The next package name in the alpha-order list.
-     */
-    protected PackageDoc next;
-
-    /**
-     * The profile package being documented.
-     */
-    protected PackageDoc packageDoc;
-
-    /**
-     * The name of the profile being documented.
-     */
-    protected String profileName;
-
-    /**
-     * The value of the profile being documented.
-     */
-    protected int profileValue;
-
-    /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
-     * The HTML tree for section tag.
-     */
-    protected HtmlTree sectionTree = HtmlTree.SECTION();
-
-    /**
-     * Constructor to construct ProfilePackageWriter object and to generate
-     * "profilename-package-summary.html" file in the respective package directory.
-     * For example for profile compact1 and package "java.lang" this will generate file
-     * "compact1-package-summary.html" file in the "java/lang" directory. It will also
-     * create "java/lang" directory in the current or the destination directory
-     * if it doesn't exist.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param packageDoc    PackageDoc under consideration.
-     * @param prev          Previous package in the sorted array.
-     * @param next          Next package in the sorted array.
-     * @param profile       The profile being documented.
-     */
-    public ProfilePackageWriterImpl(ConfigurationImpl configuration,
-            PackageDoc packageDoc, PackageDoc prev, PackageDoc next,
-            Profile profile) throws IOException {
-        super(configuration, DocPath.forPackage(packageDoc).resolve(
-                DocPaths.profilePackageSummary(profile.name)));
-        this.prev = prev;
-        this.next = next;
-        this.packageDoc = packageDoc;
-        this.profileName = profile.name;
-        this.profileValue = profile.value;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageHeader(String heading) {
-        HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getPackageName(packageDoc)));
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
-                ? HtmlTree.HEADER()
-                : bodyTree;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
-        if (configuration.allowTag(HtmlTag.HEADER)) {
-            bodyTree.addContent(htmlTree);
-        }
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
-        Content profileContent = new StringContent(profileName);
-        Content profileNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, profileContent);
-        div.addContent(profileNameDiv);
-        Content annotationContent = new HtmlTree(HtmlTag.P);
-        addAnnotationInfo(packageDoc, annotationContent);
-        div.addContent(annotationContent);
-        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.title, packageLabel);
-        tHeading.addContent(getSpace());
-        Content packageHead = new RawHtml(heading);
-        tHeading.addContent(packageHead);
-        div.addContent(tHeading);
-        addDeprecationInfo(div);
-        if (packageDoc.inlineTags().length > 0 && ! configuration.nocomment) {
-            HtmlTree docSummaryDiv = new HtmlTree(HtmlTag.DIV);
-            docSummaryDiv.addStyle(HtmlStyle.docSummary);
-            addSummaryComment(packageDoc, docSummaryDiv);
-            div.addContent(docSummaryDiv);
-            Content space = getSpace();
-            Content descLink = getHyperLink(getDocLink(
-                    SectionName.PACKAGE_DESCRIPTION),
-                    descriptionLabel, "", "");
-            Content descPara = new HtmlTree(HtmlTag.P, seeLabel, space, descLink);
-            div.addContent(descPara);
-        }
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(div);
-        } else {
-            bodyTree.addContent(div);
-        }
-        return bodyTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getContentHeader() {
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
-        return div;
-    }
-
-    /**
-     * Add the package deprecation information to the documentation tree.
-     *
-     * @param div the content tree to which the deprecation information will be added
-     */
-    public void addDeprecationInfo(Content div) {
-        Tag[] deprs = packageDoc.tags("deprecated");
-        if (utils.isDeprecated(packageDoc)) {
-            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecatedContent);
-            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
-            deprDiv.addContent(deprPhrase);
-            if (deprs.length > 0) {
-                Tag[] commentTags = deprs[0].inlineTags();
-                if (commentTags.length > 0) {
-                    addInlineDeprecatedComment(packageDoc, deprs[0], deprDiv);
-                }
-            }
-            div.addContent(deprDiv);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree) {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
-        addClassesSummary(classes, label, tableSummary, tableHeader,
-                li, profileValue);
-        packageSummaryContentTree.addContent(li);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryHeader() {
-        HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
-        return ul;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageDescription(Content packageContentTree) {
-        if (packageDoc.inlineTags().length > 0) {
-            packageContentTree.addContent(
-                    getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION));
-            Content h2Content = new StringContent(
-                    configuration.getText("doclet.Package_Description",
-                    packageDoc.name()));
-            Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, h2Content);
-            if (configuration.allowTag(HtmlTag.SECTION)) {
-                sectionTree.addContent(heading);
-                addInlineComment(packageDoc, sectionTree);
-            } else {
-                packageContentTree.addContent(heading);
-                addInlineComment(packageDoc, packageContentTree);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageTags(Content packageContentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                ? sectionTree
-                : packageContentTree;
-        addTagsInfo(packageDoc, htmlTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageContent(Content contentTree, Content packageContentTree) {
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            packageContentTree.addContent(sectionTree);
-            mainTree.addContent(packageContentTree);
-            contentTree.addContent(mainTree);
-        } else {
-            contentTree.addContent(packageContentTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addPackageFooter(Content contentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
-                ? HtmlTree.FOOTER()
-                : contentTree;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
-        if (configuration.allowTag(HtmlTag.FOOTER)) {
-            contentTree.addContent(htmlTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void printDocument(Content contentTree) throws IOException {
-        printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageDoc),
-                true, contentTree);
-    }
-
-    /**
-     * Get "Use" link for this package in the navigation bar.
-     *
-     * @return a content tree for the class use link
-     */
-    protected Content getNavLinkClassUse() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_USE,
-                useLabel, "", "");
-        Content li = HtmlTree.LI(useLink);
-        return li;
-    }
-
-    /**
-     * Get "PREV PACKAGE" link in the navigation bar.
-     *
-     * @return a content tree for the previous link
-     */
-    public Content getNavLinkPrevious() {
-        Content li;
-        if (prev == null) {
-            li = HtmlTree.LI(prevpackageLabel);
-        } else {
-            DocPath path = DocPath.relativePath(packageDoc, prev);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.profilePackageSummary(profileName)),
-                prevpackageLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "NEXT PACKAGE" link in the navigation bar.
-     *
-     * @return a content tree for the next link
-     */
-    public Content getNavLinkNext() {
-        Content li;
-        if (next == null) {
-            li = HtmlTree.LI(nextpackageLabel);
-        } else {
-            DocPath path = DocPath.relativePath(packageDoc, next);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.profilePackageSummary(profileName)),
-                nextpackageLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "Tree" link in the navigation bar. This will be link to the package
-     * tree file.
-     *
-     * @return a content tree for the tree link
-     */
-    protected Content getNavLinkTree() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_TREE,
-                treeLabel, "", "");
-        Content li = HtmlTree.LI(useLink);
-        return li;
-    }
-
-    /**
-     * Highlight "Package" in the navigation bar, as this is the package page.
-     *
-     * @return a content tree for the package link
-     */
-    protected Content getNavLinkPackage() {
-        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, packageLabel);
-        return li;
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java
deleted file mode 100644
index a86dfa1..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.formats.html;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.formats.html.markup.*;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Class to generate file for each profile contents in the right-hand
- * frame. This will list all the packages and Class Kinds in the profile. A click on any
- * class-kind will update the frame with the clicked class-kind page. A click on any
- * package will update the frame with the clicked profile package page.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfileWriterImpl extends HtmlDocletWriter
-    implements ProfileSummaryWriter {
-
-    /**
-     * The prev profile name in the alpha-order list.
-     */
-    protected Profile prevProfile;
-
-    /**
-     * The next profile name in the alpha-order list.
-     */
-    protected Profile nextProfile;
-
-    /**
-     * The profile being documented.
-     */
-    protected Profile profile;
-
-    /**
-     * The HTML tree for main tag.
-     */
-    protected HtmlTree mainTree = HtmlTree.MAIN();
-
-    /**
-     * Constructor to construct ProfileWriter object and to generate
-     * "profileName-summary.html" file.
-     *
-     * @param configuration the configuration of the doclet.
-     * @param profile       Profile under consideration.
-     * @param prevProfile   Previous profile in the sorted array.
-     * @param nextProfile   Next profile in the sorted array.
-     */
-    public ProfileWriterImpl(ConfigurationImpl configuration,
-            Profile profile, Profile prevProfile, Profile nextProfile)
-            throws IOException {
-        super(configuration, DocPaths.profileSummary(profile.name));
-        this.prevProfile = prevProfile;
-        this.nextProfile = nextProfile;
-        this.profile = profile;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getProfileHeader(String heading) {
-        String profileName = profile.name;
-        HtmlTree bodyTree = getBody(true, getWindowTitle(profileName));
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
-                ? HtmlTree.HEADER()
-                : bodyTree;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
-        if (configuration.allowTag(HtmlTag.HEADER)) {
-            bodyTree.addContent(htmlTree);
-        }
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
-        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
-                HtmlStyle.title, profileLabel);
-        tHeading.addContent(getSpace());
-        Content profileHead = new RawHtml(heading);
-        tHeading.addContent(profileHead);
-        div.addContent(tHeading);
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(div);
-        } else {
-            bodyTree.addContent(div);
-        }
-        return bodyTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getContentHeader() {
-        HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
-        return div;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryHeader() {
-        HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
-        return li;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getSummaryTree(Content summaryContentTree) {
-        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
-        HtmlTree div = HtmlTree.DIV(HtmlStyle.summary, ul);
-        return div;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageSummaryHeader(PackageDoc pkg) {
-        Content pkgName = new StringContent(pkg.name());
-        Content pkgNameLink = getTargetProfilePackageLink(pkg,
-                    "classFrame", pkgName, profile.name);
-        Content heading = HtmlTree.HEADING(HtmlTag.H3, pkgNameLink);
-        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
-                ? HtmlTree.SECTION(heading)
-                : HtmlTree.LI(HtmlStyle.blockList, heading);
-        addPackageDeprecationInfo(htmlTree, pkg);
-        return htmlTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getPackageSummaryTree(Content packageSummaryContentTree) {
-        HtmlTree htmlTree;
-        if (configuration.allowTag(HtmlTag.SECTION)) {
-            htmlTree = HtmlTree.UL(HtmlStyle.blockList,
-                    HtmlTree.LI(HtmlStyle.blockList, packageSummaryContentTree));
-        } else {
-            htmlTree = HtmlTree.UL(HtmlStyle.blockList, packageSummaryContentTree);
-        }
-        return htmlTree;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree) {
-        addClassesSummary(classes, label, tableSummary, tableHeader,
-                packageSummaryContentTree, profile.value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addProfileContent(Content contentTree, Content profileContentTree) {
-        if (configuration.allowTag(HtmlTag.MAIN)) {
-            mainTree.addContent(profileContentTree);
-            contentTree.addContent(mainTree);
-        } else {
-            contentTree.addContent(profileContentTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addProfileFooter(Content contentTree) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
-                ? HtmlTree.FOOTER()
-                : contentTree;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
-        if (configuration.allowTag(HtmlTag.FOOTER)) {
-            contentTree.addContent(htmlTree);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void printDocument(Content contentTree) throws IOException {
-        printHtmlDocument(configuration.metakeywords.getMetaKeywords(profile),
-                true, contentTree);
-    }
-
-    /**
-     * Add the profile package deprecation information to the documentation tree.
-     *
-     * @param li the content tree to which the deprecation information will be added
-     * @param pkg the PackageDoc that is added
-     */
-    public void addPackageDeprecationInfo(Content li, PackageDoc pkg) {
-        Tag[] deprs;
-        if (utils.isDeprecated(pkg)) {
-            deprs = pkg.tags("deprecated");
-            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecatedContent);
-            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
-            deprDiv.addContent(deprPhrase);
-            if (deprs.length > 0) {
-                Tag[] commentTags = deprs[0].inlineTags();
-                if (commentTags.length > 0) {
-                    addInlineDeprecatedComment(pkg, deprs[0], deprDiv);
-                }
-            }
-            li.addContent(deprDiv);
-        }
-    }
-
-    /**
-     * Get "PREV PROFILE" link in the navigation bar.
-     *
-     * @return a content tree for the previous link
-     */
-    public Content getNavLinkPrevious() {
-        Content li;
-        if (prevProfile == null) {
-            li = HtmlTree.LI(prevprofileLabel);
-        } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.profileSummary(
-                    prevProfile.name)), prevprofileLabel, "", ""));
-        }
-        return li;
-    }
-
-    /**
-     * Get "NEXT PROFILE" link in the navigation bar.
-     *
-     * @return a content tree for the next link
-     */
-    public Content getNavLinkNext() {
-        Content li;
-        if (nextProfile == null) {
-            li = HtmlTree.LI(nextprofileLabel);
-        } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.profileSummary(
-                    nextProfile.name)), nextprofileLabel, "", ""));
-        }
-        return li;
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
index 70bace9..f2401ac 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 import java.io.IOException;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
@@ -70,24 +69,6 @@
     /**
      * {@inheritDoc}
      */
-    public ProfileSummaryWriter getProfileSummaryWriter(Profile profile,
-        Profile prevProfile, Profile nextProfile) throws Exception {
-        return new ProfileWriterImpl(configuration, profile,
-            prevProfile, nextProfile);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public ProfilePackageSummaryWriter getProfilePackageSummaryWriter(PackageDoc packageDoc,
-        PackageDoc prevPkg, PackageDoc nextPkg, Profile profile) throws Exception {
-        return new ProfilePackageWriterImpl(configuration, packageDoc,
-            prevPkg, nextPkg, profile);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public ClassWriter getClassWriter(ClassDoc classDoc, ClassDoc prevClass,
             ClassDoc nextClass, ClassTree classTree) throws IOException {
         return new ClassWriterImpl(configuration, classDoc,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
index aa18de7..e5addad 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, 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
@@ -192,11 +192,6 @@
     public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2;
 
     /**
-     * Html tag for the profile name heading.
-     */
-    public static final HtmlTag PROFILE_HEADING = HtmlTag.H2;
-
-    /**
      * Html tag for the member summary heading.
      */
     public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java
index 75f291b..0d472eb 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.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
@@ -81,9 +81,11 @@
     navBarCell1Rev,
     navList,
     navListSearch,
+    navPadding,
     overrideSpecifyLabel,
     overviewSummary,
     packageHierarchyLabel,
+    packageLabelInClass,
     paramLabel,
     returnLabel,
     rightContainer,
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
index 2107273..19940dc 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
@@ -27,8 +27,6 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -65,11 +63,6 @@
     protected boolean memberDetailsListPrinted;
 
     /**
-     * Header for table displaying profiles and description..
-     */
-    protected final String[] profileTableHeader;
-
-    /**
      * Header for tables displaying packages and description..
      */
     protected final String[] packageTableHeader;
@@ -90,8 +83,6 @@
 
     public final Content packageLabel;
 
-    public final Content profileLabel;
-
     public final Content useLabel;
 
     public final Content prevLabel;
@@ -122,8 +113,6 @@
 
     public final Content allpackagesLabel;
 
-    public final Content allprofilesLabel;
-
     public final Content indexLabel;
 
     public final Content helpLabel;
@@ -136,14 +125,8 @@
 
     public final Content nextpackageLabel;
 
-    public final Content prevprofileLabel;
-
-    public final Content nextprofileLabel;
-
     public final Content packagesLabel;
 
-    public final Content profilesLabel;
-
     public final Content methodDetailsLabel;
 
     public final Content annotationTypeDetailsLabel;
@@ -183,10 +166,6 @@
         writer = DocFile.createFileForOutput(configuration, path).openWriter();
         this.configuration = configuration;
         this.memberDetailsListPrinted = false;
-        profileTableHeader = new String[] {
-            configuration.getText("doclet.Profile"),
-            configuration.getText("doclet.Description")
-        };
         packageTableHeader = new String[] {
             configuration.getText("doclet.Package"),
             configuration.getText("doclet.Description")
@@ -199,7 +178,6 @@
         overviewLabel = getResource("doclet.Overview");
         defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME);
         packageLabel = getResource("doclet.Package");
-        profileLabel = getResource("doclet.Profile");
         useLabel = getResource("doclet.navClassUse");
         prevLabel = getResource("doclet.Prev");
         nextLabel = getResource("doclet.Next");
@@ -215,17 +193,13 @@
         deprecatedPhrase = getResource("doclet.Deprecated");
         allclassesLabel = getNonBreakResource("doclet.All_Classes");
         allpackagesLabel = getNonBreakResource("doclet.All_Packages");
-        allprofilesLabel = getNonBreakResource("doclet.All_Profiles");
         indexLabel = getResource("doclet.Index");
         helpLabel = getResource("doclet.Help");
         seeLabel = getResource("doclet.See");
         descriptionLabel = getResource("doclet.Description");
         prevpackageLabel = getNonBreakResource("doclet.Prev_Package");
         nextpackageLabel = getNonBreakResource("doclet.Next_Package");
-        prevprofileLabel = getNonBreakResource("doclet.Prev_Profile");
-        nextprofileLabel = getNonBreakResource("doclet.Next_Profile");
         packagesLabel = getResource("doclet.Packages");
-        profilesLabel = getResource("doclet.Profiles");
         methodDetailsLabel = getResource("doclet.Method_Detail");
         annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail");
         fieldDetailsLabel = getResource("doclet.Field_Detail");
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
index e5cadd9..0efe7ee 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties
@@ -4,9 +4,7 @@
 doclet.Window_Overview=Overview List
 doclet.Window_Overview_Summary=Overview
 doclet.Package=Package
-doclet.Profile=Profile
 doclet.All_Packages=All Packages
-doclet.All_Profiles=All Profiles
 doclet.Tree=Tree
 doclet.Class_Hierarchy=Class Hierarchy
 doclet.Window_Class_Hierarchy=Class Hierarchy
@@ -19,8 +17,6 @@
 doclet.Next_Class=Next Class
 doclet.Prev_Package=Prev Package
 doclet.Next_Package=Next Package
-doclet.Prev_Profile=Prev Profile
-doclet.Next_Profile=Next Profile
 doclet.Prev_Letter=Prev Letter
 doclet.Next_Letter=Next Letter
 doclet.Href_Class_Title=class in {0}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
index ce4f620..e4d62a1 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -25,6 +25,8 @@
 
 package com.sun.tools.doclets.internal.toolkit;
 
+import javax.tools.StandardLocation;
+
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.builders.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
@@ -88,6 +90,7 @@
             root.printError(f.getMessage());
             return false;
         } catch (DocletAbortException e) {
+            e.printStackTrace();
             Throwable cause = e.getCause();
             if (cause != null) {
                 if (cause.getLocalizedMessage() != null) {
@@ -138,11 +141,10 @@
         ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
 
         generateClassFiles(root, classtree);
-        configuration.utils.copyDocFiles(configuration, DocPaths.DOC_FILES);
+        configuration.utils.copyDocFiles(configuration, StandardLocation.SOURCE_PATH, DocPaths.DOC_FILES);
 
         PackageListWriter.generate(configuration);
         generatePackageFiles(classtree);
-        generateProfileFiles();
 
         generateOtherFiles(root, classtree);
         configuration.tagletManager.printReport();
@@ -163,12 +165,6 @@
     }
 
     /**
-     * Generate the profile documentation.
-     *
-     */
-    protected abstract void generateProfileFiles() throws Exception;
-
-    /**
      * Generate the package documentation.
      *
      * @param classtree the data structure representing the class tree.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
index 85dcb07..f86f874 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
@@ -31,14 +31,12 @@
 import java.util.regex.Pattern;
 
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.sym.Profiles;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
-import com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.GetterSetter;
 import com.sun.tools.javac.util.StringUtils;
 
 /**
@@ -212,16 +210,6 @@
      * used.Default is don't show version information.
      */
     public boolean showversion = false;
-    /**
-     * Argument for command line option "-Xprofilespath".
-     */
-    public String profilespath = "";
-
-    /**
-     * Generate profiles documentation if profilespath is set and valid profiles
-     * are present.
-     */
-    public boolean showProfiles = false;
 
     /**
      * Don't generate deprecated API information at all, if -nodeprecated
@@ -283,28 +271,13 @@
     public abstract MessageRetriever getDocletSpecificMsg();
 
     /**
-     * A profiles object used to access profiles across various pages.
-     */
-    public Profiles profiles;
-
-    /**
-     * A map of the profiles to packages.
-     */
-    public Map<String, List<PackageDoc>> profilePackages;
-
-    /**
      * A sorted set of packages specified on the command-line merged with a
      * collection of packages that contain the classes specified on the
      * command-line.
      */
     public SortedSet<PackageDoc> packages;
 
-    // The following three fields provide caches for use by all instances of VisibleMemberMap.
-    public final Map<ClassDoc, ProgramElementDoc[]> propertiesCache = new HashMap<>();
-    public final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap = new HashMap<>();
-    public final Map<ProgramElementDoc, GetterSetter> getterSetterMap = new HashMap<>();
-
-    public DocFileFactory docFileFactory;
+    public boolean exportInternalAPI;
 
     /**
      * Constructor. Constructs the message retriever with resource file.
@@ -360,6 +333,7 @@
             case "-quiet":
             case "-xnodate":
             case "-version":
+            case "-xdaccessinternalapi":
                 return 1;
             case "-d":
             case "-docencoding":
@@ -373,7 +347,6 @@
             case "-tag":
             case "-taglet":
             case "-tagletpath":
-            case "-xprofilespath":
                 return 2;
             case "-group":
             case "-linkoffline":
@@ -392,54 +365,6 @@
     public abstract boolean validOptions(String options[][],
         DocErrorReporter reporter);
 
-    private void initProfiles() throws IOException {
-        if (profilespath.isEmpty())
-            return;
-
-        profiles = Profiles.read(new File(profilespath));
-
-        // Group the packages to be documented by the lowest profile (if any)
-        // in which each appears
-        Map<Profile, List<PackageDoc>> interimResults = new EnumMap<>(Profile.class);
-        for (Profile p: Profile.values())
-            interimResults.put(p, new ArrayList<PackageDoc>());
-
-        for (PackageDoc pkg: packages) {
-            if (nodeprecated && utils.isDeprecated(pkg)) {
-                continue;
-            }
-            // the getProfile method takes a type name, not a package name,
-            // but isn't particularly fussy about the simple name -- so just use *
-            int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*");
-            Profile p = Profile.lookup(i);
-            if (p != null) {
-                List<PackageDoc> pkgs = interimResults.get(p);
-                pkgs.add(pkg);
-            }
-        }
-
-        // Build the profilePackages structure used by the doclet
-        profilePackages = new HashMap<>();
-        List<PackageDoc> prev = Collections.<PackageDoc>emptyList();
-        int size;
-        for (Map.Entry<Profile,List<PackageDoc>> e: interimResults.entrySet()) {
-            Profile p = e.getKey();
-            List<PackageDoc> pkgs =  e.getValue();
-            pkgs.addAll(prev); // each profile contains all lower profiles
-            Collections.sort(pkgs);
-            size = pkgs.size();
-            // For a profile, if there are no packages to be documented, do not add
-            // it to profilePackages map.
-            if (size > 0)
-                profilePackages.put(p.name, pkgs);
-            prev = pkgs;
-        }
-
-        // Generate profiles documentation if any profile contains any
-        // of the packages to be documented.
-        showProfiles = !prev.isEmpty();
-    }
-
     private void initPackages() {
         packages = new TreeSet<>(Arrays.asList(root.specifiedPackages()));
         for (ClassDoc aClass : root.specifiedClasses()) {
@@ -512,8 +437,6 @@
                 customTagStrs.add(os);
             } else if (opt.equals("-tagletpath")) {
                 tagletpath = os[1];
-            }  else if (opt.equals("-xprofilespath")) {
-                profilespath = os[1];
             } else if (opt.equals("-keywords")) {
                 keywords = true;
             } else if (opt.equals("-serialwarn")) {
@@ -527,6 +450,8 @@
                 String url = os[1];
                 String pkglisturl = os[2];
                 extern.link(url, pkglisturl, root, true);
+            } else if (opt.equals("-xdaccessinternalapi")) {
+                exportInternalAPI = true;
             }
         }
         if (docencoding == null) {
@@ -545,11 +470,6 @@
     public void setOptions() throws Fault {
         initPackages();
         setOptions(root.options());
-        try {
-            initProfiles();
-        } catch (Exception e) {
-            throw new DocletAbortException(e);
-        }
         setSpecificDocletOptions(root.options());
     }
 
@@ -578,9 +498,9 @@
      * either -tag or -taglet arguments.
      */
     private void initTagletManager(Set<String[]> customTagStrs) {
-        tagletManager = tagletManager == null ?
-            new TagletManager(nosince, showversion, showauthor, javafx, message) :
-            tagletManager;
+        tagletManager = (tagletManager == null)
+                ? new TagletManager(nosince, showversion, showauthor, javafx, exportInternalAPI, message)
+                : tagletManager;
         for (String[] args : customTagStrs) {
             if (args[0].equals("-taglet")) {
                 tagletManager.addCustomTag(args[1], getFileManager(), tagletpath);
@@ -719,17 +639,6 @@
     }
 
     /**
-     * Check the validity of the given profile. Return false if there are no
-     * valid packages to be documented for the profile.
-     *
-     * @param profileName the profile that needs to be validated.
-     * @return true if the profile has valid packages to be documented.
-     */
-    public boolean shouldDocumentProfile(String profileName) {
-        return profilePackages.containsKey(profileName);
-    }
-
-    /**
      * Check the validity of the given Source or Output File encoding on this
      * platform.
      *
@@ -977,4 +886,6 @@
     }
 
     public abstract boolean showMessage(SourcePosition pos, String key);
+
+    public abstract Location getLocationForPackage(PackageDoc pd);
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java
deleted file mode 100644
index 5433552..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.internal.toolkit;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-
-/**
- * The interface for writing profile package summary output.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-
-public interface ProfilePackageSummaryWriter {
-
-    /**
-     * Get the header for the summary.
-     *
-     * @param heading Package name.
-     * @return the header to be added to the content tree
-     */
-    public abstract Content getPackageHeader(String heading);
-
-    /**
-     * Get the header for the content.
-     *
-     * @return a content tree for the content header
-     */
-    public abstract Content getContentHeader();
-
-    /**
-     * Get the header for the package summary.
-     *
-     * @return a content tree with the package summary header
-     */
-    public abstract Content getSummaryHeader();
-
-    /**
-     * Adds the table of classes to the documentation tree.
-     *
-     * @param classes the array of classes to document.
-     * @param label the label for this table.
-     * @param tableSummary the summary string for the table
-     * @param tableHeader array of table headers
-     * @param summaryContentTree the content tree to which the summaries will be added
-     */
-    public abstract void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content summaryContentTree);
-
-    /**
-     * Adds the package description from the "packages.html" file to the documentation
-     * tree.
-     *
-     * @param packageContentTree the content tree to which the package description
-     *                           will be added
-     */
-    public abstract void addPackageDescription(Content packageContentTree);
-
-    /**
-     * Adds the tag information from the "packages.html" file to the documentation
-     * tree.
-     *
-     * @param packageContentTree the content tree to which the package tags will
-     *                           be added
-     */
-    public abstract void addPackageTags(Content packageContentTree);
-
-    /**
-     * Adds the tag information from the "packages.html" or "package-info.java" file to the
-     * documentation tree.
-     *
-     * @param contentTree the content tree to which the package content tree will be added
-     * @param packageContentTree the package content tree to be added
-     */
-    public abstract void addPackageContent(Content contentTree, Content packageContentTree);
-
-    /**
-     * Adds the footer to the documentation tree.
-     *
-     * @param contentTree the tree to which the footer will be added
-     */
-    public abstract void addPackageFooter(Content contentTree);
-
-    /**
-     * Print the package summary document.
-     *
-     * @param contentTree the content tree that will be printed
-     */
-    public abstract void printDocument(Content contentTree) throws IOException;
-
-    /**
-     * Close the writer.
-     */
-    public abstract void close() throws IOException;
-
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java
deleted file mode 100644
index 5008daf..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.internal.toolkit;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-
-/**
- * The interface for writing profile summary output.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-
-public interface ProfileSummaryWriter {
-
-    /**
-     * Get the header for the summary.
-     *
-     * @param heading profile name.
-     * @return the header to be added to the content tree
-     */
-    public abstract Content getProfileHeader(String heading);
-
-    /**
-     * Get the header for the profile content.
-     *
-     * @return a content tree for the profile content header
-     */
-    public abstract Content getContentHeader();
-
-    /**
-     * Get the header for the summary header.
-     *
-     * @return a content tree with the summary header
-     */
-    public abstract Content getSummaryHeader();
-
-    /**
-     * Get the header for the summary tree.
-     *
-     * @param summaryContentTree the content tree.
-     * @return a content tree with the summary tree
-     */
-    public abstract Content getSummaryTree(Content summaryContentTree);
-
-    /**
-     * Get the header for the package summary header.
-     *
-     * @return a content tree with the package summary header
-     */
-    public abstract Content getPackageSummaryHeader(PackageDoc pkg);
-
-    /**
-     * Get the header for the package summary tree.
-     *
-     * @return a content tree with the package summary
-     */
-    public abstract Content getPackageSummaryTree(Content packageSummaryContentTree);
-
-    /**
-     * Adds the table of classes to the documentation tree.
-     *
-     * @param classes the array of classes to document.
-     * @param label the label for this table.
-     * @param tableSummary the summary string for the table
-     * @param tableHeader array of table headers
-     * @param packageSummaryContentTree the content tree to which the summaries will be added
-     */
-    public abstract void addClassesSummary(ClassDoc[] classes, String label,
-            String tableSummary, String[] tableHeader, Content packageSummaryContentTree);
-
-    /**
-     * Adds the profile content tree to the documentation tree.
-     *
-     * @param contentTree the tree to which the profile content tree will be added
-     * @param profileContentTree the content tree that will be added
-     */
-    public abstract void addProfileContent(Content contentTree, Content profileContentTree);
-
-    /**
-     * Adds the footer to the documentation tree.
-     *
-     * @param contentTree the tree to which the footer will be added
-     */
-    public abstract void addProfileFooter(Content contentTree);
-
-    /**
-     * Print the profile summary document.
-     *
-     * @param contentTree the content tree that will be printed
-     */
-    public abstract void printDocument(Content contentTree) throws IOException;
-
-    /**
-     * Close the writer.
-     */
-    public abstract void close() throws IOException;
-
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
index 985fb64..865049f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 package com.sun.tools.doclets.internal.toolkit;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
 /**
@@ -66,33 +65,6 @@
     throws Exception;
 
     /**
-     * Return the writer for the profile summary.
-     *
-     * @param profile the profile being documented.
-     * @param prevProfile the previous profile that was documented.
-     * @param nextProfile the next profile being documented.
-     * @return the writer for the profile summary.  Return null if this
-     * writer is not supported by the doclet.
-     */
-    public abstract ProfileSummaryWriter getProfileSummaryWriter(Profile
-        profile, Profile prevProfile, Profile nextProfile)
-    throws Exception;
-
-    /**
-     * Return the writer for the profile package summary.
-     *
-     * @param packageDoc the profile package being documented.
-     * @param prevPkg the previous profile package that was documented.
-     * @param nextPkg the next profile package being documented.
-     * @param profile the profile being documented.
-     * @return the writer for the profile package summary.  Return null if this
-     * writer is not supported by the doclet.
-     */
-    public abstract ProfilePackageSummaryWriter getProfilePackageSummaryWriter(
-            PackageDoc packageDoc, PackageDoc prevPkg, PackageDoc nextPkg,
-            Profile profile) throws Exception;
-
-    /**
      * Return the writer for a class.
      *
      * @param classDoc the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
index d6c7ba9..a95e081 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -123,7 +123,7 @@
     /**
      * Build the documentation.
      *
-     * @throws IOException there was a problem writing the output.
+     * @throws IOException if there was a problem writing the output.
      */
     public abstract void build() throws IOException;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
index 75181a4..972fc9e 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.util.Set;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
@@ -97,36 +96,6 @@
     }
 
     /**
-     * Return the builder that builds the profile summary.
-     *
-     * @param profile the profile being documented.
-     * @param prevProfile the previous profile being documented.
-     * @param nextProfile the next profile being documented.
-     * @return the builder that builds the profile summary.
-     */
-    public AbstractBuilder getProfileSummaryBuilder(Profile profile, Profile prevProfile,
-            Profile nextProfile) throws Exception {
-        return ProfileSummaryBuilder.getInstance(context, profile,
-            writerFactory.getProfileSummaryWriter(profile, prevProfile, nextProfile));
-    }
-
-    /**
-     * Return the builder that builds the profile package summary.
-     *
-     * @param pkg the profile package being documented.
-     * @param prevPkg the previous profile package being documented.
-     * @param nextPkg the next profile package being documented.
-     * @param profile the profile being documented.
-     * @return the builder that builds the profile package summary.
-     */
-    public AbstractBuilder getProfilePackageSummaryBuilder(PackageDoc pkg, PackageDoc prevPkg,
-            PackageDoc nextPkg, Profile profile) throws Exception {
-        return ProfilePackageSummaryBuilder.getInstance(context, pkg,
-            writerFactory.getProfilePackageSummaryWriter(pkg, prevPkg, nextPkg,
-                profile), profile);
-    }
-
-    /**
      * Return the builder for the class.
      *
      * @param classDoc the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java
deleted file mode 100644
index afc0b2c..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfilePackageSummaryBuilder.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.internal.toolkit.builders;
-
-import java.io.*;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.internal.toolkit.*;
-
-/**
- * Builds the summary for a given profile package.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfilePackageSummaryBuilder extends AbstractBuilder {
-    /**
-     * The root element of the profile package summary XML is {@value}.
-     */
-    public static final String ROOT = "PackageDoc";
-
-    /**
-     * The profile package being documented.
-     */
-    private final PackageDoc packageDoc;
-
-    /**
-     * The name of the profile being documented.
-     */
-    private final String profileName;
-
-    /**
-     * The value of the profile being documented.
-     */
-    private final int profileValue;
-
-    /**
-     * The doclet specific writer that will output the result.
-     */
-    private final ProfilePackageSummaryWriter profilePackageWriter;
-
-    /**
-     * The content that will be added to the profile package summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
-     * Construct a new ProfilePackageSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param pkg the profile package being documented.
-     * @param profilePackageWriter the doclet specific writer that will output the
-     *        result.
-     * @param profile the profile being documented.
-     */
-    private ProfilePackageSummaryBuilder(Context context,
-            PackageDoc pkg, ProfilePackageSummaryWriter profilePackageWriter,
-            Profile profile) {
-        super(context);
-        this.packageDoc = pkg;
-        this.profilePackageWriter = profilePackageWriter;
-        this.profileName = profile.name;
-        this.profileValue = profile.value;
-    }
-
-    /**
-     * Construct a new ProfilePackageSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param pkg the profile package being documented.
-     * @param profilePackageWriter the doclet specific writer that will output the
-     *        result.
-     * @param profile the profile being documented.
-     *
-     * @return an instance of a ProfilePackageSummaryBuilder.
-     */
-    public static ProfilePackageSummaryBuilder getInstance(Context context,
-            PackageDoc pkg, ProfilePackageSummaryWriter profilePackageWriter,
-            Profile profile) {
-        return new ProfilePackageSummaryBuilder(context, pkg, profilePackageWriter,
-                profile);
-    }
-
-    /**
-     * Build the profile package summary.
-     */
-    public void build() throws IOException {
-        if (profilePackageWriter == null) {
-            //Doclet does not support this output.
-            return;
-        }
-        build(layoutParser.parseXML(ROOT), contentTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return ROOT;
-    }
-
-    /**
-     * Build the profile package documentation.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the documentation will be added
-     */
-    public void buildPackageDoc(XMLNode node, Content contentTree) throws Exception {
-        contentTree = profilePackageWriter.getPackageHeader(
-                utils.getPackageName(packageDoc));
-        buildChildren(node, contentTree);
-        profilePackageWriter.addPackageFooter(contentTree);
-        profilePackageWriter.printDocument(contentTree);
-        profilePackageWriter.close();
-        utils.copyDocFiles(configuration, packageDoc);
-    }
-
-    /**
-     * Build the content for the profile package doc.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the package contents
-     *                    will be added
-     */
-    public void buildContent(XMLNode node, Content contentTree) {
-        Content packageContentTree = profilePackageWriter.getContentHeader();
-        buildChildren(node, packageContentTree);
-        profilePackageWriter.addPackageContent(contentTree, packageContentTree);
-    }
-
-    /**
-     * Build the profile package summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the package content tree to which the summaries will
-     *                           be added
-     */
-    public void buildSummary(XMLNode node, Content packageContentTree) {
-        Content summaryContentTree = profilePackageWriter.getSummaryHeader();
-        buildChildren(node, summaryContentTree);
-        packageContentTree.addContent(summaryContentTree);
-    }
-
-    /**
-     * Build the summary for the interfaces in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the interface summary
-     *                           will be added
-     */
-    public void buildInterfaceSummary(XMLNode node, Content summaryContentTree) {
-        String interfaceTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Interface_Summary"),
-                configuration.getText("doclet.interfaces"));
-        String[] interfaceTableHeader = new String[] {
-            configuration.getText("doclet.Interface"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] interfaces =
-                packageDoc.isIncluded()
-                        ? packageDoc.interfaces()
-                        : configuration.classDocCatalog.interfaces(
-                                utils.getPackageName(packageDoc));
-        if (interfaces.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    interfaces,
-                    configuration.getText("doclet.Interface_Summary"),
-                    interfaceTableSummary, interfaceTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the classes in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the class summary will
-     *                           be added
-     */
-    public void buildClassSummary(XMLNode node, Content summaryContentTree) {
-        String classTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Class_Summary"),
-                configuration.getText("doclet.classes"));
-        String[] classTableHeader = new String[] {
-            configuration.getText("doclet.Class"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] classes =
-                packageDoc.isIncluded()
-                        ? packageDoc.ordinaryClasses()
-                        : configuration.classDocCatalog.ordinaryClasses(
-                                utils.getPackageName(packageDoc));
-        if (classes.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    classes,
-                    configuration.getText("doclet.Class_Summary"),
-                    classTableSummary, classTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the enums in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the enum summary will
-     *                           be added
-     */
-    public void buildEnumSummary(XMLNode node, Content summaryContentTree) {
-        String enumTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Enum_Summary"),
-                configuration.getText("doclet.enums"));
-        String[] enumTableHeader = new String[] {
-            configuration.getText("doclet.Enum"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] enums =
-                packageDoc.isIncluded()
-                        ? packageDoc.enums()
-                        : configuration.classDocCatalog.enums(
-                                utils.getPackageName(packageDoc));
-        if (enums.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    enums,
-                    configuration.getText("doclet.Enum_Summary"),
-                    enumTableSummary, enumTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the exceptions in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the exception summary will
-     *                           be added
-     */
-    public void buildExceptionSummary(XMLNode node, Content summaryContentTree) {
-        String exceptionTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Exception_Summary"),
-                configuration.getText("doclet.exceptions"));
-        String[] exceptionTableHeader = new String[] {
-            configuration.getText("doclet.Exception"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] exceptions =
-                packageDoc.isIncluded()
-                        ? packageDoc.exceptions()
-                        : configuration.classDocCatalog.exceptions(
-                                utils.getPackageName(packageDoc));
-        if (exceptions.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    exceptions,
-                    configuration.getText("doclet.Exception_Summary"),
-                    exceptionTableSummary, exceptionTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the errors in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the error summary will
-     *                           be added
-     */
-    public void buildErrorSummary(XMLNode node, Content summaryContentTree) {
-        String errorTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Error_Summary"),
-                configuration.getText("doclet.errors"));
-        String[] errorTableHeader = new String[] {
-            configuration.getText("doclet.Error"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] errors =
-                packageDoc.isIncluded()
-                        ? packageDoc.errors()
-                        : configuration.classDocCatalog.errors(
-                                utils.getPackageName(packageDoc));
-        if (errors.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    errors,
-                    configuration.getText("doclet.Error_Summary"),
-                    errorTableSummary, errorTableHeader, summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the annotation type in this package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the summary tree to which the annotation type
-     *                           summary will be added
-     */
-    public void buildAnnotationTypeSummary(XMLNode node, Content summaryContentTree) {
-        String annotationtypeTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Types_Summary"),
-                configuration.getText("doclet.annotationtypes"));
-        String[] annotationtypeTableHeader = new String[] {
-            configuration.getText("doclet.AnnotationType"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] annotationTypes =
-                packageDoc.isIncluded()
-                        ? packageDoc.annotationTypes()
-                        : configuration.classDocCatalog.annotationTypes(
-                                utils.getPackageName(packageDoc));
-        if (annotationTypes.length > 0) {
-            profilePackageWriter.addClassesSummary(
-                    annotationTypes,
-                    configuration.getText("doclet.Annotation_Types_Summary"),
-                    annotationtypeTableSummary, annotationtypeTableHeader,
-                    summaryContentTree);
-        }
-    }
-
-    /**
-     * Build the description of the summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the tree to which the package description will
-     *                           be added
-     */
-    public void buildPackageDescription(XMLNode node, Content packageContentTree) {
-        if (configuration.nocomment) {
-            return;
-        }
-        profilePackageWriter.addPackageDescription(packageContentTree);
-    }
-
-    /**
-     * Build the tags of the summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageContentTree the tree to which the package tags will be added
-     */
-    public void buildPackageTags(XMLNode node, Content packageContentTree) {
-        if (configuration.nocomment) {
-            return;
-        }
-        profilePackageWriter.addPackageTags(packageContentTree);
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java
deleted file mode 100644
index 91faf6f..0000000
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/ProfileSummaryBuilder.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.doclets.internal.toolkit.builders;
-
-import java.io.IOException;
-import java.util.List;
-
-import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
-import com.sun.tools.doclets.internal.toolkit.*;
-import com.sun.tools.doclets.internal.toolkit.util.*;
-
-/**
- * Builds the summary for a given profile.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class ProfileSummaryBuilder extends AbstractBuilder {
-    /**
-     * The root element of the profile summary XML is {@value}.
-     */
-    public static final String ROOT = "ProfileDoc";
-
-    /**
-     * The profile being documented.
-     */
-    private final Profile profile;
-
-    /**
-     * The doclet specific writer that will output the result.
-     */
-    private final ProfileSummaryWriter profileWriter;
-
-    /**
-     * The content that will be added to the profile summary documentation tree.
-     */
-    private Content contentTree;
-
-    /**
-     * The profile package being documented.
-     */
-    private PackageDoc pkg;
-
-    /**
-     * Construct a new ProfileSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param profile the profile being documented.
-     * @param profileWriter the doclet specific writer that will output the
-     *        result.
-     */
-    private ProfileSummaryBuilder(Context context,
-            Profile profile, ProfileSummaryWriter profileWriter) {
-        super(context);
-        this.profile = profile;
-        this.profileWriter = profileWriter;
-    }
-
-    /**
-     * Construct a new ProfileSummaryBuilder.
-     *
-     * @param context  the build context.
-     * @param profile the profile being documented.
-     * @param profileWriter the doclet specific writer that will output the
-     *        result.
-     *
-     * @return an instance of a ProfileSummaryBuilder.
-     */
-    public static ProfileSummaryBuilder getInstance(Context context,
-            Profile profile, ProfileSummaryWriter profileWriter) {
-        return new ProfileSummaryBuilder(context, profile, profileWriter);
-    }
-
-    /**
-     * Build the profile summary.
-     */
-    public void build() throws IOException {
-        if (profileWriter == null) {
-            //Doclet does not support this output.
-            return;
-        }
-        build(layoutParser.parseXML(ROOT), contentTree);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getName() {
-        return ROOT;
-    }
-
-    /**
-     * Build the profile documentation.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the documentation will be added
-     */
-    public void buildProfileDoc(XMLNode node, Content contentTree) throws Exception {
-        contentTree = profileWriter.getProfileHeader(profile.name);
-        buildChildren(node, contentTree);
-        profileWriter.addProfileFooter(contentTree);
-        profileWriter.printDocument(contentTree);
-        profileWriter.close();
-        utils.copyDocFiles(configuration, DocPaths.profileSummary(profile.name));
-    }
-
-    /**
-     * Build the content for the profile doc.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param contentTree the content tree to which the profile contents
-     *                    will be added
-     */
-    public void buildContent(XMLNode node, Content contentTree) {
-        Content profileContentTree = profileWriter.getContentHeader();
-        buildChildren(node, profileContentTree);
-        profileWriter.addProfileContent(contentTree, profileContentTree);
-    }
-
-    /**
-     * Build the profile summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param profileContentTree the profile content tree to which the summaries will
-     *                           be added
-     */
-    public void buildSummary(XMLNode node, Content profileContentTree) {
-        Content summaryContentTree = profileWriter.getSummaryHeader();
-        buildChildren(node, summaryContentTree);
-        profileContentTree.addContent(profileWriter.getSummaryTree(summaryContentTree));
-    }
-
-    /**
-     * Build the profile package summary.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param summaryContentTree the content tree to which the summaries will
-     *                           be added
-     */
-    public void buildPackageSummary(XMLNode node, Content summaryContentTree) {
-        List<PackageDoc> packages = configuration.profilePackages.get(profile.name);
-        for (PackageDoc aPackage : packages) {
-            this.pkg = aPackage;
-            Content packageSummaryContentTree = profileWriter.getPackageSummaryHeader(this.pkg);
-            buildChildren(node, packageSummaryContentTree);
-            summaryContentTree.addContent(profileWriter.getPackageSummaryTree(
-                    packageSummaryContentTree));
-        }
-    }
-
-    /**
-     * Build the summary for the interfaces in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the interface summary
-     *                           will be added
-     */
-    public void buildInterfaceSummary(XMLNode node, Content packageSummaryContentTree) {
-        String interfaceTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Interface_Summary"),
-                configuration.getText("doclet.interfaces"));
-        String[] interfaceTableHeader = new String[] {
-            configuration.getText("doclet.Interface"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] interfaces = pkg.interfaces();
-        if (interfaces.length > 0) {
-            profileWriter.addClassesSummary(
-                    interfaces,
-                    configuration.getText("doclet.Interface_Summary"),
-                    interfaceTableSummary, interfaceTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the classes in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the class summary will
-     *                           be added
-     */
-    public void buildClassSummary(XMLNode node, Content packageSummaryContentTree) {
-        String classTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Class_Summary"),
-                configuration.getText("doclet.classes"));
-        String[] classTableHeader = new String[] {
-            configuration.getText("doclet.Class"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] classes = pkg.ordinaryClasses();
-        if (classes.length > 0) {
-            profileWriter.addClassesSummary(
-                    classes,
-                    configuration.getText("doclet.Class_Summary"),
-                    classTableSummary, classTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the enums in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the enum summary will
-     *                           be added
-     */
-    public void buildEnumSummary(XMLNode node, Content packageSummaryContentTree) {
-        String enumTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Enum_Summary"),
-                configuration.getText("doclet.enums"));
-        String[] enumTableHeader = new String[] {
-            configuration.getText("doclet.Enum"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] enums = pkg.enums();
-        if (enums.length > 0) {
-            profileWriter.addClassesSummary(
-                    enums,
-                    configuration.getText("doclet.Enum_Summary"),
-                    enumTableSummary, enumTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the exceptions in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the exception summary will
-     *                           be added
-     */
-    public void buildExceptionSummary(XMLNode node, Content packageSummaryContentTree) {
-        String exceptionTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Exception_Summary"),
-                configuration.getText("doclet.exceptions"));
-        String[] exceptionTableHeader = new String[] {
-            configuration.getText("doclet.Exception"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] exceptions = pkg.exceptions();
-        if (exceptions.length > 0) {
-            profileWriter.addClassesSummary(
-                    exceptions,
-                    configuration.getText("doclet.Exception_Summary"),
-                    exceptionTableSummary, exceptionTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the errors in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the error summary will
-     *                           be added
-     */
-    public void buildErrorSummary(XMLNode node, Content packageSummaryContentTree) {
-        String errorTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Error_Summary"),
-                configuration.getText("doclet.errors"));
-        String[] errorTableHeader = new String[] {
-            configuration.getText("doclet.Error"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] errors = pkg.errors();
-        if (errors.length > 0) {
-            profileWriter.addClassesSummary(
-                    errors,
-                    configuration.getText("doclet.Error_Summary"),
-                    errorTableSummary, errorTableHeader, packageSummaryContentTree);
-        }
-    }
-
-    /**
-     * Build the summary for the annotation type in the package.
-     *
-     * @param node the XML element that specifies which components to document
-     * @param packageSummaryContentTree the tree to which the annotation type
-     *                           summary will be added
-     */
-    public void buildAnnotationTypeSummary(XMLNode node, Content packageSummaryContentTree) {
-        String annotationtypeTableSummary =
-                configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Types_Summary"),
-                configuration.getText("doclet.annotationtypes"));
-        String[] annotationtypeTableHeader = new String[] {
-            configuration.getText("doclet.AnnotationType"),
-            configuration.getText("doclet.Description")
-        };
-        ClassDoc[] annotationTypes = pkg.annotationTypes();
-        if (annotationTypes.length > 0) {
-            profileWriter.addClassesSummary(
-                    annotationTypes,
-                    configuration.getText("doclet.Annotation_Types_Summary"),
-                    annotationtypeTableSummary, annotationtypeTableHeader,
-                    packageSummaryContentTree);
-        }
-    }
-}
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
index f7f2f9c..3cbe582 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='utf-8'?>
 
 <!--
- Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -28,21 +28,6 @@
 
 <Doclet>
 
-    <ProfileDoc>
-        <Content>
-            <Summary>
-                <PackageSummary>
-                    <InterfaceSummary/>
-                    <ClassSummary/>
-                    <EnumSummary/>
-                    <ExceptionSummary/>
-                    <ErrorSummary/>
-                    <AnnotationTypeSummary/>
-                </PackageSummary>
-            </Summary>
-        </Content>
-    </ProfileDoc>
-
     <PackageDoc>
         <Content>
             <Summary>
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
index f6e10be..84e44b3 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
@@ -31,7 +31,6 @@
 doclet.Building_Index_For_All_Classes=Building index for all classes...
 doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
 doclet.Packages=Packages
-doclet.Profiles=Profiles
 doclet.Other_Packages=Other Packages
 doclet.Notice_taglet_registered=Registered Taglet {0} ...
 doclet.Notice_taglet_unseen=Note: Custom tags that were not seen: {0}
@@ -69,7 +68,6 @@
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
 doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
-doclet.Profile_Summary=Profile Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
 doclet.Enum_Summary=Enum Summary
@@ -92,7 +90,6 @@
 doclet.Classes=Classes
 doclet.Packages=Packages
 doclet.packages=packages
-doclet.profiles=profiles
 doclet.All_Classes=All Classes
 doclet.All_Superinterfaces=All Superinterfaces:
 doclet.All_Implemented_Interfaces=All Implemented Interfaces:
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
index 076087c..55b5109 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css
@@ -143,6 +143,9 @@
     font-size:11px;
     margin:0;
 }
+.navPadding {
+    padding-top: 100px;
+}
 .fixedNav {
     position:fixed;
     width:100%;
@@ -265,7 +268,6 @@
 .title {
     color:#2c4557;
     margin:10px 0;
-    padding-top:5.4em;
 }
 .subTitle {
     margin:5px 0 0 0;
@@ -610,7 +612,7 @@
     color:#474747;
 }
 .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
-.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
+.overrideSpecifyLabel, .packageHierarchyLabel, .packageLabelInClass, .paramLabel, .returnLabel,
 .seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
     font-weight:bold;
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
index ddb9289..bd4ff76 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -163,6 +163,8 @@
      */
     private boolean javafx;
 
+    private boolean exportInternalAPI;
+
     /**
      * Construct a new <code>TagletManager</code>.
      * @param nosince true if we do not want to use @since tags.
@@ -172,6 +174,7 @@
      */
     public TagletManager(boolean nosince, boolean showversion,
                          boolean showauthor, boolean javafx,
+                         boolean exportInternalAPI,
                          MessageRetriever message) {
         overridenStandardTags = new HashSet<>();
         potentiallyConflictingTags = new HashSet<>();
@@ -183,6 +186,7 @@
         this.showversion = showversion;
         this.showauthor = showauthor;
         this.javafx = javafx;
+        this.exportInternalAPI = exportInternalAPI;
         this.message = message;
         initStandardTaglets();
         initStandardTagsLowercase();
@@ -233,7 +237,13 @@
                 tagClassLoader = new URLClassLoader(pathToURLs(cpString));
             }
 
+            if (exportInternalAPI) {
+                exportInternalAPI(tagClassLoader);
+            }
+
             customTagClass = tagClassLoader.loadClass(classname);
+            ensureReadable(customTagClass);
+
             Method meth = customTagClass.getMethod("register",
                                                    Map.class);
             Object[] list = customTags.values().toArray();
@@ -253,11 +263,71 @@
                 }
             }
         } catch (Exception exc) {
+            exc.printStackTrace();
             message.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname);
         }
 
     }
 
+    /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Export javadoc internal API to the unnamed module for a classloader.
+     * This is to support continued use of existing non-standard doclets that
+     * use the internal toolkit API and related classes.
+     * @param cl the classloader
+     */
+    private void exportInternalAPI(ClassLoader cl) {
+        String[] packages = {
+            "com.sun.tools.doclets",
+            "com.sun.tools.doclets.standard",
+            "com.sun.tools.doclets.internal.toolkit",
+            "com.sun.tools.doclets.internal.toolkit.taglets",
+            "com.sun.tools.doclets.internal.toolkit.builders",
+            "com.sun.tools.doclets.internal.toolkit.util",
+            "com.sun.tools.doclets.internal.toolkit.util.links",
+            "com.sun.tools.doclets.formats.html",
+            "com.sun.tools.doclets.formats.html.markup"
+        };
+
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(getClass());
+
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
+
+            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
+            Object target = getUnnamedModuleMethod.invoke(cl);
+
+            for (String pack : packages) {
+                addExportsMethod.invoke(thisModule, pack, target);
+            }
+        } catch (Exception e) {
+            // do nothing
+            e.printStackTrace();
+        }
+    }
+
     private String appendPath(String path1, String path2) {
         if (path1 == null || path1.length() == 0) {
             return path2 == null ? "." : path2;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
index 7c0b88d..8b71150 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
@@ -25,6 +25,9 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
+import java.util.Map;
+import java.util.WeakHashMap;
+
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
@@ -42,13 +45,15 @@
  *
  * @since 1.8
  */
-public abstract class DocFileFactory {
+abstract class DocFileFactory {
+    private static final Map<Configuration, DocFileFactory> factories = new WeakHashMap<>();
+
     /**
      * Get the appropriate factory, based on the file manager given in the
      * configuration.
      */
     static synchronized DocFileFactory getFactory(Configuration configuration) {
-        DocFileFactory f = configuration.docFileFactory;
+        DocFileFactory f = factories.get(configuration);
         if (f == null) {
             JavaFileManager fm = configuration.getFileManager();
             if (fm instanceof StandardJavaFileManager) {
@@ -56,7 +61,7 @@
             } else {
                 throw new IllegalStateException();
             }
-            configuration.docFileFactory = f;
+            factories.put(configuration, f);
         }
         return f;
     }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
index 9da6ac6..06e5b27 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocPaths.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -147,26 +147,6 @@
     /** The name of the file for the overview frame. */
     public static final DocPath PROFILE_OVERVIEW_FRAME = DocPath.create("profile-overview-frame.html");
 
-    /** The name of the file for the profile frame. */
-     public static DocPath profileFrame(String profileName) {
-        return DocPath.create(profileName + "-frame.html");
-    }
-
-    /** The name of the file for the profile package frame. */
-     public static DocPath profilePackageFrame(String profileName) {
-        return DocPath.create(profileName + "-package-frame.html");
-    }
-
-    /** The name of the file for the profile package summary. */
-     public static DocPath profilePackageSummary(String profileName) {
-        return DocPath.create(profileName + "-package-summary.html");
-    }
-
-    /** The name of the file for the profile summary. */
-     public static DocPath profileSummary(String profileName) {
-        return DocPath.create(profileName + "-summary.html");
-    }
-
     /** The name of the sub-package from which resources are read. */
     public static final DocPath RESOURCES = DocPath.create("resources");
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
index 350e807..88f3d92 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
@@ -80,7 +80,7 @@
 
         /**
          * The URL or the directory path at which the package documentation will be
-         * avaliable.
+         * available.
          */
         final String path;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
index cf63a7f..5775899 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MetaKeywords.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, 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
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.sun.javadoc.*;
-import com.sun.tools.javac.jvm.Profile;
 import com.sun.tools.doclets.internal.toolkit.*;
 
 /**
@@ -108,20 +107,6 @@
     }
 
     /**
-     * Get the profile keywords.
-     *
-     * @param profile the profile being documented
-     */
-    public String[] getMetaKeywords(Profile profile) {
-        if( configuration.keywords ) {
-            String profileName = profile.name;
-            return new String[] { profileName + " " + "profile" };
-        } else {
-            return new String[] {};
-        }
-    }
-
-    /**
      * Get the overview keywords.
      */
     public String[] getOverviewMetaKeywords(String title, String docTitle) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
index 2c2941d..f20012a 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
@@ -105,12 +105,12 @@
 
     @Override
     Iterable<DocFile> list(Location location, DocPath path) {
-        if (location != StandardLocation.SOURCE_PATH)
-            throw new IllegalArgumentException();
+        Location l = ((location == StandardLocation.SOURCE_PATH)
+                && !fileManager.hasLocation(StandardLocation.SOURCE_PATH))
+                ? StandardLocation.CLASS_PATH
+                : location;
 
         Set<DocFile> files = new LinkedHashSet<>();
-        Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
         for (Path f: fileManager.getLocationAsPaths(l)) {
             if (Files.isDirectory(f)) {
                 f = f.resolve(path.getPath());
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
index 7019a04..0a9acf8 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -32,6 +32,7 @@
 import java.text.Collator;
 import java.util.*;
 
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.javadoc.*;
@@ -205,13 +206,14 @@
      * @param overwrite Overwrite files if true.
      */
     public void copyDocFiles(Configuration configuration, PackageDoc pd) {
-        copyDocFiles(configuration, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
+        Location locn = configuration.getLocationForPackage(pd);
+        copyDocFiles(configuration, locn, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
     }
 
-    public void copyDocFiles(Configuration configuration, DocPath dir) {
+    public void copyDocFiles(Configuration configuration, Location locn, DocPath dir) {
         try {
             boolean first = true;
-            for (DocFile f : DocFile.list(configuration, StandardLocation.SOURCE_PATH, dir)) {
+            for (DocFile f : DocFile.list(configuration, locn, dir)) {
                 if (!f.isDirectory()) {
                     continue;
                 }
@@ -237,7 +239,7 @@
                     } else if (srcfile.isDirectory()) {
                         if (configuration.copydocfilesubdirs
                                 && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
-                            copyDocFiles(configuration, dir.resolve(srcfile.getName()));
+                            copyDocFiles(configuration, locn, dir.resolve(srcfile.getName()));
                         }
                     }
                 }
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
index 7a1abfb..487215c 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java
@@ -101,9 +101,9 @@
     private final Configuration configuration;
     private final Utils utils;
 
-    private final Map<ClassDoc, ProgramElementDoc[]> propertiesCache;
-    private final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap;
-    private final Map<ProgramElementDoc, GetterSetter> getterSetterMap;
+    private static final Map<ClassDoc, ProgramElementDoc[]> propertiesCache = new HashMap<>();
+    private static final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap = new HashMap<>();
+    private static final Map<ProgramElementDoc, GetterSetter> getterSetterMap = new HashMap<>();
 
     /**
      * Construct a VisibleMemberMap of the given type for the given
@@ -123,9 +123,6 @@
         this.kind = kind;
         this.configuration = configuration;
         this.utils = configuration.utils;
-        propertiesCache = configuration.propertiesCache;
-        classPropertiesMap = configuration.classPropertiesMap;
-        getterSetterMap = configuration.getterSetterMap;
         new ClassMembers(classdoc, STARTLEVEL).build();
     }
 
@@ -716,7 +713,7 @@
         }
     }
 
-    public class GetterSetter {
+    private class GetterSetter {
         private final ProgramElementDoc getter;
         private final ProgramElementDoc setter;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
index d67cc78..acebdb8 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
@@ -89,7 +89,7 @@
 public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
 
     public final ClassType type;        // protected->public for debugging
-    protected final ClassSymbol tsym;
+    public final ClassSymbol tsym;
 
     boolean isIncluded = false;         // Set in RootDocImpl
 
@@ -1137,7 +1137,7 @@
 
         //### Add the implicit "import java.lang.*" to the result
         Names names = tsym.name.table.names;
-        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(names.java_lang)));
+        importedPackages.append(env.getPackageDoc(env.syms.enterPackage(env.syms.java_base, names.java_lang)));
 
         Env<AttrContext> compenv = env.enter.getEnv(tsym);
         if (compenv == null) return new PackageDocImpl[0];
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
index 680f37f..2ac3652 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java
@@ -52,6 +52,8 @@
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
+import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 
 /**
@@ -151,7 +153,7 @@
         finder = JavadocClassFinder.instance(context);
         enter = JavadocEnter.instance(context);
         names = Names.instance(context);
-        externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable"));
+        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
@@ -185,7 +187,9 @@
      */
     public ClassDocImpl loadClass(String name) {
         try {
-            ClassSymbol c = finder.loadClass(names.fromString(name));
+            Name nameImpl = names.fromString(name);
+            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
             return getClassDoc(c);
         } catch (CompletionFailure ex) {
             chk.completionError(null, ex);
@@ -201,7 +205,9 @@
         //### to avoid a compiler bug.  Most likely
         //### instead a dummy created for error recovery.
         //### Should investigate this.
-        PackageSymbol p = syms.packages.get(names.fromString(name));
+        Name nameImpl = names.fromString(name);
+        ModuleSymbol mod = syms.inferModule(nameImpl);
+        PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null;
         ClassSymbol c = getClassSymbol(name);
         if (p != null && c == null) {
             return getPackageDoc(p);
@@ -220,7 +226,9 @@
             char[] nameChars = name.toCharArray();
             int idx = name.length();
             for (;;) {
-                ClassSymbol s = syms.classes.get(names.fromChars(nameChars, 0, nameLen));
+                Name nameImpl = names.fromChars(nameChars, 0, nameLen);
+                ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+                ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null;
                 if (s != null)
                     return s; // found it!
                 idx = name.substring(0, idx).lastIndexOf('.');
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
index b432653..f41edba 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, 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
@@ -74,6 +74,12 @@
      */
     private final boolean apiMode;
 
+    /**
+     * Whether javadoc internal API should be exported to doclets
+     * and (indirectly) to taglets
+     */
+    private final boolean exportInternalAPI;
+
     private static class DocletInvokeException extends Exception {
         private static final long serialVersionUID = 0;
     }
@@ -88,21 +94,30 @@
         }
     }
 
-    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode) {
+    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode, boolean exportInternalAPI) {
         this.messager = messager;
         this.docletClass = docletClass;
         docletClassName = docletClass.getName();
         appClassLoader = null;
         this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
+
+        ensureReadable(docletClass);
+        // this may not be soon enough if the class has already been loaded
+        if (exportInternalAPI) {
+            exportInternalAPI(docletClass.getClassLoader());
+        }
     }
 
     public DocletInvoker(Messager messager, JavaFileManager fileManager,
                          String docletClassName, String docletPath,
                          ClassLoader docletParentClassLoader,
-                         boolean apiMode) {
+                         boolean apiMode,
+                         boolean exportInternalAPI) {
         this.messager = messager;
         this.docletClassName = docletClassName;
         this.apiMode = apiMode;
+        this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
 
         if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.DOCLET_PATH)) {
             appClassLoader = fileManager.getClassLoader(DocumentationTool.Location.DOCLET_PATH);
@@ -121,6 +136,10 @@
                 appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
         }
 
+        if (exportInternalAPI) {
+            exportInternalAPI(appClassLoader);
+        }
+
         // attempt to find doclet
         Class<?> dc = null;
         try {
@@ -130,6 +149,8 @@
             messager.exit();
         }
         docletClass = dc;
+
+        ensureReadable(docletClass);
     }
 
     /*
@@ -341,6 +362,64 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Export javadoc internal API to the unnamed module for a classloader.
+     * This is to support continued use of existing non-standard doclets that
+     * use the internal toolkit API and related classes.
+     * @param cl the classloader
+     */
+    private void exportInternalAPI(ClassLoader cl) {
+        String[] packages = {
+            "com.sun.tools.doclets",
+            "com.sun.tools.doclets.standard",
+            "com.sun.tools.doclets.internal.toolkit",
+            "com.sun.tools.doclets.internal.toolkit.taglets",
+            "com.sun.tools.doclets.internal.toolkit.builders",
+            "com.sun.tools.doclets.internal.toolkit.util",
+            "com.sun.tools.doclets.internal.toolkit.util.links",
+            "com.sun.tools.doclets.formats.html",
+            "com.sun.tools.doclets.formats.html.markup"
+        };
+
+        try {
+            Method getModuleMethod = Class.class.getDeclaredMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(getClass());
+
+            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
+            Method addExportsMethod = moduleClass.getDeclaredMethod("addExports", String.class, moduleClass);
+
+            Method getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule");
+            Object target = getUnnamedModuleMethod.invoke(cl);
+
+            for (String pack : packages) {
+                addExportsMethod.invoke(thisModule, pack, target);
+            }
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+
+    /**
      * Utility method for converting a search path string to an array of directory and JAR file
      * URLs.
      *
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
index 617d4cd..b29c289 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/JavadocTool.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
@@ -29,7 +29,6 @@
 import java.io.IOException;
 import java.util.Collection;
 import java.util.EnumSet;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -44,7 +43,7 @@
 
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.Completer;
-import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -53,7 +52,6 @@
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Position;
 
 
 /**
@@ -92,6 +90,7 @@
     /**
      * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
      */
+    @Override
     protected boolean keepComments() {
         return true;
     }
@@ -100,28 +99,22 @@
      *  Construct a new javadoc tool.
      */
     public static JavadocTool make0(Context context) {
-        Messager messager = null;
-        try {
-            // force the use of Javadoc's class finder
-            JavadocClassFinder.preRegister(context);
+        // force the use of Javadoc's class finder
+        JavadocClassFinder.preRegister(context);
 
-            // force the use of Javadoc's own enter phase
-            JavadocEnter.preRegister(context);
+        // force the use of Javadoc's own enter phase
+        JavadocEnter.preRegister(context);
 
-            // force the use of Javadoc's own member enter phase
-            JavadocMemberEnter.preRegister(context);
+        // force the use of Javadoc's own member enter phase
+        JavadocMemberEnter.preRegister(context);
 
-            // force the use of Javadoc's own todo phase
-            JavadocTodo.preRegister(context);
+        // force the use of Javadoc's own todo phase
+        JavadocTodo.preRegister(context);
 
-            // force the use of Messager as a Log
-            messager = Messager.instance0(context);
+        // force the use of Messager as a Log
+        Messager.instance0(context);
 
-            return new JavadocTool(context);
-        } catch (CompletionFailure ex) {
-            messager.error(Position.NOPOS, ex.getMessage());
-            return null;
-        }
+        return new JavadocTool(context);
     }
 
     public RootDocImpl getRootDocImpl(String doclocale,
@@ -170,7 +163,11 @@
             // Parse the files and collect the package names.
             for (String arg: args) {
                 if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
-                    parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    if (new File(arg).getName().equals("module-info.java")) {
+                        docenv.warning(null, "main.file_ignored", arg);
+                    } else {
+                        parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    }
                 } else if (isValidPackageName(arg)) {
                     packageNames.add(arg);
                 } else if (arg.endsWith(".java")) {
@@ -185,10 +182,15 @@
 
             // Parse file objects provide via the DocumentationTool API
             parse(fileObjects, classTrees, true);
+            modules.enter(classTrees.toList(), null);
+
+            syms.unnamedModule.complete(); // TEMP to force reading all named modules
 
             // Build up the complete list of any packages to be documented
-            Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+            Location location =
+                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
+                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
+                    : StandardLocation.CLASS_PATH;
 
             PackageTable t = new PackageTable(docenv.fileManager, location)
                     .packages(packageNames)
@@ -206,6 +208,7 @@
                     messager.warning(Messager.NOPOS, "main.no_source_files_for_package", packageName);
                 parse(files, packageTrees, false);
             }
+            modules.enter(packageTrees.toList(), null);
 
             if (messager.nerrors() != 0) {
                 return null;
@@ -214,6 +217,7 @@
             // Enter symbols for all files
             docenv.notice("main.Building_tree");
             javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
+            enterDone = true;
         } catch (Abort ex) {}
 
         if (messager.nerrors() != 0)
@@ -301,7 +305,7 @@
     /**
      * A table to manage included and excluded packages.
      */
-    static class PackageTable {
+    class PackageTable {
         private final Map<String, Entry> entries = new LinkedHashMap<>();
         private final Set<String> includedPackages = new LinkedHashSet<>();
         private final JavaFileManager fm;
@@ -331,8 +335,9 @@
             }
 
             for (String packageName: packageNames) {
-                for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, true)) {
-                    String binaryName = fm.inferBinaryName(location, fo);
+                Location packageLocn = getLocation(packageName);
+                for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, true)) {
+                    String binaryName = fm.inferBinaryName(packageLocn, fo);
                     String pn = getPackageName(binaryName);
                     String simpleName = getSimpleName(binaryName);
                     Entry e = getEntry(pn);
@@ -366,8 +371,9 @@
                 return e.files;
 
             ListBuffer<JavaFileObject> lb = new ListBuffer<>();
-            for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, false)) {
-                String binaryName = fm.inferBinaryName(location, fo);
+            Location packageLocn = getLocation(packageName);
+            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
+                String binaryName = fm.inferBinaryName(packageLocn, fo);
                 String simpleName = getSimpleName(binaryName);
                 if (isValidClassName(simpleName)) {
                     lb.append(fo);
@@ -377,6 +383,15 @@
             return lb.toList();
         }
 
+        private Location getLocation(String packageName) throws IOException {
+            if (location == StandardLocation.MODULE_SOURCE_PATH) {
+                // TODO: handle invalid results
+                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
+                return fm.getModuleLocation(location, msym.name.toString());
+            } else {
+                return location;
+            }
+        }
 
         private Entry getEntry(String name) {
             Entry e = entries.get(name);
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
index fcc5efd..1375395 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/PackageDocImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
 
 public class PackageDocImpl extends DocImpl implements PackageDoc {
 
-    protected PackageSymbol sym;
+    public final PackageSymbol sym;
     private JCCompilationUnit tree = null;    // for source position
 
     public FileObject docPath = null;
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
index 9e3419f..c057625 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -313,7 +313,11 @@
                     setOption(arg);
                     o.process(this);
                 }
-
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                // pass this hidden option down to the doclet, if it wants it
+                if (docletInvoker.optionLength("-XDaccessInternalAPI") == 1) {
+                    setOption(arg);
+                }
             } else if (arg.startsWith("-XD")) {
                 // hidden javac options
                 String s = arg.substring("-XD".length());
@@ -461,12 +465,7 @@
      * @param argv Args containing -doclet and -docletpath, in case they are required.
      */
     private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
-        if (docletClass != null) {
-            docletInvoker = new DocletInvoker(messager, docletClass, apiMode);
-            // TODO, check no -doclet, -docletpath
-            return;
-        }
-
+        boolean exportInternalAPI = false;
         String docletClassName = null;
         String docletPath = null;
 
@@ -487,18 +486,26 @@
                 } else {
                     docletPath += File.pathSeparator + argv[i];
                 }
+            } else if (arg.equals("-XDaccessInternalAPI")) {
+                exportInternalAPI = true;
             }
         }
 
-        if (docletClassName == null) {
-            docletClassName = defaultDocletClassName;
-        }
+        if (docletClass != null) {
+            // TODO, check no -doclet, -docletpath
+            docletInvoker = new DocletInvoker(messager, docletClass, apiMode, exportInternalAPI);
+        } else {
+            if (docletClassName == null) {
+                docletClassName = defaultDocletClassName;
+            }
 
-        // attempt to find doclet
-        docletInvoker = new DocletInvoker(messager, fileManager,
-                docletClassName, docletPath,
-                docletParentClassLoader,
-                apiMode);
+            // attempt to find doclet
+            docletInvoker = new DocletInvoker(messager, fileManager,
+                    docletClassName, docletPath,
+                    docletParentClassLoader,
+                    apiMode,
+                    exportInternalAPI);
+        }
     }
 
     /**
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
index 6c3b417..18ab44f 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.java
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ToolOption.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
@@ -88,6 +88,48 @@
         }
     },
 
+    MODULESOURCEPATH("-modulesourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
+        }
+    },
+
+    SYSTEM("-system", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEM, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
+    ADDMODS("-addmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    LIMITMODS("-limitmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
     ENCODING("-encoding", true) {
         @Override
         public void process(Helper helper, String arg) {
diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
index 105ab1c..dbd4993 100644
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
@@ -91,6 +91,7 @@
 main.illegal_locale_name=Locale not available: {0}
 main.malformed_locale_name=Malformed locale name: {0}
 main.file_not_found=File not found: "{0}"
+main.file_ignored=File ignored: "{0}" (not yet supported)
 main.illegal_class_name=Illegal class name: "{0}"
 main.illegal_package_name=Illegal package name: "{0}"
 main.release.bootclasspath.conflict=option {0} cannot be used together with -release
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
new file mode 100644
index 0000000..457fe16
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java
@@ -0,0 +1,289 @@
+/*
+ * 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.  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.javadoc.internal.doclets.formats.html;
+
+import java.io.*;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+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.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+
+/**
+ * Abstract class to generate the module overview files in
+ * Frame and Non-Frame format. This will be sub-classed to
+ * generate module-overview-frame.html as well as module-overview-summary.html.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public abstract class AbstractModuleIndexWriter extends HtmlDocletWriter {
+
+    /**
+     * Modules to be documented.
+     */
+    protected Map<ModuleElement, Set<PackageElement>> modules;
+
+    /**
+     * Constructor. Also initializes the modules variable.
+     *
+     * @param configuration  The current configuration
+     * @param filename Name of the module index file to be generated.
+     */
+    public AbstractModuleIndexWriter(ConfigurationImpl configuration,
+                                      DocPath filename) throws IOException {
+        super(configuration, filename);
+        modules = configuration.modulePackages;
+    }
+
+    /**
+     * Adds the navigation bar header to the documentation tree.
+     *
+     * @param body the document tree to which the navigation bar header will be added
+     */
+    protected abstract void addNavigationBarHeader(Content body);
+
+    /**
+     * Adds the navigation bar footer to the documentation tree.
+     *
+     * @param body the document tree to which the navigation bar footer will be added
+     */
+    protected abstract void addNavigationBarFooter(Content body);
+
+    /**
+     * Adds the overview header to the documentation tree.
+     *
+     * @param body the document tree to which the overview header will be added
+     */
+    protected abstract void addOverviewHeader(Content body);
+
+    /**
+     * Adds the modules list to the documentation tree.
+     *
+     * @param modules the set of modules
+     * @param text caption for the table
+     * @param tableSummary summary for the table
+     * @param body the document tree to which the modules list will be added
+     */
+    protected abstract void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body);
+
+    /**
+     * Adds the module packages list to the documentation tree.
+     *
+     * @param modules the set of modules
+     * @param text caption for the table
+     * @param tableSummary summary for the table
+     * @param body the document tree to which the modules list will be added
+     * @param mdle the module being documented
+     */
+    protected abstract void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle);
+
+    /**
+     * Generate and prints the contents in the module index file. Call appropriate
+     * methods from the sub-class in order to generate Frame or Non
+     * Frame format.
+     *
+     * @param title the title of the window.
+     * @param includeScript boolean set true if windowtitle script is to be included
+     */
+    protected void buildModuleIndexFile(String title, boolean includeScript) throws IOException {
+        String windowOverview = configuration.getText(title);
+        Content body = getBody(includeScript, getWindowTitle(windowOverview));
+        addNavigationBarHeader(body);
+        addOverviewHeader(body);
+        addIndex(body);
+        addOverview(body);
+        addNavigationBarFooter(body);
+        printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title,
+                configuration.doctitle), includeScript, body);
+    }
+
+    /**
+     * Generate and prints the contents in the module packages index file. Call appropriate
+     * methods from the sub-class in order to generate Frame or Non
+     * Frame format.
+     *
+     * @param title the title of the window.
+     * @param includeScript boolean set true if windowtitle script is to be included
+     * @param moduleName the name of the module being documented
+     */
+    protected void buildModulePackagesIndexFile(String title,
+            boolean includeScript, ModuleElement mdle) throws IOException {
+        String windowOverview = configuration.getText(title);
+        Content body = getBody(includeScript, getWindowTitle(windowOverview));
+        addNavigationBarHeader(body);
+        addOverviewHeader(body);
+        addModulePackagesIndex(body, mdle);
+        addOverview(body);
+        addNavigationBarFooter(body);
+        printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title,
+                configuration.doctitle), includeScript, body);
+    }
+
+    /**
+     * Default to no overview, override to add overview.
+     *
+     * @param body the document tree to which the overview will be added
+     */
+    protected void addOverview(Content body) throws IOException {
+    }
+
+    /**
+     * Adds the frame or non-frame module index to the documentation tree.
+     *
+     * @param body the document tree to which the index will be added
+     */
+    protected void addIndex(Content body) {
+        addIndexContents(modules, "doclet.Module_Summary",
+                configuration.getText("doclet.Member_Table_Summary",
+                configuration.getText("doclet.Module_Summary"),
+                configuration.getText("doclet.modules")), body);
+    }
+
+    /**
+     * Adds the frame or non-frame module packages index to the documentation tree.
+     *
+     * @param body the document tree to which the index will be added
+     * @param mdle the module being documented
+     */
+    protected void addModulePackagesIndex(Content body, ModuleElement mdle) {
+        addModulePackagesIndexContents("doclet.Module_Summary",
+                configuration.getText("doclet.Member_Table_Summary",
+                configuration.getText("doclet.Module_Summary"),
+                configuration.getText("doclet.modules")), body, mdle);
+    }
+
+    /**
+     * Adds module index contents. Call appropriate methods from
+     * the sub-classes. Adds it to the body HtmlTree
+     *
+     * @param modules the modules to be documented
+     * @param text string which will be used as the heading
+     * @param tableSummary summary for the table
+     * @param body the document tree to which the index contents will be added
+     */
+    protected void addIndexContents(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body) {
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
+                ? HtmlTree.NAV()
+                : new HtmlTree(HtmlTag.DIV);
+        htmlTree.addStyle(HtmlStyle.indexNav);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        addAllClassesLink(ul);
+        addAllPackagesLink(ul);
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+        addModulesList(modules, text, tableSummary, body);
+    }
+
+    /**
+     * Adds module packages index contents. Call appropriate methods from
+     * the sub-classes. Adds it to the body HtmlTree
+     *
+     * @param text string which will be used as the heading
+     * @param tableSummary summary for the table
+     * @param body the document tree to which the index contents will be added
+     * @param mdle the module being documented
+     */
+    protected void addModulePackagesIndexContents(String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
+                ? HtmlTree.NAV()
+                : new HtmlTree(HtmlTag.DIV);
+        htmlTree.addStyle(HtmlStyle.indexNav);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        addAllClassesLink(ul);
+        addAllPackagesLink(ul);
+        addAllModulesLink(ul);
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+        addModulePackagesList(modules, text, tableSummary, body, mdle);
+    }
+
+    /**
+     * Adds the doctitle to the documentation tree, if it is specified on the command line.
+     *
+     * @param body the document tree to which the title will be added
+     */
+    protected void addConfigurationTitle(Content body) {
+        if (configuration.doctitle.length() > 0) {
+            Content title = new RawHtml(configuration.doctitle);
+            Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING,
+                    HtmlStyle.title, title);
+            Content div = HtmlTree.DIV(HtmlStyle.header, heading);
+            body.addContent(div);
+        }
+    }
+
+    /**
+     * Returns highlighted "Overview", in the navigation bar as this is the
+     * overview page.
+     *
+     * @return a Content object to be added to the documentation tree
+     */
+    protected Content getNavLinkContents() {
+        Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, overviewLabel);
+        return li;
+    }
+
+    /**
+     * Do nothing. This will be overridden in ModuleIndexFrameWriter.
+     *
+     * @param div the document tree to which the all classes link will be added
+     */
+    protected void addAllClassesLink(Content div) {
+    }
+
+    /**
+     * Do nothing. This will be overridden in ModuleIndexFrameWriter.
+     *
+     * @param div the document tree to which the all packages link will be added
+     */
+    protected void addAllPackagesLink(Content div) {
+    }
+
+    /**
+     * Do nothing. This will be overridden in ModulePackageIndexFrameWriter.
+     *
+     * @param div the document tree to which the all modules link will be added
+     */
+    protected void addAllModulesLink(Content div) {
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
index 26061a8..62a1074 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java
@@ -160,6 +160,9 @@
             htmlTree.addStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
+            if (configuration.showModules) {
+                addAllModulesLink(ul);
+            }
             htmlTree.addContent(ul);
             body.addContent(htmlTree);
             addPackagesList(packages, text, tableSummary, body);
@@ -199,4 +202,12 @@
      */
     protected void addAllClassesLink(Content div) {
     }
+
+    /**
+     * Do nothing. This will be overridden.
+     *
+     * @param div the document tree to which the all modules link will be added
+     */
+    protected void addAllModulesLink(Content div) {
+    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
index 17efe9c..4137cef 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
@@ -30,6 +30,7 @@
 
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -194,12 +195,22 @@
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
+        ModuleElement mdle = configuration.root.getElementUtils().getModuleOf(typeElement);
+        if (mdle != null && !mdle.isUnnamed()) {
+            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, moduleLabel);
+            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
+            moduleNameDiv.addContent(getSpace());
+            moduleNameDiv.addContent(getModuleLink(mdle,
+                    new StringContent(mdle.getQualifiedName().toString())));
+            div.addContent(moduleNameDiv);
+        }
         PackageElement pkg = utils.containingPackage(typeElement);
         if (!pkg.isUnnamed()) {
             Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel);
             Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel);
             pkgNameDiv.addContent(getSpace());
-            Content pkgNameContent = getPackageLink(pkg, new StringContent(pkg.getQualifiedName()));
+            Content pkgNameContent = getPackageLink(pkg,
+                    new StringContent(utils.getPackageName(pkg)));
             pkgNameDiv.addContent(pkgNameContent);
             div.addContent(pkgNameDiv);
         }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
index 0b7aa5e..64b4b3f 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
@@ -25,6 +25,7 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import java.io.IOException;
 import java.net.*;
 import java.util.*;
 
@@ -33,10 +34,15 @@
 import javax.lang.model.element.TypeElement;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
 
 import com.sun.source.util.DocTreePath;
 import com.sun.tools.doclint.DocLint;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
 
 import jdk.javadoc.doclet.Doclet;
 import jdk.javadoc.doclet.DocletEnvironment;
@@ -49,6 +55,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
 import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 
@@ -507,6 +514,20 @@
         return new ContentBuilder();
     }
 
+    @Override
+    public Location getLocationForPackage(PackageElement pd) {
+        JavaFileManager fm = getFileManager();
+        if (fm.hasLocation(StandardLocation.MODULE_SOURCE_PATH) && (pd instanceof PackageSymbol)) {
+            try {
+                ModuleSymbol msym = ((PackageSymbol) pd).modle;
+                return fm.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH, msym.name.toString());
+            } catch (IOException e) {
+                throw new DocletAbortException(e);
+            }
+        }
+        return StandardLocation.SOURCE_PATH;
+    }
+
     protected void buildSearchTagIndex() {
         for (SearchIndexItem sii : tagSearchIndex) {
             String tagLabel = sii.getLabel();
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
index 70f4a0f..bfa3060 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
@@ -140,7 +140,7 @@
             packageNameContent.addContent(".*");
             link = getHyperLink(DocLink.fragment(parsedPackageName),
                     packageNameContent, "", "");
-            PackageElement abbrevPkg = utils.elementUtils.getPackageElement(parsedPackageName);
+            PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(pkg);
             printedPackageHeaders.add(abbrevPkg);
         }
         contentListTree.addContent(HtmlTree.LI(link));
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
index b0f8ad9..1c0464e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
@@ -28,9 +28,11 @@
 import java.io.*;
 import java.util.*;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
+import com.sun.javadoc.PackageDoc;
 import jdk.javadoc.doclet.Doclet.Option;
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.doclet.Reporter;
@@ -248,6 +250,7 @@
             } catch (IOException e) {
                 throw new DocletAbortException(e);
             } catch (DocletAbortException de) {
+                de.printStackTrace();
                 throw de;
             } catch (Exception e) {
                 e.printStackTrace();
@@ -256,6 +259,37 @@
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    protected void generateModuleFiles() throws Exception {
+        if (configuration.showModules) {
+            ModuleIndexFrameWriter.generate(configuration);
+            ModuleElement prevModule = null, nextModule;
+            List<ModuleElement> mdles = new ArrayList<>(configuration.modulePackages.keySet());
+            int i = 0;
+            for (ModuleElement mdle : mdles) {
+                ModulePackageIndexFrameWriter.generate(configuration, mdle);
+                nextModule = (i + 1 < mdles.size()) ? mdles.get(i + 1) : null;
+                AbstractBuilder moduleSummaryBuilder =
+                        configuration.getBuilderFactory().getModuleSummaryBuilder(
+                        mdle, prevModule, nextModule);
+                moduleSummaryBuilder.build();
+                prevModule = mdle;
+                i++;
+            }
+        }
+    }
+
+    PackageElement getNamedPackage(List<PackageElement> list, int idx) {
+        if (idx < list.size()) {
+            PackageElement pkg = list.get(idx);
+            if (pkg != null && !pkg.isUnnamed()) {
+                return pkg;
+            }
+        }
+        return null;
+    }
 
     /**
      * {@inheritDoc}
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 294bc60..71eedc8 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
@@ -35,6 +35,7 @@
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
@@ -351,6 +352,33 @@
         return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
     }
 
+    /**
+     * Get Module Package link, with target frame.
+     *
+     * @param pkg the PackageElement
+     * @param target name of the target frame
+     * @param label tag for the link
+     * @param mdle the module being documented
+     * @return a content for the target module packages link
+     */
+    public Content getTargetModulePackageLink(PackageElement pkg, String target,
+            Content label, ModuleElement mdle) {
+        return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
+                label, "", target);
+    }
+
+    /**
+     * Get Module link, with target frame.
+     *
+     * @param target name of the target frame
+     * @param label tag for the link
+     * @param mdle the module being documented
+     * @return a content for the target module link
+     */
+    public Content getTargetModuleLink(String target, Content label, ModuleElement mdle) {
+        return getHyperLink(pathToRoot.resolve(
+                DocPaths.moduleSummary(mdle)), label, "", target);
+    }
 
     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
             String tableSummary, List<String> tableHeader, Content summaryContentTree) {
@@ -599,6 +627,8 @@
                 fixedNavDiv.addContent(subDiv);
                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
                 tree.addContent(fixedNavDiv);
+                HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, getSpace());
+                tree.addContent(paddingDiv);
             } else {
                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
                 tree.addContent(subDiv);
@@ -1081,6 +1111,18 @@
         }
     }
 
+    /**
+     * Get Module link.
+     *
+     * @param mdle the module being documented
+     * @param label tag for the link
+     * @return a content for the module link
+     */
+    public Content getModuleLink(ModuleElement mdle, Content label) {
+        return getHyperLink(pathToRoot.resolve(
+                DocPaths.moduleSummary(mdle)), label, "", "");
+    }
+
     public Content interfaceName(TypeElement typeElement, boolean qual) {
         Content name = new StringContent((qual)
                 ? typeElement.getQualifiedName()
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java
new file mode 100644
index 0000000..38bd8cc
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java
@@ -0,0 +1,184 @@
+/*
+ * 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.  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.javadoc.internal.doclets.formats.html;
+
+import java.io.*;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+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.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
+
+/**
+ * Generate the module index for the left-hand frame in the generated output.
+ * A click on the module name in this frame will update the page in the top
+ * left hand frame with the listing of packages of the clicked module.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModuleIndexFrameWriter extends AbstractModuleIndexWriter {
+
+    /**
+     * Construct the ModuleIndexFrameWriter object.
+     *
+     * @param configuration the configuration object
+     * @param filename Name of the module index file to be generated.
+     */
+    public ModuleIndexFrameWriter(ConfigurationImpl configuration,
+                                   DocPath filename) throws IOException {
+        super(configuration, filename);
+    }
+
+    /**
+     * Generate the module index file named "module-overview-frame.html".
+     * @throws DocletAbortException
+     * @param configuration the configuration object
+     */
+    public static void generate(ConfigurationImpl configuration) {
+        ModuleIndexFrameWriter modulegen;
+        DocPath filename = DocPaths.MODULE_OVERVIEW_FRAME;
+        try {
+            modulegen = new ModuleIndexFrameWriter(configuration, filename);
+            modulegen.buildModuleIndexFile("doclet.Window_Overview", false);
+            modulegen.close();
+        } catch (IOException exc) {
+            configuration.standardmessage.error(
+                        "doclet.exception_encountered",
+                        exc.toString(), filename);
+            throw new DocletAbortException(exc);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body) {
+        Content heading = HtmlTree.HEADING(HtmlConstants.MODULE_HEADING, true,
+                modulesLabel);
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
+                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
+                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setTitle(modulesLabel);
+        for (ModuleElement mdle: modules.keySet()) {
+            ul.addContent(getModuleLink(mdle));
+        }
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+    }
+
+    /**
+     * Returns each module name as a separate link.
+     *
+     * @param moduleName the module being documented
+     * @return content for the module link
+     */
+    protected Content getModuleLink(ModuleElement mdle) {
+        Content moduleLinkContent;
+        Content moduleLabel;
+        moduleLabel = new StringContent(mdle.getQualifiedName().toString());
+        moduleLinkContent = getHyperLink(DocPaths.moduleFrame(mdle),
+                moduleLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(moduleLinkContent);
+        return li;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarHeader(Content body) {
+        Content headerContent;
+        if (configuration.packagesheader.length() > 0) {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
+        } else {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
+        }
+        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
+                HtmlStyle.bar, headerContent);
+        body.addContent(heading);
+    }
+
+    /**
+     * Do nothing as there is no overview information in this page.
+     */
+    protected void addOverviewHeader(Content body) {
+    }
+
+    /**
+     * Adds "All Classes" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all classes link should be added
+     */
+    protected void addAllClassesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+                allclassesLabel, "", "packageFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * Adds "All Packages" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all packages link should be added
+     */
+    protected void addAllPackagesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
+                allpackagesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarFooter(Content body) {
+        Content p = HtmlTree.P(getSpace());
+        body.addContent(p);
+    }
+
+    protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java
new file mode 100644
index 0000000..dd87080
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java
@@ -0,0 +1,239 @@
+/*
+ * 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.  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.javadoc.internal.doclets.formats.html;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+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.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
+
+/**
+ * Generate the module package index for the left-hand frame in the generated output.
+ * A click on the package name in this frame will update the page in the bottom
+ * left hand frame with the listing of contents of the clicked module package.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModulePackageIndexFrameWriter extends AbstractModuleIndexWriter {
+
+    /**
+     * Construct the ModulePackageIndexFrameWriter object.
+     *
+     * @param configuration the configuration object
+     * @param filename Name of the package index file to be generated.
+     */
+    public ModulePackageIndexFrameWriter(ConfigurationImpl configuration,
+                                   DocPath filename) throws IOException {
+        super(configuration, filename);
+    }
+
+    /**
+     * Generate the module package index file.
+     * @throws DocletAbortException
+     * @param configuration the configuration object
+     * @param mdle the module being documented
+     */
+    public static void generate(ConfigurationImpl configuration, ModuleElement mdle) {
+        ModulePackageIndexFrameWriter modpackgen;
+        DocPath filename = DocPaths.moduleFrame(mdle);
+        try {
+            modpackgen = new ModulePackageIndexFrameWriter(configuration, filename);
+            modpackgen.buildModulePackagesIndexFile("doclet.Window_Overview", false, mdle);
+            modpackgen.close();
+        } catch (IOException exc) {
+            configuration.standardmessage.error(
+                        "doclet.exception_encountered",
+                        exc.toString(), filename);
+            throw new DocletAbortException(exc);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        Content profNameContent = new StringContent(mdle.getQualifiedName().toString());
+        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
+                getTargetModuleLink("classFrame", profNameContent, mdle));
+        heading.addContent(getSpace());
+        heading.addContent(packagesLabel);
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
+                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
+                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setTitle(packagesLabel);
+        List<PackageElement> packages = new ArrayList<>(modules.get(mdle));
+        for (PackageElement pkg : packages) {
+            if ((!(configuration.nodeprecated && utils.isDeprecated(pkg)))) {
+                ul.addContent(getPackage(pkg, mdle));
+            }
+        }
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addModulePackagesList(Set<ModuleElement> modules, String text,
+            String tableSummary, Content body, ModuleElement mdle) {
+        Content moduleNameContent = new StringContent(mdle.getQualifiedName().toString());
+        Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true,
+                getTargetModuleLink("classFrame", moduleNameContent, mdle));
+        heading.addContent(getSpace());
+        heading.addContent(packagesLabel);
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN))
+                ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading)
+                : HtmlTree.DIV(HtmlStyle.indexContainer, heading);
+        HtmlTree ul = new HtmlTree(HtmlTag.UL);
+        ul.setTitle(packagesLabel);
+        Set<PackageElement> modulePackages = configuration.modulePackages.get(mdle);
+        for (PackageElement pkg: modulePackages) {
+            if ((!(configuration.nodeprecated && utils.isDeprecated(pkg)))) {
+                ul.addContent(getPackage(pkg, mdle));
+            }
+        }
+        htmlTree.addContent(ul);
+        body.addContent(htmlTree);
+    }
+
+    /**
+     * Returns each package name as a separate link.
+     *
+     * @param pkg PackageElement
+     * @param mdle the module being documented
+     * @return content for the package link
+     */
+    protected Content getPackage(PackageElement pkg, ModuleElement mdle) {
+        Content packageLinkContent;
+        Content pkgLabel;
+        if (!pkg.isUnnamed()) {
+            pkgLabel = getPackageLabel(utils.getPackageName(pkg));
+            packageLinkContent = getHyperLink(pathString(pkg,
+                     DocPaths.PACKAGE_FRAME), pkgLabel, "",
+                    "packageFrame");
+        } else {
+            pkgLabel = new StringContent("<unnamed package>");
+            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
+                    pkgLabel, "", "packageFrame");
+        }
+        Content li = HtmlTree.LI(packageLinkContent);
+        return li;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarHeader(Content body) {
+        Content headerContent;
+        if (configuration.packagesheader.length() > 0) {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader));
+        } else {
+            headerContent = new RawHtml(replaceDocRootDir(configuration.header));
+        }
+        Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
+                HtmlStyle.bar, headerContent);
+        body.addContent(heading);
+    }
+
+    /**
+     * Do nothing as there is no overview information in this page.
+     */
+    protected void addOverviewHeader(Content body) {
+    }
+
+    protected void addModulesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
+            String tableSummary, Content body) {
+    }
+
+    /**
+     * Adds "All Classes" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all classes link should be added
+     */
+    protected void addAllClassesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+                allclassesLabel, "", "packageFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * Adds "All Packages" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all packages link should be added
+     */
+    protected void addAllPackagesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
+                allpackagesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * Adds "All Modules" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the all modules link should be added
+     */
+    protected void addAllModulesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+                allmodulesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void addNavigationBarFooter(Content body) {
+        Content p = HtmlTree.P(getSpace());
+        body.addContent(p);
+    }
+}
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
new file mode 100644
index 0000000..105cb70
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
@@ -0,0 +1,286 @@
+/*
+ * 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.  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.javadoc.internal.doclets.formats.html;
+
+import java.io.*;
+import java.util.List;
+import java.util.Set;
+
+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.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+
+/**
+ * Class to generate file for each module contents in the right-hand
+ * frame. This will list all the packages and Class Kinds in the module. A click on any
+ * class-kind will update the frame with the clicked class-kind page. A click on any
+ * package will update the frame with the clicked module package page.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryWriter {
+
+    /**
+     * The prev module name in the alpha-order list.
+     */
+    protected ModuleElement prevModule;
+
+    /**
+     * The next module name in the alpha-order list.
+     */
+    protected ModuleElement nextModule;
+
+    /**
+     * The module being documented.
+     */
+    protected ModuleElement mdle;
+
+    /**
+     * The HTML tree for main tag.
+     */
+    protected HtmlTree mainTree = HtmlTree.MAIN();
+
+    /**
+     * Constructor to construct ModuleWriter object and to generate
+     * "moduleName-summary.html" file.
+     *
+     * @param configuration the configuration of the doclet.
+     * @param module        Module under consideration.
+     * @param prevModule   Previous module in the sorted array.
+     * @param nextModule   Next module in the sorted array.
+     */
+    public ModuleWriterImpl(ConfigurationImpl configuration,
+            ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule)
+            throws IOException {
+        super(configuration, DocPaths.moduleSummary(mdle));
+        this.prevModule = prevModule;
+        this.nextModule = nextModule;
+        this.mdle = mdle;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getModuleHeader(String heading) {
+        HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
+        HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+                ? HtmlTree.HEADER()
+                : bodyTree;
+        addTop(htmlTree);
+        addNavLinks(true, htmlTree);
+        if (configuration.allowTag(HtmlTag.HEADER)) {
+            bodyTree.addContent(htmlTree);
+        }
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        div.addStyle(HtmlStyle.header);
+        Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
+                HtmlStyle.title, moduleLabel);
+        tHeading.addContent(getSpace());
+        Content moduleHead = new RawHtml(heading);
+        tHeading.addContent(moduleHead);
+        div.addContent(tHeading);
+        if (configuration.allowTag(HtmlTag.MAIN)) {
+            mainTree.addContent(div);
+        } else {
+            bodyTree.addContent(div);
+        }
+        return bodyTree;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getContentHeader() {
+        HtmlTree div = new HtmlTree(HtmlTag.DIV);
+        div.addStyle(HtmlStyle.contentContainer);
+        return div;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getSummaryHeader() {
+        HtmlTree li = new HtmlTree(HtmlTag.LI);
+        li.addStyle(HtmlStyle.blockList);
+        return li;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Content getSummaryTree(Content summaryContentTree) {
+        HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
+        return ul;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addPackagesSummary(Set<PackageElement> packages, String text,
+            String tableSummary, Content summaryContentTree) {
+        Content table = (configuration.isOutputHtml5())
+                ? HtmlTree.TABLE(HtmlStyle.overviewSummary, getTableCaption(new RawHtml(text)))
+                : HtmlTree.TABLE(HtmlStyle.overviewSummary, tableSummary, getTableCaption(new RawHtml(text)));
+        table.addContent(getSummaryTableHeader(packageTableHeader, "col"));
+        Content tbody = new HtmlTree(HtmlTag.TBODY);
+        addPackagesList(packages, tbody);
+        table.addContent(tbody);
+        summaryContentTree.addContent(table);
+    }
+
+    /**
+     * Adds list of packages in the package summary table. Generate link to each package.
+     *
+     * @param packages Packages to which link is to be generated
+     * @param tbody the documentation tree to which the list will be added
+     */
+    protected void addPackagesList(Set<PackageElement> packages, Content tbody) {
+        boolean altColor = true;
+        for (PackageElement pkg : packages) {
+            if (pkg != null && !pkg.isUnnamed()) {
+                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
+                    Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
+                    Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent);
+                    HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
+                    tdSummary.addStyle(HtmlStyle.colLast);
+                    addSummaryComment(pkg, tdSummary);
+                    HtmlTree tr = HtmlTree.TR(tdPackage);
+                    tr.addContent(tdSummary);
+                    tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+                    tbody.addContent(tr);
+                }
+            }
+            altColor = !altColor;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addModuleContent(Content contentTree, Content moduleContentTree) {
+        if (configuration.allowTag(HtmlTag.MAIN)) {
+            mainTree.addContent(moduleContentTree);
+            contentTree.addContent(mainTree);
+        } else {
+            contentTree.addContent(moduleContentTree);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addModuleFooter(Content contentTree) {
+        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
+                ? HtmlTree.FOOTER()
+                : contentTree;
+        addNavLinks(false, htmlTree);
+        addBottom(htmlTree);
+        if (configuration.allowTag(HtmlTag.FOOTER)) {
+            contentTree.addContent(htmlTree);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void printDocument(Content contentTree) throws IOException {
+        printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle),
+                true, contentTree);
+    }
+
+    /**
+     * Add the module package deprecation information to the documentation tree.
+     *
+     * @param li the content tree to which the deprecation information will be added
+     * @param pkg the PackageDoc that is added
+     */
+    public void addPackageDeprecationInfo(Content li, PackageElement pkg) {
+        List<? extends DocTree> deprs;
+        if (utils.isDeprecated(pkg)) {
+            deprs = utils.getDeprecatedTrees(pkg);
+            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
+            deprDiv.addStyle(HtmlStyle.deprecatedContent);
+            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase);
+            deprDiv.addContent(deprPhrase);
+            if (!deprs.isEmpty()) {
+                CommentHelper ch = utils.getCommentHelper(pkg);
+                List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
+                if (!commentTags.isEmpty()) {
+                    addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv);
+                }
+            }
+            li.addContent(deprDiv);
+        }
+    }
+
+    /**
+     * Get "PREV MODULE" link in the navigation bar.
+     *
+     * @return a content tree for the previous link
+     */
+    public Content getNavLinkPrevious() {
+        Content li;
+        if (prevModule == null) {
+            li = HtmlTree.LI(prevmoduleLabel);
+        } else {
+            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+                    prevModule)), prevmoduleLabel, "", ""));
+        }
+        return li;
+    }
+
+    /**
+     * Get "NEXT MODULE" link in the navigation bar.
+     *
+     * @return a content tree for the next link
+     */
+    public Content getNavLinkNext() {
+        Content li;
+        if (nextModule == null) {
+            li = HtmlTree.LI(nextmoduleLabel);
+        } else {
+            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+                    nextModule)), nextmoduleLabel, "", ""));
+        }
+        return li;
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
index 94170a3..e83d4ab 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java
@@ -167,6 +167,19 @@
     }
 
     /**
+     * Adds "All Modules" link for the top of the left-hand frame page to the
+     * documentation tree.
+     *
+     * @param ul the Content object to which the "All Modules" link should be added
+     */
+    protected void addAllModulesLink(Content ul) {
+        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+                allmodulesLabel, "", "packageListFrame");
+        Content li = HtmlTree.LI(linkContent);
+        ul.addContent(li);
+    }
+
+    /**
      * {@inheritDoc}
      */
     protected void addNavigationBarFooter(Content body) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
index 8689b0f..64d76a0 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.util.*;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
@@ -124,6 +125,15 @@
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
+        ModuleElement mdle = configuration.root.getElementUtils().getModuleOf(packageElement);
+        if (mdle != null && !mdle.isUnnamed()) {
+            Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, moduleLabel);
+            Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
+            moduleNameDiv.addContent(getSpace());
+            moduleNameDiv.addContent(getModuleLink(mdle,
+                    new StringContent(mdle.getQualifiedName().toString())));
+            div.addContent(moduleNameDiv);
+        }
         Content annotationContent = new HtmlTree(HtmlTag.P);
         addAnnotationInfo(packageElement, annotationContent);
         div.addContent(annotationContent);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
index cce4052..7e67fa7 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -38,6 +39,7 @@
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
@@ -83,6 +85,15 @@
     /**
      * {@inheritDoc}
      */
+    public ModuleSummaryWriter getModuleSummaryWriter(ModuleElement mdle,
+        ModuleElement prevModule, ModuleElement nextModule) throws Exception {
+        return new ModuleWriterImpl(configuration, mdle,
+            prevModule, nextModule);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ClassWriter getClassWriter(TypeElement typeElement, TypeElement prevClass,
             TypeElement nextClass, ClassTree classTree) throws IOException {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
index b1e03e3..1b7731b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java
@@ -192,6 +192,11 @@
     public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2;
 
     /**
+     * Html tag for the module name heading.
+     */
+    public static final HtmlTag MODULE_HEADING = HtmlTag.H2;
+
+    /**
      * Html tag for the member summary heading.
      */
     public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3;
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
index f55de09..301f86d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
@@ -77,10 +77,12 @@
     memberNameLabel,
     memberNameLink,
     memberSummary,
+    moduleLabelInClass,
     nameValue,
     navBarCell1Rev,
     navList,
     navListSearch,
+    navPadding,
     overrideSpecifyLabel,
     overviewSummary,
     packageHierarchyLabel,
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
index dce9fd7..f3774d2 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
@@ -67,6 +67,11 @@
     protected boolean memberDetailsListPrinted;
 
     /**
+     * Header for table displaying modules and description..
+     */
+    protected final List<String> moduleTableHeader;
+
+    /**
      * Header for tables displaying packages and description..
      */
     protected final List<String> packageTableHeader;
@@ -87,6 +92,8 @@
 
     public final Content packageLabel;
 
+    public final Content moduleLabel;
+
     public final Content useLabel;
 
     public final Content prevLabel;
@@ -117,6 +124,8 @@
 
     public final Content allpackagesLabel;
 
+    public final Content allmodulesLabel;
+
     public final Content indexLabel;
 
     public final Content helpLabel;
@@ -129,8 +138,14 @@
 
     public final Content nextpackageLabel;
 
+    public final Content prevmoduleLabel;
+
+    public final Content nextmoduleLabel;
+
     public final Content packagesLabel;
 
+    public final Content modulesLabel;
+
     public final Content methodDetailsLabel;
 
     public final Content annotationTypeDetailsLabel;
@@ -171,6 +186,9 @@
         writer = DocFile.createFileForOutput(configuration, path).openWriter();
         this.configuration = configuration;
         this.memberDetailsListPrinted = false;
+        moduleTableHeader = Arrays.asList(
+            configuration.getText("doclet.Module"),
+            configuration.getText("doclet.Description"));
         packageTableHeader = new ArrayList<>();
         packageTableHeader.add(configuration.getText("doclet.Package"));
         packageTableHeader.add(configuration.getText("doclet.Description"));
@@ -182,6 +200,7 @@
         overviewLabel = getResource("doclet.Overview");
         defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME);
         packageLabel = getResource("doclet.Package");
+        moduleLabel = getResource("doclet.Module");
         useLabel = getResource("doclet.navClassUse");
         prevLabel = getResource("doclet.Prev");
         nextLabel = getResource("doclet.Next");
@@ -197,13 +216,17 @@
         deprecatedPhrase = getResource("doclet.Deprecated");
         allclassesLabel = getNonBreakResource("doclet.All_Classes");
         allpackagesLabel = getNonBreakResource("doclet.All_Packages");
+        allmodulesLabel = getNonBreakResource("doclet.All_Modules");
         indexLabel = getResource("doclet.Index");
         helpLabel = getResource("doclet.Help");
         seeLabel = getResource("doclet.See");
         descriptionLabel = getResource("doclet.Description");
         prevpackageLabel = getNonBreakResource("doclet.Prev_Package");
         nextpackageLabel = getNonBreakResource("doclet.Next_Package");
+        prevmoduleLabel = getNonBreakResource("doclet.Prev_Module");
+        nextmoduleLabel = getNonBreakResource("doclet.Next_Module");
         packagesLabel = getResource("doclet.Packages");
+        modulesLabel = getResource("doclet.Modules");
         methodDetailsLabel = getResource("doclet.Method_Detail");
         annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail");
         fieldDetailsLabel = getResource("doclet.Field_Detail");
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 8e7ac74..6356cbf 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
@@ -4,7 +4,9 @@
 doclet.Window_Overview=Overview List
 doclet.Window_Overview_Summary=Overview
 doclet.Package=Package
+doclet.Module=Module
 doclet.All_Packages=All Packages
+doclet.All_Modules=All Modules
 doclet.Tree=Tree
 doclet.Class_Hierarchy=Class Hierarchy
 doclet.Window_Class_Hierarchy=Class Hierarchy
@@ -17,6 +19,8 @@
 doclet.Next_Class=Next Class
 doclet.Prev_Package=Prev Package
 doclet.Next_Package=Next Package
+doclet.Prev_Module=Prev Module
+doclet.Next_Module=Next Module
 doclet.Prev_Letter=Prev Letter
 doclet.Next_Letter=Next Letter
 doclet.Href_Class_Title=class in {0}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
index e634140..a5ffa28 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
@@ -107,7 +107,6 @@
             return false;
         } catch (DocletAbortException e) {
             Throwable cause = e.getCause();
-            // e.printStackTrace();
             if (cause != null) {
                 if (cause.getLocalizedMessage() != null) {
                     configuration.reporter.print(ERROR, cause.getLocalizedMessage());
@@ -163,6 +162,7 @@
 
         PackageListWriter.generate(configuration);
         generatePackageFiles(classtree);
+        generateModuleFiles();
 
         generateOtherFiles(root, classtree);
         configuration.tagletManager.printReport();
@@ -183,6 +183,12 @@
     }
 
     /**
+     * Generate the module documentation.
+     *
+     */
+    protected abstract void generateModuleFiles() throws Exception;
+
+    /**
      * Generate the package documentation.
      *
      * @param classtree the data structure representing the class tree.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
index 9577631..f16b817 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java
@@ -31,9 +31,11 @@
 import java.util.regex.Pattern;
 
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 
 import com.sun.source.util.DocTreePath;
@@ -240,6 +242,17 @@
     public boolean showversion = false;
 
     /**
+     * Sourcepath from where to read the source files. Default is classpath.
+     *
+     */
+    public String sourcepath = "";
+
+    /**
+     * Generate modules documentation if more than one module is present.
+     */
+    public boolean showModules = false;
+
+    /**
      * Don't generate deprecated API information at all, if -nodeprecated
      * option is used. <code>nodepracted</code> is set to true if
      * -nodeprecated option is used. Default is generate deprected API
@@ -336,6 +349,11 @@
     public DocFileFactory docFileFactory;
 
     /**
+     * A sorted set of modules containing the packages.
+     */
+    public Map<ModuleElement, Set<PackageElement>> modulePackages;
+
+    /**
      * Constructor. Constructs the message retriever with resource file.
      */
     public Configuration() {
@@ -365,6 +383,21 @@
         return this.reporter;
     }
 
+    private void initModules() {
+        // Build the modules structure used by the doclet
+        modulePackages = new TreeMap<>(utils.makeModuleComparator());
+        for (PackageElement p: packages) {
+            ModuleElement mdle = root.getElementUtils().getModuleOf(p);
+            if (mdle != null && !mdle.isUnnamed()) {
+                Set<PackageElement> s = modulePackages.get(mdle);
+                if (s == null)
+                    modulePackages.put(mdle, s = new TreeSet<>(utils.makePackageComparator()));
+                s.add(p);
+            }
+        }
+        showModules = (modulePackages.size() > 1);
+    }
+
     private void initPackages() {
         packages = new TreeSet<>(utils.makePackageComparator());
         packages.addAll(utils.getSpecifiedPackages());
@@ -617,12 +650,13 @@
     /**
      * Set the command line options supported by this configuration.
      *
-     * @return
+     * @return true if the options are set successfully
      * @throws DocletAbortException
      */
-    public boolean setOptions() {
+    public boolean setOptions() throws Fault {
         try {
             initPackages();
+            initModules();
             finishOptionSettings0();
             if (!finishOptionSettings())
                 return false;
@@ -1181,4 +1215,6 @@
             this.value2 = value2;
         }
     }
+
+    public abstract Location getLocationForPackage(PackageElement pd);
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java
new file mode 100644
index 0000000..50a87a6
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java
@@ -0,0 +1,114 @@
+/*
+ * 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.  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.javadoc.internal.doclets.toolkit;
+
+import java.io.*;
+import java.util.Set;
+
+import javax.lang.model.element.PackageElement;
+
+/**
+ * The interface for writing module summary output.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+
+public interface ModuleSummaryWriter {
+
+    /**
+     * Get the header for the summary.
+     *
+     * @param heading module name.
+     * @return the header to be added to the content tree
+     */
+    public abstract Content getModuleHeader(String heading);
+
+    /**
+     * Get the header for the module content.
+     *
+     * @return a content tree for the module content header
+     */
+    public abstract Content getContentHeader();
+
+    /**
+     * Get the header for the summary header.
+     *
+     * @return a content tree with the summary header
+     */
+    public abstract Content getSummaryHeader();
+
+    /**
+     * Get the header for the summary tree.
+     *
+     * @param summaryContentTree the content tree.
+     * @return a content tree with the summary tree
+     */
+    public abstract Content getSummaryTree(Content summaryContentTree);
+
+    /**
+     * Adds the table of packages to the documentation tree.
+     *
+     * @param packages the set of packages that should be added.
+     * @param label the label for this table.
+     * @param tableSummary the summary string for the table
+     * @param summaryContentTree the content tree to which the summary will be added
+     */
+    public abstract void addPackagesSummary(Set<PackageElement> packages, String label,
+            String tableSummary, Content summaryContentTree);
+
+    /**
+     * Adds the module content tree to the documentation tree.
+     *
+     * @param contentTree the tree to which the module content tree will be added
+     * @param moduleContentTree the content tree that will be added
+     */
+    public abstract void addModuleContent(Content contentTree, Content moduleContentTree);
+
+    /**
+     * Adds the footer to the documentation tree.
+     *
+     * @param contentTree the tree to which the footer will be added
+     */
+    public abstract void addModuleFooter(Content contentTree);
+
+    /**
+     * Print the module summary document.
+     *
+     * @param contentTree the content tree that will be printed
+     */
+    public abstract void printDocument(Content contentTree) throws IOException;
+
+    /**
+     * Close the writer.
+     */
+    public abstract void close() throws IOException;
+
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
index 83cbac7..569209b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
@@ -38,6 +38,7 @@
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
@@ -59,6 +60,7 @@
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.model.JavacTypes;
 import com.sun.tools.javac.util.Names;
 
@@ -68,6 +70,7 @@
 
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
+
 import static javax.lang.model.element.ElementKind.*;
 
 /**
@@ -532,4 +535,21 @@
     public JavaFileObject getJavaFileObject(PackageElement pe) {
         return env.pkgToJavaFOMap.get(pe);
     }
+
+    // TODO: we need to eliminate this, as it is hacky.
+    /**
+     * Returns a representation of the package truncated to two levels.
+     * For instance if the given package represents foo.bar.baz will return
+     * a representation of foo.bar
+     * @param pkg the PackageElement
+     * @return an abbreviated PackageElement
+     */
+    public PackageElement getAbbreviatedPackageElement(PackageElement pkg) {
+        String parsedPackageName = utils.parsePackageName(pkg);
+        ModuleElement encl = (ModuleElement) pkg.getEnclosingElement();
+        PackageElement abbrevPkg = encl == null
+                ? utils.elementUtils.getPackageElement(parsedPackageName)
+                : ((JavacElements) utils.elementUtils).getPackageElement(encl, parsedPackageName);
+        return abbrevPkg;
+    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
index dc5441a..a9f400e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
@@ -25,6 +25,7 @@
 
 package jdk.javadoc.internal.doclets.toolkit;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -68,6 +69,19 @@
     throws Exception;
 
     /**
+     * Return the writer for the module summary.
+     *
+     * @param mdle the module being documented.
+     * @param prevModule the previous module that was documented.
+     * @param nextModule the next module being documented.
+     * @return the writer for the module summary.  Return null if this
+     * writer is not supported by the doclet.
+     */
+    public abstract ModuleSummaryWriter getModuleSummaryWriter(
+        ModuleElement mdle, ModuleElement prevModule, ModuleElement nextModule)
+    throws Exception;
+
+    /**
      * Return the writer for a class.
      *
      * @param typeElement the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
index c7731c1..2b8ccd4 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java
@@ -28,6 +28,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
@@ -102,6 +103,20 @@
     }
 
     /**
+     * Return the builder that builds the module summary.
+     *
+     * @param mdle the module being documented.
+     * @param prevModule the previous module being documented.
+     * @param nextModule the next module being documented.
+     * @return the builder that builds the module summary.
+     */
+    public AbstractBuilder getModuleSummaryBuilder(ModuleElement mdle, ModuleElement prevModule,
+            ModuleElement nextModule) throws Exception {
+        return ModuleSummaryBuilder.getInstance(context, mdle,
+            writerFactory.getModuleSummaryWriter(mdle, prevModule, nextModule));
+    }
+
+    /**
      * Return the builder for the class.
      *
      * @param typeElement the class being documented.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
index 080921e..d0a36f7 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
@@ -200,11 +200,10 @@
      * @param summariesTree the tree to which the package header will be added
      */
     public void buildPackageHeader(XMLNode node, Content summariesTree) {
-        String parsedPackageName = utils.parsePackageName(currentPackage);
-        PackageElement p = utils.elementUtils.getPackageElement(parsedPackageName);
-        if (!printedPackageHeaders.contains(p)) {
+        PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(currentPackage);
+        if (!printedPackageHeaders.contains(abbrevPkg)) {
             writer.addPackageName(currentPackage, summariesTree, first);
-            printedPackageHeaders.add(p);
+            printedPackageHeaders.add(abbrevPkg);
         }
     }
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java
new file mode 100644
index 0000000..d2de20d
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java
@@ -0,0 +1,188 @@
+/*
+ * 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.  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.javadoc.internal.doclets.toolkit.builders;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+import javax.tools.StandardLocation;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+
+
+/**
+ * Builds the summary for a given module.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Bhavesh Patel
+ */
+public class ModuleSummaryBuilder extends AbstractBuilder {
+    /**
+     * The root element of the module summary XML is {@value}.
+     */
+    public static final String ROOT = "ModuleDoc";
+
+    /**
+     * The module being documented.
+     */
+    private final ModuleElement mdle;
+
+    /**
+     * The doclet specific writer that will output the result.
+     */
+    private final ModuleSummaryWriter moduleWriter;
+
+    /**
+     * The content that will be added to the module summary documentation tree.
+     */
+    private Content contentTree;
+
+    /**
+     * The module package being documented.
+     */
+    private PackageElement pkg;
+
+    /**
+     * Construct a new ModuleSummaryBuilder.
+     *
+     * @param context  the build context.
+     * @param mdle the module being documented.
+     * @param moduleWriter the doclet specific writer that will output the
+     *        result.
+     */
+    private ModuleSummaryBuilder(Context context,
+            ModuleElement mdle, ModuleSummaryWriter moduleWriter) {
+        super(context);
+        this.mdle = mdle;
+        this.moduleWriter = moduleWriter;
+    }
+
+    /**
+     * Construct a new ModuleSummaryBuilder.
+     *
+     * @param context  the build context.
+     * @param mdle the module being documented.
+     * @param moduleWriter the doclet specific writer that will output the
+     *        result.
+     *
+     * @return an instance of a ModuleSummaryBuilder.
+     */
+    public static ModuleSummaryBuilder getInstance(Context context,
+            ModuleElement mdle, ModuleSummaryWriter moduleWriter) {
+        return new ModuleSummaryBuilder(context, mdle, moduleWriter);
+    }
+
+    /**
+     * Build the module summary.
+     */
+    public void build() throws IOException {
+        if (moduleWriter == null) {
+            //Doclet does not support this output.
+            return;
+        }
+        build(layoutParser.parseXML(ROOT), contentTree);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getName() {
+        return ROOT;
+    }
+
+    /**
+     * Build the module documentation.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param contentTree the content tree to which the documentation will be added
+     */
+    public void buildModuleDoc(XMLNode node, Content contentTree) throws Exception {
+        contentTree = moduleWriter.getModuleHeader(mdle.getSimpleName().toString());
+        buildChildren(node, contentTree);
+        moduleWriter.addModuleFooter(contentTree);
+        moduleWriter.printDocument(contentTree);
+        moduleWriter.close();
+        // TEMPORARY:
+        // The use of SOURCE_PATH on the next line is temporary. As we transition into the
+        // modules world, this should migrate into using a location for the appropriate module
+        // on the MODULE_SOURCE_PATH, or (in the old doclet) simply deleted.
+        utils.copyDocFiles(configuration, StandardLocation.SOURCE_PATH, DocPaths.moduleSummary(mdle));
+    }
+
+    /**
+     * Build the content for the module doc.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param contentTree the content tree to which the module contents
+     *                    will be added
+     */
+    public void buildContent(XMLNode node, Content contentTree) {
+        Content moduleContentTree = moduleWriter.getContentHeader();
+        buildChildren(node, moduleContentTree);
+        moduleWriter.addModuleContent(contentTree, moduleContentTree);
+    }
+
+    /**
+     * Build the module summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param moduleContentTree the module content tree to which the summaries will
+     *                           be added
+     */
+    public void buildSummary(XMLNode node, Content moduleContentTree) {
+        Content summaryContentTree = moduleWriter.getSummaryHeader();
+        buildChildren(node, summaryContentTree);
+        moduleContentTree.addContent(moduleWriter.getSummaryTree(summaryContentTree));
+    }
+
+    /**
+     * Build the module package summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param summaryContentTree the content tree to which the summaries will
+     *                           be added
+     */
+    public void buildPackageSummary(XMLNode node, Content summaryContentTree) {
+        Set<PackageElement> packages = configuration.modulePackages.get(mdle);
+        if (!packages.isEmpty()) {
+            String packageTableSummary
+                    = configuration.getText("doclet.Member_Table_Summary",
+                            configuration.getText("doclet.Package_Summary"),
+                            configuration.getText("doclet.packages"));
+            moduleWriter.addPackagesSummary(
+                    packages, configuration.getText("doclet.Package_Summary"),
+                    packageTableSummary, summaryContentTree);
+        }
+    }
+}
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
index 88c998d..62a3183 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0' encoding='utf-8'?>
 
 <!--
- Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ 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
@@ -28,6 +28,14 @@
 
 <Doclet>
 
+    <ModuleDoc>
+        <Content>
+            <Summary>
+                <PackageSummary/>
+            </Summary>
+        </Content>
+    </ModuleDoc>
+
     <PackageDoc>
         <Content>
             <Summary>
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
index a4b574d..00ed40b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
@@ -31,6 +31,7 @@
 doclet.Building_Index_For_All_Classes=Building index for all classes...
 doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
 doclet.Packages=Packages
+doclet.Modules=Modules
 doclet.Other_Packages=Other Packages
 doclet.Notice_taglet_registered=Registered Taglet {0} ...
 doclet.Notice_taglet_unseen=Note: Custom tags that were not seen: {0}
@@ -68,6 +69,7 @@
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
 doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
+doclet.Module_Summary=Module Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
 doclet.Enum_Summary=Enum Summary
@@ -90,6 +92,7 @@
 doclet.Classes=Classes
 doclet.Packages=Packages
 doclet.packages=packages
+doclet.modules=modules
 doclet.All_Classes=All Classes
 doclet.All_Superinterfaces=All Superinterfaces:
 doclet.All_Implemented_Interfaces=All Implemented Interfaces:
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
index 4a0e575..eef017b 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css
@@ -143,6 +143,9 @@
     font-size:11px;
     margin:0;
 }
+.navPadding {
+    padding-top: 100px;
+}
 .fixedNav {
     position:fixed;
     width:100%;
@@ -265,7 +268,6 @@
 .title {
     color:#2c4557;
     margin:10px 0;
-    padding-top:5.4em;
 }
 .subTitle {
     margin:5px 0 0 0;
@@ -610,9 +612,9 @@
     color:#474747;
 }
 .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
-.overrideSpecifyLabel, .packageLabelInClass, .packageHierarchyLabel,
-.paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel,
-.typeNameLabel, .typeNameLink, .searchTagLink {
+.moduleLabelInClass, .overrideSpecifyLabel, .packageLabelInClass,
+.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel,
+.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
     font-weight:bold;
 }
 .deprecationComment, .emphasizedPhrase, .interfaceName {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
index 9cc9dc2..f03b1c4 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
@@ -26,6 +26,7 @@
 package jdk.javadoc.internal.doclets.toolkit.taglets;
 
 import java.io.*;
+import java.lang.reflect.Method;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -231,7 +232,7 @@
      */
     public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) {
         try {
-            ClassLoader tagClassLoader;
+            ClassLoader tagClassLoader = null;
             if (!fileManager.hasLocation(TAGLET_PATH)) {
                 List<File> paths = new ArrayList<>();
                 if (tagletPath != null) {
@@ -245,6 +246,7 @@
             }
             tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
             Class<?> customTagClass = tagClassLoader.loadClass(classname);
+            ensureReadable(customTagClass);
             Object instance = customTagClass.newInstance();
             Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance);
             String tname = newLegacy.getName();
@@ -260,6 +262,27 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e.toString());
+        }
+    }
+
+    /**
      * Add a new <code>SimpleTaglet</code>.  If this tag already exists
      * and the header passed as an argument is null, move tag to the back of the
      * list. If this tag already exists and the header passed as an argument is
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
index 8eaf210..57956f9 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.toolkit.util;
 
+import javax.lang.model.element.ModuleElement;
+
 /**
  * Standard DocPath objects.
  *
@@ -143,6 +145,19 @@
     /** The name of the file for the package usage info. */
     public static final DocPath PACKAGE_USE = DocPath.create("package-use.html");
 
+    /** The name of the file for the module frame. */
+    public static DocPath moduleFrame(ModuleElement mdle) {
+        return DocPath.create(mdle.getQualifiedName() + "-frame.html");
+    }
+
+    /** The name of the file for the module summary. */
+    public static DocPath moduleSummary(ModuleElement mdle) {
+        return DocPath.create(mdle.getQualifiedName() + "-summary.html");
+    }
+
+    /** The name of the file for the module overview frame. */
+    public static final DocPath MODULE_OVERVIEW_FRAME = DocPath.create("module-overview-frame.html");
+
     /** The name of the sub-package from which resources are read. */
     public static final DocPath RESOURCES = DocPath.create("resources");
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java
index c36f293..d0bac01 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MetaKeywords.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;
 
@@ -109,6 +110,19 @@
     }
 
     /**
+     * Get the module keywords.
+     *
+     * @param mdle the module being documented
+     */
+    public List<String> getMetaKeywordsForModule(ModuleElement mdle) {
+        if (config.keywords) {
+            return Arrays.asList(mdle.getQualifiedName() + " " + "module");
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
      * Get the overview keywords.
      */
     public List<String> getOverviewMetaKeywords(String title, String docTitle) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
index 004fcb1..6cf91e5 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java
@@ -104,12 +104,12 @@
 
     @Override
     Iterable<DocFile> list(Location location, DocPath path) {
-        if (location != StandardLocation.SOURCE_PATH)
-            throw new IllegalArgumentException();
+        Location l = ((location == StandardLocation.SOURCE_PATH)
+                && !fileManager.hasLocation(StandardLocation.SOURCE_PATH))
+                ? StandardLocation.CLASS_PATH
+                : location;
 
         Set<DocFile> files = new LinkedHashSet<>();
-        Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
         for (Path f: fileManager.getLocationAsPaths(l)) {
             if (Files.isDirectory(f)) {
                 f = f.resolve(path.getPath());
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
index fa2c90f..d2d5d2a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
@@ -41,6 +41,7 @@
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.TypeParameterElement;
@@ -60,6 +61,7 @@
 import javax.lang.model.util.TypeKindVisitor9;
 import javax.lang.model.util.Types;
 import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
 import com.sun.source.doctree.DocCommentTree;
@@ -1539,6 +1541,45 @@
         return secondaryCollator.compare(s1, s2);
     }
 
+    public void copyDocFiles(Configuration configuration, Location locn, DocPath dir) {
+        try {
+            boolean first = true;
+            for (DocFile f : DocFile.list(configuration, locn, dir)) {
+                if (!f.isDirectory()) {
+                    continue;
+                }
+                DocFile srcdir = f;
+                DocFile destdir = DocFile.createFileForOutput(configuration, dir);
+                if (srcdir.isSameFile(destdir)) {
+                    continue;
+                }
+
+                for (DocFile srcfile: srcdir.list()) {
+                    DocFile destfile = destdir.resolve(srcfile.getName());
+                    if (srcfile.isFile()) {
+                        if (destfile.exists() && !first) {
+                            configuration.message.warning("doclet.Copy_Overwrite_warning",
+                                    srcfile.getPath(), destdir.getPath());
+                        } else {
+                            configuration.message.notice(
+                                    "doclet.Copying_File_0_To_Dir_1",
+                                    srcfile.getPath(), destdir.getPath());
+                            destfile.copyFile(srcfile);
+                        }
+                    } else if (srcfile.isDirectory()) {
+                        if (configuration.copydocfilesubdirs
+                                && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
+                            copyDocFiles(configuration, locn, dir.resolve(srcfile.getName()));
+                        }
+                    }
+                }
+
+                first = false;
+            }
+        } catch (SecurityException | IOException exc) {
+            throw new com.sun.tools.doclets.internal.toolkit.util.DocletAbortException(exc);
+        }
+    }
 
     private static class DocCollator {
         private final Map<String, CollationKey> keys;
@@ -1567,6 +1608,18 @@
     }
 
     /**
+     * Comparator for ModuleElements, simply compares the fully qualified names
+     */
+    public Comparator<Element> makeModuleComparator() {
+        return new Utils.ElementComparator<Element>() {
+            @Override
+            public int compare(Element mod1, Element mod2) {
+                return compareFullyQualifiedNames(mod1, mod2);
+            }
+        };
+    }
+
+    /**
      * Comparator for PackageElements, simply compares the fully qualified names
      */
     public Comparator<Element> makePackageComparator() {
@@ -1942,6 +1995,11 @@
          */
         private String getFullyQualifiedName(Element e) {
             return new SimpleElementVisitor9<String, Void>() {
+                @Override  @DefinedBy(Api.LANGUAGE_MODEL)
+                public String visitModule(ModuleElement e, Void p) {
+                    return e.getQualifiedName().toString();
+                }
+
                 @Override @DefinedBy(Api.LANGUAGE_MODEL)
                 public String visitPackage(PackageElement e, Void p) {
                     return e.getQualifiedName().toString();
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
index 0be30eb..674187d 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java
@@ -50,6 +50,7 @@
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
@@ -65,8 +66,10 @@
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Convert;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
@@ -164,7 +167,7 @@
         finder = JavadocClassFinder.instance(context);
         enter = JavadocEnter.instance(context);
         names = Names.instance(context);
-        externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable"));
+        externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable"));
         chk = Check.instance(context);
         types = com.sun.tools.javac.code.Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
@@ -199,7 +202,9 @@
      */
     public TypeElement loadClass(String name) {
         try {
-            ClassSymbol c = finder.loadClass(names.fromString(name));
+            Name nameImpl = names.fromString(name);
+            ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl));
+            ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl);
             return c;
         } catch (CompletionFailure ex) {
             chk.completionError(null, ex);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
index d546d4a..b62c322 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocClassFinder.java
@@ -66,6 +66,7 @@
                                                           JavaFileObject.Kind.HTML);
     private EnumSet<JavaFileObject.Kind> noSource = EnumSet.of(JavaFileObject.Kind.CLASS,
                                                                JavaFileObject.Kind.HTML);
+    private JavacTrees jctrees;
 
     private final JavacTrees trees;
 
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
index c8250e6..227063a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.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
@@ -48,6 +48,7 @@
 import com.sun.tools.javac.code.ClassFinder;
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -95,6 +96,7 @@
     /**
      * For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
      */
+    @Override
     protected boolean keepComments() {
         return true;
     }
@@ -158,6 +160,7 @@
         Set<String> includedPackages = new LinkedHashSet<>();
 
         try {
+
             StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
                     ? (StandardJavaFileManager) docenv.fileManager : null;
             Set<String> packageNames = new LinkedHashSet<>();
@@ -165,7 +168,11 @@
             // Parse the files and collect the package names.
             for (String arg: args) {
                 if (fm != null && arg.endsWith(".java") && new File(arg).exists()) {
-                    parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    if (new File(arg).getName().equals("module-info.java")) {
+                        docenv.warning("main.file_ignored", arg);
+                    } else {
+                        parse(fm.getJavaFileObjects(arg), classTrees, true);
+                    }
                 } else if (isValidPackageName(arg)) {
                     packageNames.add(arg);
                 } else if (arg.endsWith(".java")) {
@@ -180,10 +187,15 @@
 
             // Parse file objects provide via the DocumentationTool API
             parse(fileObjects, classTrees, true);
+            modules.enter(classTrees.toList(), null);
+
+            syms.unnamedModule.complete(); // TEMP to force reading all named modules
 
             // Build up the complete list of any packages to be documented
-            Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
-                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+            Location location =
+                    modules.multiModuleMode && !modules.noModules ? StandardLocation.MODULE_SOURCE_PATH
+                    : docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH
+                    : StandardLocation.CLASS_PATH;
 
             PackageTable t = new PackageTable(docenv.fileManager, location)
                     .packages(packageNames)
@@ -200,6 +212,7 @@
                     docenv.warning("main.no_source_files_for_package", packageName);
                 parse(files, packageTrees, false);
             }
+            modules.enter(packageTrees.toList(), null);
 
             if (messager.nerrors() != 0) {
                 return null;
@@ -208,6 +221,8 @@
             // Enter symbols for all files
             docenv.notice("main.Building_tree");
             javadocEnter.main(classTrees.toList().appendList(packageTrees.toList()));
+
+            enterDone = true;
         } catch (Abort ex) {}
 
         if (messager.nerrors() != 0)
@@ -296,7 +311,7 @@
     /**
      * A table to manage included and excluded packages.
      */
-    static class PackageTable {
+    class PackageTable {
         private final Map<String, Entry> entries = new LinkedHashMap<>();
         private final Set<String> includedPackages = new LinkedHashSet<>();
         private final JavaFileManager fm;
@@ -363,8 +378,11 @@
                 return e.files;
 
             ListBuffer<JavaFileObject> lb = new ListBuffer<>();
-            for (JavaFileObject fo: fm.list(location, packageName, sourceKinds, false)) {
-                String binaryName = fm.inferBinaryName(location, fo);
+            Location packageLocn = getLocation(packageName);
+            if (packageLocn == null)
+                return Collections.emptyList();
+            for (JavaFileObject fo: fm.list(packageLocn, packageName, sourceKinds, false)) {
+                String binaryName = fm.inferBinaryName(packageLocn, fo);
                 String simpleName = getSimpleName(binaryName);
                 if (isValidClassName(simpleName)) {
                     lb.append(fo);
@@ -374,6 +392,18 @@
             return lb.toList();
         }
 
+        private Location getLocation(String packageName) throws IOException {
+            if (location == StandardLocation.MODULE_SOURCE_PATH) {
+                // TODO: handle invalid results better.
+                ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
+                if (msym == null) {
+                    return null;
+                }
+                return fm.getModuleLocation(location, msym.name.toString());
+            } else {
+                return location;
+            }
+        }
 
         private Entry getEntry(String name) {
             Entry e = entries.get(name);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
index 4cc5e18..0de7455 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java
@@ -29,6 +29,7 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Method;
 import java.nio.file.Path;
 import java.text.BreakIterator;
 import java.util.ArrayList;
@@ -39,7 +40,9 @@
 import java.util.Locale;
 import java.util.Objects;
 import java.util.Set;
+
 import static javax.tools.DocumentationTool.Location.*;
+
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
@@ -249,6 +252,7 @@
             try {
                 doclet = (Doclet) docletClass.newInstance();
             } catch (InstantiationException | IllegalAccessException exc) {
+                exc.printStackTrace();
                 if (!apiMode) {
                     error("main.could_not_instantiate_class", docletClass);
                     messager.exit();
@@ -306,6 +310,27 @@
     }
 
     /**
+     * Ensures that the module of the given class is readable to this
+     * module.
+     * @param targetClass class in module to be made readable
+     */
+    private void ensureReadable(Class<?> targetClass) {
+        try {
+            Method getModuleMethod = Class.class.getMethod("getModule");
+            Object thisModule = getModuleMethod.invoke(this.getClass());
+            Object targetModule = getModuleMethod.invoke(targetClass);
+
+            Class<?> moduleClass = getModuleMethod.getReturnType();
+            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+            addReadsMethod.invoke(thisModule, targetModule);
+        } catch (NoSuchMethodException e) {
+            // ignore
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
      * Main program - internal
      */
     private boolean parseAndExecute(List<String> argList,
@@ -490,7 +515,9 @@
                     return null; // keep compiler happy
                 }
                 try {
-                    return cl.loadClass(userDocletName);
+                    Class<?> klass = cl.loadClass(userDocletName);
+                    ensureReadable(klass);
+                    return klass;
                 } catch (ClassNotFoundException cnfe) {
                     panic("main.doclet_class_not_found", userDocletName);
                     return null; // keep compiler happy
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 9b0a8ae..7f8d2f0 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
@@ -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
@@ -87,6 +87,48 @@
         }
     },
 
+    MODULESOURCEPATH("-modulesourcepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULESOURCEPATH, arg);
+        }
+    },
+
+    UPGRADEMODULEPATH("-upgrademodulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.UPGRADEMODULEPATH, arg);
+        }
+    },
+
+    SYSTEM("-system", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.SYSTEM, arg);
+        }
+    },
+
+    MODULEPATH("-modulepath", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setFileManagerOpt(Option.MODULEPATH, arg);
+        }
+    },
+
+    ADDMODS("-addmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
+    LIMITMODS("-limitmods", true) {
+        @Override
+        public void process(Helper helper, String arg) {
+            helper.setCompilerOpt(opt, arg);
+        }
+    },
+
     ENCODING("-encoding", true) {
         @Override
         public void process(Helper helper, String arg) {
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 519385d..1bebe48 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
@@ -86,6 +86,7 @@
 main.illegal_locale_name=Locale not available: {0}
 main.malformed_locale_name=Malformed locale name: {0}
 main.file_not_found=File not found: "{0}"
+main.file_ignored=File ignored: "{0}" (not yet supported)
 main.illegal_class_name=Illegal class name: "{0}"
 main.illegal_package_name=Illegal package name: "{0}"
 main.release.bootclasspath.conflict=option {0} cannot be used together with -release
diff --git a/langtools/src/jdk.javadoc/share/classes/module-info.java b/langtools/src/jdk.javadoc/share/classes/module-info.java
new file mode 100644
index 0000000..c548ec9
--- /dev/null
+++ b/langtools/src/jdk.javadoc/share/classes/module-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * 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.
+ */
+
+module jdk.javadoc {
+    requires public java.compiler;
+    requires public jdk.compiler;
+    requires java.xml;
+
+    exports com.sun.javadoc;
+    exports com.sun.tools.doclets;
+    exports com.sun.tools.javadoc;
+    exports jdk.javadoc.doclet;
+    exports jdk.javadoc.doclet.taglet;
+
+    provides javax.tools.DocumentationTool
+        with jdk.javadoc.internal.api.JavadocTool;
+}
+
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
index 051a325..5e9b685 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -56,7 +56,8 @@
     public static final int ACC_SYNTHETIC     = 0x1000; // class, inner, field, method
     public static final int ACC_ANNOTATION    = 0x2000; // class, inner
     public static final int ACC_ENUM          = 0x4000; // class, inner, field
-    public static final int ACC_MANDATED      = 0x8000; // class, inner, field, method
+    public static final int ACC_MANDATED      = 0x8000; //                          method parameter
+    public static final int ACC_MODULE        = 0x8000; // class
 
     public static enum Kind { Class, InnerClass, Field, Method}
 
@@ -86,7 +87,7 @@
 
     private static final int[] classFlags = {
         ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
-        ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
+        ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
     };
 
     public Set<String> getClassModifiers() {
@@ -247,8 +248,8 @@
             return "ACC_ANNOTATION";
         case ACC_ENUM:
             return "ACC_ENUM";
-        case ACC_MANDATED:
-            return "ACC_MANDATED";
+        case 0x8000:
+            return (t == Kind.Class ? "ACC_MODULE" : "ACC_MANDATED");
         default:
             return null;
         }
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 ce5ec70..fed0bed 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, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -42,16 +42,20 @@
     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 RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
     public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
     public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@@ -65,6 +69,8 @@
     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() {
@@ -109,15 +115,19 @@
             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(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
             standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
             standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
@@ -131,6 +141,8 @@
             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;
@@ -166,15 +178,19 @@
         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 visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
         R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
         R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
@@ -188,5 +204,7 @@
         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 903931d..b4fad8a 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -221,7 +221,7 @@
             }
         }
 
-        private DataOutputStream d;
+        private final DataOutputStream d;
     }
 
     /**
@@ -234,73 +234,87 @@
             return info.accept(this, out);
         }
 
+        @Override
         public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
             out.writeShort(info.name_index);
             return 1;
         }
 
+        @Override
         public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
             out.writeDouble(info.value);
             return 2;
         }
 
+        @Override
         public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
             writeRef(info, out);
             return 1;
         }
 
+        @Override
         public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
             out.writeFloat(info.value);
             return 1;
         }
 
+        @Override
         public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
             out.writeInt(info.value);
             return 1;
         }
 
+        @Override
         public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
             writeRef(info, out);
             return 1;
         }
 
+        @Override
         public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) {
             out.writeShort(info.bootstrap_method_attr_index);
             out.writeShort(info.name_and_type_index);
             return 1;
         }
 
+        @Override
         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
             out.writeLong(info.value);
             return 2;
         }
 
+        @Override
         public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
             out.writeShort(info.name_index);
             out.writeShort(info.type_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) {
             out.writeByte(info.reference_kind.tag);
             out.writeShort(info.reference_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) {
             out.writeShort(info.descriptor_index);
             return 1;
         }
 
+        @Override
         public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
             return writeRef(info, out);
         }
 
+        @Override
         public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
             out.writeShort(info.string_index);
             return 1;
         }
 
+        @Override
         public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
             out.writeUTF(info.value);
             return 1;
@@ -336,16 +350,19 @@
         protected ClassOutputStream sharedOut = new ClassOutputStream();
         protected AnnotationWriter annotationWriter = new AnnotationWriter();
 
+        @Override
         public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
             out.write(attr.info, 0, attr.info.length);
             return null;
         }
 
+        @Override
         public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.default_value, out);
             return null;
         }
 
+        @Override
         public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.bootstrap_method_specifiers.length);
             for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) {
@@ -359,6 +376,7 @@
             return null;
         }
 
+        @Override
         public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.character_range_table.length);
             for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
@@ -374,6 +392,7 @@
             out.writeShort(entry.flags);
         }
 
+        @Override
         public Void visitCode(Code_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.max_stack);
             out.writeShort(attr.max_locals);
@@ -393,26 +412,39 @@
             out.writeShort(exception_data.catch_type);
         }
 
+        @Override
         public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.compilationID_index);
             return null;
         }
 
+        @Override
+        public Void visitConcealedPackages(ConcealedPackages_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.packages_count);
+            for (int i: attr.packages_index)
+                out.writeShort(i);
+            return null;
+        }
+
+        @Override
         public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.constantvalue_index);
             return null;
         }
 
+        @Override
         public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
             return null;
         }
 
+        @Override
         public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.class_index);
             out.writeShort(attr.method_index);
             return null;
         }
 
+        @Override
         public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.exception_index_table.length);
             for (int i: attr.exception_index_table)
@@ -420,6 +452,7 @@
             return null;
         }
 
+        @Override
         public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.classes.length);
             for (InnerClasses_attribute.Info info: attr.classes)
@@ -427,6 +460,17 @@
             return null;
         }
 
+        @Override
+        public Void visitHashes(Hashes_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);
+            }
+            return null;
+        }
+
         protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
             out.writeShort(info.inner_class_info_index);
             out.writeShort(info.outer_class_info_index);
@@ -434,6 +478,7 @@
             writeAccessFlags(info.inner_class_access_flags, out);
         }
 
+        @Override
         public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.line_number_table.length);
             for (LineNumberTable_attribute.Entry e: attr.line_number_table)
@@ -446,6 +491,7 @@
             out.writeShort(entry.line_number);
         }
 
+        @Override
         public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.local_variable_table.length);
             for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
@@ -461,6 +507,7 @@
             out.writeShort(entry.index);
         }
 
+        @Override
         public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.local_variable_table.length);
             for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
@@ -476,6 +523,7 @@
             out.writeShort(entry.index);
         }
 
+        @Override
         public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.method_parameter_table.length);
             for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
@@ -485,26 +533,62 @@
             return null;
         }
 
+        @Override
+        public Void visitMainClass(MainClass_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.main_class_index);
+            return null;
+        }
+
+        @Override
+        public Void visitModule(Module_attribute attr, ClassOutputStream out) {
+            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_to_index.length);
+                for (int index: e.exports_to_index)
+                    out.writeShort(index);
+            }
+            out.writeShort(attr.uses_index.length);
+            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);
+            }
+            return null;
+        }
+
+        @Override
         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
             annotationWriter.write(attr.annotations, out);
             return null;
         }
 
+        @Override
         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.parameter_annotations.length);
             for (Annotation[] annos: attr.parameter_annotations)
@@ -512,6 +596,7 @@
             return null;
         }
 
+        @Override
         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
             out.writeByte(attr.parameter_annotations.length);
             for (Annotation[] annos: attr.parameter_annotations)
@@ -519,26 +604,31 @@
             return null;
         }
 
+        @Override
         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.signature_index);
             return null;
         }
 
+        @Override
         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
             out.write(attr.debug_extension, 0, attr.debug_extension.length);
             return null;
         }
 
+        @Override
         public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.sourcefile_index);
             return null;
         }
 
+        @Override
         public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.sourceID_index);
             return null;
         }
 
+        @Override
         public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
             if (stackMapWriter == null)
                 stackMapWriter = new StackMapTableWriter();
@@ -549,6 +639,7 @@
             return null;
         }
 
+        @Override
         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
             if (stackMapWriter == null)
                 stackMapWriter = new StackMapTableWriter();
@@ -559,14 +650,29 @@
             return null;
         }
 
+        @Override
         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
             return null;
         }
 
+        @Override
+        public Void visitTargetPlatform(TargetPlatform_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.os_name_index);
+            out.writeShort(attr.os_arch_index);
+            out.writeShort(attr.os_version_index);
+            return null;
+        }
+
         protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
             sharedOut.writeShort(flags.flags);
         }
 
+        @Override
+        public Void visitVersion(Version_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.version_index);
+            return null;
+        }
+
         protected StackMapTableWriter stackMapWriter;
     }
 
@@ -581,31 +687,37 @@
             frame.accept(this, out);
         }
 
+        @Override
         public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
             writeVerificationTypeInfo(frame.stack[0], out);
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             writeVerificationTypeInfo(frame.stack[0], out);
             return null;
         }
 
+        @Override
         public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             return null;
         }
 
+        @Override
         public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             return null;
         }
 
+        @Override
         public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             for (verification_type_info l: frame.locals)
@@ -613,6 +725,7 @@
             return null;
         }
 
+        @Override
         public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
             out.writeShort(frame.offset_delta);
             out.writeShort(frame.locals.length);
@@ -692,27 +805,32 @@
             ev.accept(this, out);
         }
 
+        @Override
         public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.const_value_index);
             return null;
         }
 
+        @Override
         public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.type_name_index);
             out.writeShort(ev.const_name_index);
             return null;
         }
 
+        @Override
         public Void visitClass(Class_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.class_info_index);
             return null;
         }
 
+        @Override
         public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
             write(ev.annotation_value, out);
             return null;
         }
 
+        @Override
         public Void visitArray(Array_element_value ev, ClassOutputStream out) {
             out.writeShort(ev.num_values);
             for (element_value v: ev.values)
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/ConcealedPackages_attribute.java
new file mode 100644
index 0000000..dc56d7b
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class ConcealedPackages_attribute extends Attribute {
+    ConcealedPackages_attribute(ClassReader cr, int name_index, int length)
+            throws IOException {
+        super(name_index, length);
+        packages_count = cr.readUnsignedShort();
+        packages_index = new int[packages_count];
+        for (int i = 0; i < packages_count; i++)
+            packages_index[i] = cr.readUnsignedShort();
+    }
+
+    public ConcealedPackages_attribute(ConstantPool constant_pool,
+                                       int[] packages_index)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.ConcealedPackages),
+             packages_index);
+    }
+
+    public ConcealedPackages_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;
+    }
+
+    public String getPackage(int index, ConstantPool constant_pool) throws ConstantPoolException {
+        int package_index = packages_index[index];
+        return constant_pool.getUTF8Value(package_index);
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitConcealedPackages(this, data);
+    }
+
+    public final int packages_count;
+    public final int[] packages_index;
+}
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/Hashes_attribute.java
new file mode 100644
index 0000000..a248ebc
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Hashes_attribute extends Attribute {
+    Hashes_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        algorithm_index = cr.readUnsignedShort();
+        hashes_table_length = cr.readUnsignedShort();
+        hashes_table = new Entry[hashes_table_length];
+        for (int i = 0; i < hashes_table_length; i++)
+            hashes_table[i] = new Entry(cr);
+    }
+
+    public Hashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Hashes), 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());
+        this.algorithm_index = algorithm_index;
+        this.hashes_table_length = hashes_table.length;
+        this.hashes_table = hashes_table;
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitHashes(this, data);
+    }
+
+    public final int algorithm_index;
+    public final int hashes_table_length;
+    public final Entry[] hashes_table;
+
+    public static class Entry {
+        Entry(ClassReader cr) throws IOException {
+            requires_index = cr.readUnsignedShort();
+            hash_index = cr.readUnsignedShort();
+        }
+
+        public static int length() {
+            return 4;
+        }
+
+        public final int requires_index;
+        public final int hash_index;
+    }
+
+}
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/MainClass_attribute.java
new file mode 100644
index 0000000..ccd4554
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class MainClass_attribute extends Attribute {
+    MainClass_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)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Version), mainClass_index);
+    }
+
+    public MainClass_attribute(int name_index, int mainClass_index) {
+        super(name_index, 2);
+        this.main_class_index = mainClass_index;
+    }
+
+    public String getMainClassName(ConstantPool constant_pool) throws ConstantPoolException {
+        return constant_pool.getClassInfo(main_class_index).getName();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitMainClass(this, data);
+    }
+
+    public final int main_class_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
new file mode 100644
index 0000000..b20729f
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See Jigsaw.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class 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;
+
+    Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        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);
+        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++)
+            provides[i] = new ProvidesEntry(cr);
+    }
+
+    public Module_attribute(int name_index,
+            RequiresEntry[] requires,
+            ExportsEntry[] exports,
+            int[] uses,
+            ProvidesEntry[] provides) {
+        super(name_index, 2);
+        requires_count = requires.length;
+        this.requires = requires;
+        exports_count = exports.length;
+        this.exports = exports;
+        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 {
+        int i = uses_index[index];
+        return constant_pool.getClassInfo(i).getName();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitModule(this, data);
+    }
+
+    public final int requires_count;
+    public final RequiresEntry[] requires;
+    public final int exports_count;
+    public final ExportsEntry[] exports;
+    public final int uses_count;
+    public final int[] uses_index;
+    public final int provides_count;
+    public final ProvidesEntry[] provides;
+
+    public static class RequiresEntry {
+        RequiresEntry(ClassReader cr) throws IOException {
+            requires_index = cr.readUnsignedShort();
+            requires_flags = cr.readUnsignedShort();
+        }
+
+        public RequiresEntry(int index, int flags) {
+            this.requires_index = index;
+            this.requires_flags = flags;
+        }
+
+        public String getRequires(ConstantPool constant_pool) throws ConstantPoolException {
+            return constant_pool.getUTF8Value(requires_index);
+        }
+
+        public static final int length = 4;
+
+        public final int requires_index;
+        public final int requires_flags;
+    }
+
+    public static class ExportsEntry {
+        ExportsEntry(ClassReader cr) throws IOException {
+            exports_index = 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) {
+            this.exports_index = index;
+            this.exports_to_count = to.length;
+            this.exports_to_index = to;
+        }
+
+        public int length() {
+            return 4 + 2 * exports_to_index.length;
+        }
+
+        public final int exports_index;
+        public final int exports_to_count;
+        public final int[] exports_to_index;
+    }
+
+    public static class ProvidesEntry {
+        ProvidesEntry(ClassReader cr) throws IOException {
+            provides_index = cr.readUnsignedShort();
+            with_index = cr.readUnsignedShort();
+        }
+
+        public ProvidesEntry(int provides, int with) {
+            this.provides_index = provides;
+            this.with_index = with;
+        }
+
+        public static final int length = 4;
+
+        public final int provides_index;
+        public final int with_index;
+    }
+}
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/TargetPlatform_attribute.java
new file mode 100644
index 0000000..ad469a5
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class TargetPlatform_attribute extends Attribute {
+    TargetPlatform_attribute(ClassReader cr, int name_index, int length) throws IOException {
+        super(name_index, length);
+        os_name_index = cr.readUnsignedShort();
+        os_arch_index = cr.readUnsignedShort();
+        os_version_index = cr.readUnsignedShort();
+    }
+
+    @Override
+    public <R, D> R accept(Visitor<R, D> visitor, D data) {
+        return visitor.visitTargetPlatform(this, data);
+    }
+
+    public final int os_name_index;
+    public final int os_arch_index;
+    public final int os_version_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/Version_attribute.java
new file mode 100644
index 0000000..ed6b749
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS, section 4.8.15.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Version_attribute extends Attribute {
+    Version_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)
+            throws ConstantPoolException {
+        this(constant_pool.getUTF8Index(Attribute.Version), version_index);
+    }
+
+    public Version_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);
+    }
+
+    public final int version_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 9bd961b..562d419 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, 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
@@ -25,16 +25,16 @@
 
 package com.sun.tools.javap;
 
-import java.util.Formatter;
-
 import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.AnnotationDefault_attribute;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.Attributes;
 import com.sun.tools.classfile.BootstrapMethods_attribute;
 import com.sun.tools.classfile.CharacterRangeTable_attribute;
+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,11 +42,15 @@
 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.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
@@ -60,6 +64,8 @@
 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.*;
 
@@ -114,6 +120,7 @@
         }
     }
 
+    @Override
     public Void visitDefault(DefaultAttribute attr, Void ignore) {
         if (attr.reason != null) {
             report(attr.reason);
@@ -150,6 +157,7 @@
         return null;
     }
 
+    @Override
     public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) {
         println("AnnotationDefault:");
         indent(+1);
@@ -159,6 +167,7 @@
         return null;
     }
 
+    @Override
     public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) {
         println(Attribute.BootstrapMethods + ":");
         for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) {
@@ -178,11 +187,11 @@
         return null;
     }
 
+    @Override
     public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) {
         println("CharacterRangeTable:");
         indent(+1);
-        for (int i = 0; i < attr.character_range_table.length; i++) {
-            CharacterRangeTable_attribute.Entry e = attr.character_range_table[i];
+        for (Entry e : attr.character_range_table) {
             print(String.format("    %2d, %2d, %6x, %6x, %4x",
                     e.start_pc, e.end_pc,
                     e.character_range_start, e.character_range_end,
@@ -216,16 +225,40 @@
         return null;
     }
 
+    @Override
     public Void visitCode(Code_attribute attr, Void ignore) {
         codeWriter.write(attr, constant_pool);
         return null;
     }
 
+    @Override
     public Void visitCompilationID(CompilationID_attribute attr, Void ignore) {
         constantWriter.write(attr.compilationID_index);
         return null;
     }
 
+    private String getJavaPackage(ConcealedPackages_attribute attr, int index) {
+        try {
+            return getJavaName(attr.getPackage(index, constant_pool));
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
+    public Void visitConcealedPackages(ConcealedPackages_attribute attr, Void ignore) {
+        println("ConcealedPackages: ");
+        indent(+1);
+        for (int i = 0; i < attr.packages_count; i++) {
+            print("#" + attr.packages_index[i]);
+            tab();
+            println("// " + getJavaPackage(attr, i));
+        }
+        indent(-1);
+        return null;
+    }
+
+    @Override
     public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) {
         print("ConstantValue: ");
         constantWriter.write(attr.constantvalue_index);
@@ -233,11 +266,13 @@
         return null;
     }
 
+    @Override
     public Void visitDeprecated(Deprecated_attribute attr, Void ignore) {
         println("Deprecated: true");
         return null;
     }
 
+    @Override
     public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) {
         print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index);
         tab();
@@ -264,6 +299,7 @@
         }
     }
 
+    @Override
     public Void visitExceptions(Exceptions_attribute attr, Void ignore) {
         println("Exceptions:");
         indent(+1);
@@ -286,10 +322,50 @@
         }
     }
 
+    @Override
+    public Void visitHashes(Hashes_attribute attr, Void ignore) {
+        println("Hashes:");
+        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);
+            tab();
+            println("// " + getRequires(e) + ": " + getHash(e));
+        }
+        indent(-1);
+        return null;
+    }
+
+    private String getAlgorithm(Hashes_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.algorithm_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getRequires(Hashes_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);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
     public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) {
         boolean first = true;
-        for (int i = 0 ; i < attr.classes.length; i++) {
-            InnerClasses_attribute.Info info = attr.classes[i];
+        for (Info info : attr.classes) {
             //access
             AccessFlags access_flags = info.inner_class_access_flags;
             if (options.checkAccess(access_flags)) {
@@ -338,6 +414,7 @@
         indent(+1);
     }
 
+    @Override
     public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) {
         println("LineNumberTable:");
         indent(+1);
@@ -348,6 +425,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) {
         println("LocalVariableTable:");
         indent(+1);
@@ -362,6 +440,7 @@
         return null;
     }
 
+    @Override
     public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) {
         println("LocalVariableTypeTable:");
         indent(+1);
@@ -376,8 +455,26 @@
         return null;
     }
 
+    @Override
+    public Void visitMainClass(MainClass_attribute attr, Void ignore) {
+        print("MainClass: #" + attr.main_class_index);
+        tab();
+        print("// " + getJavaClassName(attr));
+        println();
+        return null;
+    }
+
+    private String getJavaClassName(MainClass_attribute a) {
+        try {
+            return getJavaName(a.getMainClassName(constant_pool));
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     private static final String format = "%-31s%s";
 
+    @Override
     public Void visitMethodParameters(MethodParameters_attribute attr,
                                       Void ignore) {
 
@@ -400,6 +497,82 @@
         return null;
     }
 
+    @Override
+    public Void visitModule(Module_attribute attr, Void ignore) {
+        println("Module:");
+        indent(+1);
+        printRequiresTable(attr);
+        printExportsTable(attr);
+        printUsesTable(attr);
+        printProvidesTable(attr);
+        indent(-1);
+        return null;
+    }
+
+    protected void printRequiresTable(Module_attribute attr) {
+        Module_attribute.RequiresEntry[] entries = attr.requires;
+        println(entries.length + "\t// " + "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");
+            if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0)
+                print(" synthetic");
+            if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0)
+                print(" mandated");
+            println(" " + constantWriter.stringValue(e.requires_index));
+        }
+        indent(-1);
+    }
+
+    protected void printExportsTable(Module_attribute attr) {
+        Module_attribute.ExportsEntry[] entries = attr.exports;
+        println(entries.length + "\t// " + "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);
+            }
+        }
+        indent(-1);
+    }
+
+    protected void printUsesTable(Module_attribute attr) {
+        int[] entries = attr.uses_index;
+        println(entries.length + "\t// " + "uses services");
+        indent(+1);
+        for (int e: entries) {
+            println("#" + e + "\t// uses " + constantWriter.stringValue(e));
+        }
+        indent(-1);
+    }
+
+    protected void printProvidesTable(Module_attribute attr) {
+        Module_attribute.ProvidesEntry[] entries = attr.provides;
+        println(entries.length + "\t// " + "provides services");
+        indent(+1);
+        for (Module_attribute.ProvidesEntry e: entries) {
+            print("#" + e.provides_index + ",#" +
+                    e.with_index + "\t// provides ");
+            print(constantWriter.stringValue(e.provides_index));
+            print (" with ");
+            println(constantWriter.stringValue(e.with_index));
+        }
+        indent(-1);
+    }
+
+    @Override
     public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleAnnotations:");
         indent(+1);
@@ -412,6 +585,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleAnnotations:");
         indent(+1);
@@ -424,6 +598,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleTypeAnnotations:");
         indent(+1);
@@ -436,6 +611,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleTypeAnnotations:");
         indent(+1);
@@ -448,6 +624,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeVisibleParameterAnnotations:");
         indent(+1);
@@ -465,6 +642,7 @@
         return null;
     }
 
+    @Override
     public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) {
         println("RuntimeInvisibleParameterAnnotations:");
         indent(+1);
@@ -482,6 +660,7 @@
         return null;
     }
 
+    @Override
     public Void visitSignature(Signature_attribute attr, Void ignore) {
         print("Signature: #" + attr.signature_index);
         tab();
@@ -497,6 +676,7 @@
         }
     }
 
+    @Override
     public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) {
         println("SourceDebugExtension:");
         indent(+1);
@@ -507,6 +687,7 @@
         return null;
     }
 
+    @Override
     public Void visitSourceFile(SourceFile_attribute attr, Void ignore) {
         println("SourceFile: \"" + getSourceFile(attr) + "\"");
         return null;
@@ -520,11 +701,13 @@
         }
     }
 
+    @Override
     public Void visitSourceID(SourceID_attribute attr, Void ignore) {
         constantWriter.write(attr.sourceID_index);
         return null;
     }
 
+    @Override
     public Void visitStackMap(StackMap_attribute attr, Void ignore) {
         println("StackMap: number_of_entries = " + attr.number_of_entries);
         indent(+1);
@@ -536,6 +719,7 @@
         return null;
     }
 
+    @Override
     public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) {
         println("StackMapTable: number_of_entries = " + attr.number_of_entries);
         indent(+1);
@@ -553,11 +737,13 @@
             frame.accept(this, null);
         }
 
+        @Override
         public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) {
             printHeader(frame, "/* same */");
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) {
             printHeader(frame, "/* same_locals_1_stack_item */");
             indent(+1);
@@ -566,6 +752,7 @@
             return null;
         }
 
+        @Override
         public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) {
             printHeader(frame, "/* same_locals_1_stack_item_frame_extended */");
             indent(+1);
@@ -575,6 +762,7 @@
             return null;
         }
 
+        @Override
         public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) {
             printHeader(frame, "/* chop */");
             indent(+1);
@@ -583,6 +771,7 @@
             return null;
         }
 
+        @Override
         public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) {
             printHeader(frame, "/* same_frame_extended */");
             indent(+1);
@@ -591,6 +780,7 @@
             return null;
         }
 
+        @Override
         public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) {
             printHeader(frame, "/* append */");
             indent(+1);
@@ -600,6 +790,7 @@
             return null;
         }
 
+        @Override
         public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) {
             if (frame instanceof StackMap_attribute.stack_map_frame) {
                 printHeader(frame, "offset = " + frame.offset_delta);
@@ -678,11 +869,80 @@
         }
     }
 
+    @Override
     public Void visitSynthetic(Synthetic_attribute attr, Void ignore) {
         println("Synthetic: true");
         return null;
     }
 
+    @Override
+    public Void visitTargetPlatform(TargetPlatform_attribute attr, Void ignore) {
+        println("TargetPlatform:");
+        indent(+1);
+        print("os_name: #" + attr.os_name_index);
+        if (attr.os_name_index != 0) {
+            tab();
+            print("// " + getOSName(attr));
+        }
+        println();
+        print("os_arch: #" + attr.os_arch_index);
+        if (attr.os_arch_index != 0) {
+            tab();
+            print("// " + getOSArch(attr));
+        }
+        println();
+        print("os_version: #" + attr.os_version_index);
+        if (attr.os_version_index != 0) {
+            tab();
+            print("// " + getOSVersion(attr));
+        }
+        println();
+        indent(-1);
+        return null;
+    }
+
+    private String getOSName(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_name_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getOSArch(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_arch_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    private String getOSVersion(TargetPlatform_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.os_version_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    @Override
+    public Void visitVersion(Version_attribute attr, Void ignore) {
+        print("Version: #" + attr.version_index);
+        indent(+1);
+        tab();
+        println("// " + getVersion(attr));
+        indent(-1);
+        return null;
+    }
+
+    private String getVersion(Version_attribute attr) {
+        try {
+            return constant_pool.getUTF8Value(attr.version_index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     static String getJavaName(String name) {
         return name.replace('/', '.');
     }
@@ -702,10 +962,10 @@
         return StringUtils.toUpperCase(s);
     }
 
-    private AnnotationWriter annotationWriter;
-    private CodeWriter codeWriter;
-    private ConstantWriter constantWriter;
-    private Options options;
+    private final AnnotationWriter annotationWriter;
+    private final CodeWriter codeWriter;
+    private final ConstantWriter constantWriter;
+    private final Options options;
 
     private ConstantPool constant_pool;
     private Object owner;
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 a483775..1df09a1 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, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -44,6 +44,7 @@
 import com.sun.tools.classfile.Exceptions_attribute;
 import com.sun.tools.classfile.Field;
 import com.sun.tools.classfile.Method;
+import com.sun.tools.classfile.Module_attribute;
 import com.sun.tools.classfile.Signature;
 import com.sun.tools.classfile.Signature_attribute;
 import com.sun.tools.classfile.SourceFile_attribute;
@@ -161,12 +162,17 @@
 
         writeModifiers(flags.getClassModifiers());
 
-        if (classFile.isClass())
-            print("class ");
-        else if (classFile.isInterface())
-            print("interface ");
+        if (classFile.access_flags.is(AccessFlags.ACC_MODULE) && name.endsWith(".module-info")) {
+            print("module ");
+            print(name.replace(".module-info", ""));
+        } else {
+            if (classFile.isClass())
+                print("class ");
+            else if (classFile.isInterface())
+                print("interface ");
 
-        print(name);
+            print(name);
+        }
 
         Signature_attribute sigAttr = getSignature(cf.attributes);
         if (sigAttr == null) {
@@ -213,6 +219,9 @@
 
         println("{");
         indent(+1);
+        if (flags.is(AccessFlags.ACC_MODULE) && !options.verbose) {
+            writeDirectives();
+        }
         writeFields();
         writeMethods();
         indent(-1);
@@ -538,6 +547,79 @@
         }
     }
 
+    void writeDirectives() {
+        Attribute attr = classFile.attributes.get(Attribute.Module);
+        if (!(attr instanceof Module_attribute))
+            return;
+
+        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");
+            print(" ");
+            print(getUTF8Value(entry.requires_index).replace('/', '.'));
+            println(";");
+        }
+
+        for (Module_attribute.ExportsEntry entry: m.exports) {
+            print("exports ");
+            print(getUTF8Value(entry.exports_index).replace('/', '.'));
+            boolean first = true;
+            for (int i: entry.exports_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('/', '.'));
+            println(";");
+        }
+
+        for (Module_attribute.ProvidesEntry entry: m.provides) {
+            print("provides ");
+            print(getClassName(entry.provides_index).replace('/', '.'));
+            println(" with");
+            indent(+1);
+            print(getClassName(entry.with_index).replace('/', '.'));
+            println(";");
+            indent(-1);
+        }
+    }
+
+    String getUTF8Value(int index) {
+        try {
+            return classFile.constant_pool.getUTF8Value(index);
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
+    String getClassName(int index) {
+        try {
+            return classFile.constant_pool.getClassInfo(index).getName();
+        } catch (ConstantPoolException e) {
+            return report(e);
+        }
+    }
+
     void writeList(String prefix, Collection<?> items, String suffix) {
         print(prefix);
         String sep = "";
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
index 0cfa5d0..c63caa2 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, 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
@@ -55,12 +55,14 @@
 import java.util.MissingResourceException;
 import java.util.Objects;
 import java.util.ResourceBundle;
+import java.util.Set;
 
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
 import javax.tools.Diagnostic;
 import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
@@ -301,6 +303,13 @@
                 } catch (NumberFormatException e) {
                 }
             }
+        },
+
+        new Option(true, "-m") {
+            @Override
+            void process(JavapTask task, String opt, String arg) throws BadArgs {
+                task.options.moduleName = arg;
+            }
         }
 
     };
@@ -558,6 +567,19 @@
         SourceWriter sourceWriter = SourceWriter.instance(context);
         sourceWriter.setFileManager(fileManager);
 
+        if (options.moduleName != null) {
+            try {
+                moduleLocation = findModule(options.moduleName);
+                if (moduleLocation == null) {
+                    reportError("err.cant.find.module", options.moduleName);
+                    return EXIT_ERROR;
+                }
+            } catch (IOException e) {
+                reportError("err.cant.find.module.ex", options.moduleName, e);
+                return EXIT_ERROR;
+            }
+        }
+
         int result = EXIT_OK;
 
         for (String className: classes) {
@@ -866,15 +888,44 @@
     private JavaFileObject getClassFileObject(String className) throws IOException {
         try {
             JavaFileObject fo;
-            fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
-            if (fo == null)
-                fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+            if (moduleLocation != null) {
+                fo = fileManager.getJavaFileForInput(moduleLocation, className, JavaFileObject.Kind.CLASS);
+            } else {
+                fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+                if (fo == null)
+                    fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
+            }
             return fo;
         } catch (IllegalArgumentException e) {
             return null;
         }
     }
 
+    private Location findModule(String moduleName) throws IOException {
+        Location[] locns = {
+            StandardLocation.UPGRADE_MODULE_PATH,
+            StandardLocation.SYSTEM_MODULES,
+            StandardLocation.MODULE_PATH
+        };
+        for (Location segment: locns) {
+            for (Set<Location> set: fileManager.listModuleLocations(segment)) {
+                Location result = null;
+                for (Location l: set) {
+                    String name = fileManager.inferModuleName(l);
+                    if (name.equals(moduleName)) {
+                        if (result == null)
+                            result = l;
+                        else
+                            throw new IOException("multiple definitions found for " + moduleName);
+                    }
+                }
+                if (result != null)
+                    return result;
+            }
+        }
+        return null;
+    }
+
     private void showHelp() {
         printLines(getMessage("main.usage", progname));
         for (Option o: recognizedOptions) {
@@ -883,7 +934,9 @@
                 continue;
             printLines(getMessage("main.opt." + name));
         }
-        String[] fmOptions = { "-classpath", "-cp", "-bootclasspath" };
+        String[] fmOptions = {
+            "-classpath", "-cp", "-bootclasspath",
+            "-upgrademodulepath", "-system", "-modulepath" };
         for (String o: fmOptions) {
             if (fileManager.isSupportedOption(o) == -1)
                 continue;
@@ -1031,6 +1084,7 @@
     PrintWriter log;
     DiagnosticListener<? super JavaFileObject> diagnosticListener;
     List<String> classes;
+    Location moduleLocation;
     Options options;
     //ResourceBundle bundle;
     Locale task_locale;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
index 3723fc3..3a31155 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -88,4 +88,5 @@
     public boolean showInnerClasses;
     public int indentWidth = 2;   // #spaces per indentWidth level; must be > 0
     public int tabColumn = 40;    // column number for comments; must be > 0
+    public String moduleName;
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
index ec87869..fb8d19b 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties
@@ -19,6 +19,8 @@
 err.source.file.not.found=source file not found
 err.bad.innerclasses.attribute=bad InnerClasses attribute for {0}
 err.nomem=Insufficient memory. To increase memory use -J-Xmx option.
+err.cant.find.module=Cannot find module {0}
+err.cant.find.module.ex=Problem finding module {0}: {1}
 
 main.usage.summary=\
 Usage: {0} <options> <classes>\n\
@@ -78,6 +80,15 @@
 main.opt.bootclasspath=\
 \  -bootclasspath <path>    Override location of bootstrap class files
 
+main.opt.upgrademodulepath=\
+\  -upgrademodulepath <path>    Specify where to find upgradeable modules
+
+main.opt.system=\
+\  -system <jdk>            Specify where to find system modules
+
+main.opt.modulepath=\
+\  -modulepath <path>       Specify where to find application modules
+
 main.opt.constants=\
 \  -constants               Show final constants
 
@@ -85,3 +96,6 @@
 main.opt.sysinfo=\
 \  -sysinfo                 Show system info (path, size, date, MD5 hash)\n\
 \                           of class being processed
+
+main.opt.m=\
+\  -m <module-name>         Specify module containing classes to be disassembled
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
index 88ee11b..1228622 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java
@@ -26,9 +26,13 @@
 package com.sun.tools.jdeps;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -63,9 +67,9 @@
 
     protected final Type type;
     protected final Filter filter;
-    protected final Map<Archive, ArchiveDeps> results = new HashMap<>();
-    protected final Map<Location, Archive> map = new HashMap<>();
-    private static final Archive NOT_FOUND
+    protected final Map<Archive, Dependences> results = new HashMap<>();
+    protected final Map<Location, Archive> locationToArchive = new HashMap<>();
+    static final Archive NOT_FOUND
         = new Archive(JdepsTask.getMessage("artifact.not.found"));
 
     /**
@@ -82,29 +86,31 @@
     /**
      * Performs the dependency analysis on the given archives.
      */
-    public boolean run(List<Archive> archives) {
+    public boolean run(Stream<? extends Archive> archives) {
+        return run(archives.collect(Collectors.toList()));
+    }
+
+    /**
+     * Performs the dependency analysis on the given archives.
+     */
+    public boolean run(Iterable<? extends Archive> archives) {
         // build a map from Location to Archive
         buildLocationArchiveMap(archives);
 
         // traverse and analyze all dependencies
         for (Archive archive : archives) {
-            ArchiveDeps deps = new ArchiveDeps(archive, type);
+            Dependences deps = new Dependences(archive, type);
             archive.visitDependences(deps);
             results.put(archive, deps);
         }
         return true;
     }
 
-    protected void buildLocationArchiveMap(List<Archive> archives) {
+    protected void buildLocationArchiveMap(Iterable<? extends Archive> archives) {
         // build a map from Location to Archive
         for (Archive archive: archives) {
-            for (Location l: archive.getClasses()) {
-                if (!map.containsKey(l)) {
-                    map.put(l, archive);
-                } else {
-                    // duplicated class warning?
-                }
-            }
+            archive.getClasses()
+                   .forEach(l -> locationToArchive.putIfAbsent(l, archive));
         }
     }
 
@@ -116,12 +122,23 @@
     }
 
     public Set<String> dependences(Archive source) {
-        ArchiveDeps result = results.get(source);
+        if (!results.containsKey(source)) {
+            return Collections.emptySet();
+        }
+        Dependences result = results.get(source);
         return result.dependencies().stream()
                      .map(Dep::target)
                      .collect(Collectors.toSet());
     }
 
+    public Stream<Archive> requires(Archive source) {
+        if (!results.containsKey(source)) {
+            return Stream.empty();
+        }
+        Dependences result = results.get(source);
+        return result.requires().stream().filter(a -> !a.isEmpty());
+    }
+
     public interface Visitor {
         /**
          * Visits a recorded dependency from origin to target which can be
@@ -138,7 +155,7 @@
      */
     public void visitDependences(Archive source, Visitor v, Type level) {
         if (level == Type.SUMMARY) {
-            final ArchiveDeps result = results.get(source);
+            final Dependences result = results.get(source);
             final Set<Archive> reqs = result.requires();
             Stream<Archive> stream = reqs.stream();
             if (reqs.isEmpty()) {
@@ -152,19 +169,21 @@
                   .forEach(archive -> {
                       Profile profile = result.getTargetProfile(archive);
                       v.visitDependence(source.getName(), source,
-                                        profile != null ? profile.profileName() : archive.getName(), archive);
+                                        profile != null ? profile.profileName()
+                                                        : archive.getName(), archive);
                   });
         } else {
-            ArchiveDeps result = results.get(source);
+            Dependences result = results.get(source);
             if (level != type) {
                 // requesting different level of analysis
-                result = new ArchiveDeps(source, level);
+                result = new Dependences(source, level);
                 source.visitDependences(result);
             }
             result.dependencies().stream()
                   .sorted(Comparator.comparing(Dep::origin)
                                     .thenComparing(Dep::target))
-                  .forEach(d -> v.visitDependence(d.origin(), d.originArchive(), d.target(), d.targetArchive()));
+                  .forEach(d -> v.visitDependence(d.origin(), d.originArchive(),
+                                                  d.target(), d.targetArchive()));
         }
     }
 
@@ -173,16 +192,16 @@
     }
 
     /**
-     * ArchiveDeps contains the dependencies for an Archive that can have one or
+     * Dependences contains the dependencies for an Archive that can have one or
      * more classes.
      */
-    class ArchiveDeps implements Archive.Visitor {
+    class Dependences implements Archive.Visitor {
         protected final Archive archive;
         protected final Set<Archive> requires;
         protected final Set<Dep> deps;
         protected final Type level;
         private Profile profile;
-        ArchiveDeps(Archive archive, Type level) {
+        Dependences(Archive archive, Type level) {
             this.archive = archive;
             this.deps = new HashSet<>();
             this.requires = new HashSet<>();
@@ -198,7 +217,7 @@
         }
 
         Profile getTargetProfile(Archive target) {
-            if (target instanceof Module) {
+            if (target.getModule().isJDK()) {
                 return Profile.getProfile((Module) target);
             } else {
                 return null;
@@ -206,11 +225,10 @@
         }
 
         Archive findArchive(Location t) {
-            Archive target = archive.getClasses().contains(t) ? archive : map.get(t);
-            if (target == null) {
-                map.put(t, target = NOT_FOUND);
-            }
-            return target;
+            if (archive.getClasses().contains(t))
+                return archive;
+
+            return locationToArchive.computeIfAbsent(t, _k -> NOT_FOUND);
         }
 
         // return classname or package name depedning on the level
@@ -232,7 +250,7 @@
                     requires.add(targetArchive);
                 }
             }
-            if (targetArchive instanceof Module) {
+            if (targetArchive.getModule().isNamed()) {
                 Profile p = Profile.getProfile(t.getPackageName());
                 if (profile == null || (p != null && p.compareTo(profile) > 0)) {
                     profile = p;
@@ -315,12 +333,10 @@
 
         @Override
         public int hashCode() {
-            int hash = 7;
-            hash = 67*hash + Objects.hashCode(this.origin)
-                           + Objects.hashCode(this.originArchive)
-                           + Objects.hashCode(this.target)
-                           + Objects.hashCode(this.targetArchive);
-            return hash;
+            return Objects.hash(this.origin,
+                                this.originArchive,
+                                this.target,
+                                this.targetArchive);
         }
 
         public String toString() {
@@ -329,124 +345,4 @@
                     target, targetArchive.getName());
         }
     }
-
-    static Analyzer getExportedAPIsAnalyzer() {
-        return new ModuleAccessAnalyzer(ModuleAccessAnalyzer.reexportsFilter, true);
-    }
-
-    static Analyzer getModuleAccessAnalyzer() {
-        return new ModuleAccessAnalyzer(ModuleAccessAnalyzer.accessCheckFilter, false);
-    }
-
-    private static class ModuleAccessAnalyzer extends Analyzer {
-        private final boolean apionly;
-        ModuleAccessAnalyzer(Filter filter, boolean apionly) {
-            super(Type.VERBOSE, filter);
-            this.apionly = apionly;
-        }
-        /**
-         * Verify module access
-         */
-        public boolean run(List<Archive> archives) {
-            // build a map from Location to Archive
-            buildLocationArchiveMap(archives);
-
-            // traverse and analyze all dependencies
-            int count = 0;
-            for (Archive archive : archives) {
-                ArchiveDeps checker = new ArchiveDeps(archive, type);
-                archive.visitDependences(checker);
-                count += checker.dependencies().size();
-                // output if any error
-                Module m = (Module)archive;
-                printDependences(System.err, m, checker.dependencies());
-                results.put(archive, checker);
-            }
-            return count == 0;
-        }
-
-        private void printDependences(PrintStream out, Module m, Set<Dep> deps) {
-            if (deps.isEmpty())
-                return;
-
-            String msg = apionly ? "API reference:" : "inaccessible reference:";
-            deps.stream().sorted(Comparator.comparing(Dep::origin)
-                                           .thenComparing(Dep::target))
-                .forEach(d -> out.format("%s %s (%s) -> %s (%s)%n", msg,
-                                         d.origin(), d.originArchive().getName(),
-                                         d.target(), d.targetArchive().getName()));
-            if (apionly) {
-                out.format("Dependences missing re-exports=\"true\" attribute:%n");
-                deps.stream()
-                        .map(Dep::targetArchive)
-                        .map(Archive::getName)
-                        .distinct()
-                        .sorted()
-                        .forEach(d -> out.format("  %s -> %s%n", m.name(), d));
-            }
-        }
-
-        private static Module findModule(Archive archive) {
-            if (Module.class.isInstance(archive)) {
-                return (Module) archive;
-            } else {
-                return null;
-            }
-        }
-
-        // returns true if target is accessible by origin
-        private static boolean canAccess(Location o, Archive originArchive, Location t, Archive targetArchive) {
-            Module origin = findModule(originArchive);
-            Module target = findModule(targetArchive);
-
-            if (targetArchive == Analyzer.NOT_FOUND) {
-                return false;
-            }
-
-            // unnamed module
-            // ## should check public type?
-            if (target == null)
-                return true;
-
-            // module-private
-            if (origin == target)
-                return true;
-
-            return target.isAccessibleTo(t.getClassName(), origin);
-        }
-
-        static final Filter accessCheckFilter = new Filter() {
-            @Override
-            public boolean accepts(Location o, Archive originArchive, Location t, Archive targetArchive) {
-                return !canAccess(o, originArchive, t, targetArchive);
-            }
-        };
-
-        static final Filter reexportsFilter = new Filter() {
-            @Override
-            public boolean accepts(Location o, Archive originArchive, Location t, Archive targetArchive) {
-                Module origin = findModule(originArchive);
-                Module target = findModule(targetArchive);
-                if (!origin.isExportedPackage(o.getPackageName())) {
-                    // filter non-exported classes
-                    return false;
-                }
-
-                boolean accessible = canAccess(o, originArchive, t, targetArchive);
-                if (!accessible)
-                    return true;
-
-                String mn = target.name();
-                // skip checking re-exports for java.base
-                if (origin == target || "java.base".equals(mn))
-                    return false;
-
-                assert origin.requires().containsKey(mn);  // otherwise, should not be accessible
-                if (origin.requires().get(mn)) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
index e6a18f5..90e4890 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java
@@ -25,14 +25,17 @@
 
 package com.sun.tools.jdeps;
 
-import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.Dependency.Location;
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.net.URI;
+import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -48,20 +51,24 @@
         }
     }
 
+    private final URI location;
     private final Path path;
     private final String filename;
     private final ClassFileReader reader;
+
     protected Map<Location, Set<Location>> deps = new ConcurrentHashMap<>();
 
     protected Archive(String name) {
-        this(name, null);
+        this(name, null, null);
     }
-    protected Archive(String name, ClassFileReader reader) {
-        this.path = null;
+    protected Archive(String name, URI location, ClassFileReader reader) {
+        this.location = location;
+        this.path = location != null ? Paths.get(location) : null;
         this.filename = name;
         this.reader = reader;
     }
     protected Archive(Path p, ClassFileReader reader) {
+        this.location = null;
         this.path = p;
         this.filename = path.getFileName().toString();
         this.reader = reader;
@@ -75,6 +82,10 @@
         return filename;
     }
 
+    public Module getModule() {
+        return Module.UNNAMED_MODULE;
+    }
+
     public void addClass(Location origin) {
         deps.computeIfAbsent(origin, _k -> new HashSet<>());
     }
@@ -95,6 +106,9 @@
         }
     }
 
+    /**
+     * Tests if any class has been parsed.
+     */
     public boolean isEmpty() {
         return getClasses().isEmpty();
     }
@@ -103,6 +117,22 @@
         return path != null ? path.toString() : filename;
     }
 
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.filename, this.path);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof Archive) {
+            Archive other = (Archive)o;
+            if (path == other.path || isSameLocation(this, other))
+                return true;
+        }
+        return false;
+    }
+
+    @Override
     public String toString() {
         return filename;
     }
@@ -111,6 +141,29 @@
         return path;
     }
 
+    public static boolean isSameLocation(Archive archive, Archive other) {
+        if (archive.path == null || other.path == null)
+            return false;
+
+        if (archive.location != null && other.location != null &&
+                archive.location.equals(other.location)) {
+            return true;
+        }
+
+        if (archive.isJrt() || other.isJrt()) {
+            return false;
+        }
+
+        try {
+            return Files.isSameFile(archive.path, other.path);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private boolean isJrt() {
+        return location != null && location.getScheme().equals("jrt");
+    }
     interface Visitor {
         void visit(Location origin, Location target);
     }
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 f849b32..aa2e6ff 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
@@ -28,22 +28,26 @@
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Dependencies.ClassFileError;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
-import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * ClassFileReader reads ClassFile(s) of a given path that can be
@@ -74,8 +78,19 @@
         return new JarFileReader(path, jf);
     }
 
+    /**
+     * Returns a ClassFileReader instance of a given FileSystem and path.
+     *
+     * This method is used for reading classes from jrtfs.
+     */
+    public static ClassFileReader newInstance(FileSystem fs, Path path) throws IOException {
+        return new DirectoryReader(fs, path);
+    }
+
     protected final Path path;
     protected final String baseFileName;
+    protected Set<String> entries; // binary names
+
     protected final List<String> skippedEntries = new ArrayList<>();
     protected ClassFileReader(Path path) {
         this.path = path;
@@ -93,6 +108,18 @@
     }
 
     /**
+     * Returns all entries in this archive.
+     */
+    public Set<String> entries() {
+        Set<String> es = this.entries;
+        if (es == null) {
+            // lazily scan the entries
+            this.entries = scan();
+        }
+        return this.entries;
+    }
+
+    /**
      * Returns the ClassFile matching the given binary name
      * or a fully-qualified class name.
      */
@@ -135,6 +162,20 @@
         }
     }
 
+    protected Set<String> scan() {
+        try {
+            ClassFile cf = ClassFile.read(path);
+            return Collections.singleton(cf.getName());
+        } catch (ConstantPoolException|IOException e) {
+            throw new ClassFileError(e);
+        }
+    }
+
+    static boolean isClass(Path file) {
+        String fn = file.getFileName().toString();
+        return fn.endsWith(".class") && !fn.equals(MODULE_INFO);
+    }
+
     class FileIterator implements Iterator<ClassFile> {
         int count;
         FileIterator() {
@@ -176,6 +217,19 @@
             this.fsSep = fs.getSeparator();
         }
 
+        protected Set<String> scan() {
+            try {
+                return Files.walk(path, Integer.MAX_VALUE)
+                        .filter(ClassFileReader::isClass)
+                        .map(f -> path.relativize(f))
+                        .map(Path::toString)
+                        .map(p -> p.replace(File.separatorChar, '/'))
+                        .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
         public ClassFile getClassFile(String name) throws IOException {
             if (name.indexOf('.') > 0) {
                 int i = name.lastIndexOf('.');
@@ -206,28 +260,13 @@
             };
         }
 
-        private List<Path> entries;
-        protected synchronized List<Path> walkTree() throws IOException {
-            if (entries == null) {
-                entries = new ArrayList<>();
-                Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
-                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-                            throws IOException {
-                        if (file.getFileName().toString().endsWith(".class")) {
-                            entries.add(file);
-                        }
-                        return FileVisitResult.CONTINUE;
-                    }
-                });
-            }
-            return entries;
-        }
-
         class DirectoryIterator implements Iterator<ClassFile> {
             private List<Path> entries;
             private int index = 0;
             DirectoryIterator() throws IOException {
-                entries = walkTree();
+                entries = Files.walk(path, Integer.MAX_VALUE)
+                               .filter(ClassFileReader::isClass)
+                               .collect(Collectors.toList());
                 index = 0;
             }
 
@@ -264,6 +303,16 @@
             this.jarfile = jf;
         }
 
+        protected Set<String> scan() {
+            try (JarFile jf = new JarFile(path.toFile())) {
+                return jf.stream().map(JarEntry::getName)
+                         .filter(n -> n.endsWith(".class") && !n.endsWith(MODULE_INFO))
+                         .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
         public ClassFile getClassFile(String name) throws IOException {
             if (name.indexOf('.') > 0) {
                 int i = name.lastIndexOf('.');
@@ -360,7 +409,7 @@
             while (entries.hasMoreElements()) {
                 JarEntry e = entries.nextElement();
                 String name = e.getName();
-                if (name.endsWith(".class")) {
+                if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
                     return e;
                 }
             }
@@ -371,29 +420,5 @@
             throw new UnsupportedOperationException("Not supported yet.");
         }
     }
-
-    /**
-     * ClassFileReader for modules.
-     */
-    static class ModuleClassReader extends DirectoryReader {
-        final String modulename;
-        ModuleClassReader(FileSystem fs, String mn, Path root) throws IOException {
-            super(fs, root);
-            this.modulename = mn;
-        }
-
-        public Set<String> packages() throws IOException {
-            return walkTree().stream()
-                             .map(this::toPackageName)
-                             .sorted()
-                             .collect(Collectors.toSet());
-        }
-
-        String toPackageName(Path p) {
-            if (p.getParent() == null) {
-                return "";
-            }
-            return path.relativize(p.getParent()).toString().replace(fsSep, ".");
-        }
-    }
+    private static final String MODULE_INFO = "module-info.class";
 }
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
new file mode 100644
index 0000000..086e13a
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package 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;
+import com.sun.tools.classfile.Dependency;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.sun.tools.jdeps.Module.*;
+import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
+
+public class DependencyFinder {
+    private final List<Archive> roots = new ArrayList<>();
+    private final List<Archive> classpaths = new ArrayList<>();
+    private final List<Module> modulepaths = new ArrayList<>();
+    private final List<String> classes = new ArrayList<>();
+    private final boolean compileTimeView;
+
+    DependencyFinder(boolean compileTimeView) {
+        this.compileTimeView = compileTimeView;
+    }
+
+    /*
+     * Adds a class name to the root set
+     */
+    void addClassName(String cn) {
+        classes.add(cn);
+    }
+
+    /*
+     * Adds the archive of the given path to the root set
+     */
+    void addRoot(Path path) {
+        addRoot(Archive.getInstance(path));
+    }
+
+    /*
+     * Adds the given archive to the root set
+     */
+    void addRoot(Archive archive) {
+        Objects.requireNonNull(archive);
+        if (!roots.contains(archive))
+            roots.add(archive);
+    }
+
+    /**
+     * Add an archive specified in the classpath.
+     */
+    void addClassPathArchive(Path path) {
+        addClassPathArchive(Archive.getInstance(path));
+    }
+
+    /**
+     * Add an archive specified in the classpath.
+     */
+    void addClassPathArchive(Archive archive) {
+        Objects.requireNonNull(archive);
+        classpaths.add(archive);
+    }
+
+    /**
+     * Add an archive specified in the modulepath.
+     */
+    void addModule(Module m) {
+        Objects.requireNonNull(m);
+        modulepaths.add(m);
+    }
+
+    /**
+     * Returns the root set.
+     */
+    List<Archive> roots() {
+        return roots;
+    }
+
+    /**
+     * Returns a stream of all archives including the root set, module paths,
+     * and classpath.
+     *
+     * This only returns the archives with classes parsed.
+     */
+    Stream<Archive> archives() {
+        Stream<Archive> archives = Stream.concat(roots.stream(), modulepaths.stream());
+        archives = Stream.concat(archives, classpaths.stream());
+        return archives.filter(a -> !a.isEmpty())
+                       .distinct();
+    }
+
+    /**
+     * Finds dependencies
+     *
+     * @param apiOnly  API only
+     * @param maxDepth depth of transitive dependency analysis; zero indicates
+     * @throws IOException
+     */
+    void findDependencies(JdepsFilter filter, boolean apiOnly, int maxDepth)
+            throws IOException
+    {
+        Dependency.Finder finder =
+                apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
+                        : Dependencies.getClassDependencyFinder();
+
+        // list of archives to be analyzed
+        Set<Archive> roots = new LinkedHashSet<>(this.roots);
+
+        // include java.base in root set
+        roots.add(JAVA_BASE);
+
+        // If -include pattern specified, classes may be in module path or class path.
+        // To get compile time view analysis, all classes are analyzed.
+        // add all modules except JDK modules to root set
+        modulepaths.stream()
+                   .filter(filter::matches)
+                   .forEach(roots::add);
+
+        // add classpath to the root set
+        classpaths.stream()
+                .filter(filter::matches)
+                .forEach(roots::add);
+
+        // transitive dependency
+        int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE;
+
+        // Work queue of names of classfiles to be searched.
+        // Entries will be unique, and for classes that do not yet have
+        // dependencies in the results map.
+        ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>();
+        ConcurrentSkipListSet<String> doneClasses = new ConcurrentSkipListSet<>();
+
+        TaskExecutor executor = new TaskExecutor(finder, filter, apiOnly, deque, doneClasses);
+        try {
+            // get the immediate dependencies of the input files
+            for (Archive source : roots) {
+                executor.task(source, deque);
+            }
+            executor.waitForTasksCompleted();
+
+            List<Archive> archives = Stream.concat(Stream.concat(roots.stream(),
+                    modulepaths.stream()),
+                    classpaths.stream())
+                    .collect(Collectors.toList());
+
+            // Additional pass to find archive where dependences are identified
+            // and also any specified classes, if any.
+            // If -R is specified, perform transitive dependency analysis.
+            Deque<String> unresolved = new LinkedList<>(classes);
+            do {
+                String name;
+                while ((name = unresolved.poll()) != null) {
+                    if (doneClasses.contains(name)) {
+                        continue;
+                    }
+                    if (compileTimeView) {
+                        final String cn = name + ".class";
+                        // parse all classes in the source archive
+                        Optional<Archive> source = archives.stream()
+                                .filter(a -> a.reader().entries().contains(cn))
+                                .findFirst();
+                        trace("%s compile time view %s%n", name, source.map(Archive::getName).orElse(" not found"));
+                        if (source.isPresent()) {
+                            executor.runTask(source.get(), deque);
+                        }
+                    }
+                    ClassFile cf = null;
+                    for (Archive archive : archives) {
+                        cf = archive.reader().getClassFile(name);
+
+                        if (cf != null) {
+                            String classFileName;
+                            try {
+                                classFileName = cf.getName();
+                            } catch (ConstantPoolException e) {
+                                throw new Dependencies.ClassFileError(e);
+                            }
+                            if (!doneClasses.contains(classFileName)) {
+                                // if name is a fully-qualified class name specified
+                                // from command-line, this class might already be parsed
+                                doneClasses.add(classFileName);
+                                for (Dependency d : finder.findDependencies(cf)) {
+                                    if (depth == 0) {
+                                        // ignore the dependency
+                                        archive.addClass(d.getOrigin());
+                                        break;
+                                    } else if (filter.accepts(d) && filter.accept(archive)) {
+                                        // continue analysis on non-JDK classes
+                                        archive.addClass(d.getOrigin(), d.getTarget());
+                                        String cn = d.getTarget().getName();
+                                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
+                                            deque.add(cn);
+                                        }
+                                    } else {
+                                        // ensure that the parsed class is added the archive
+                                        archive.addClass(d.getOrigin());
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    if (cf == null) {
+                        doneClasses.add(name);
+                    }
+                }
+                unresolved = deque;
+                deque = new ConcurrentLinkedDeque<>();
+            } while (!unresolved.isEmpty() && depth-- > 0);
+        } finally {
+            executor.shutdown();
+        }
+     }
+
+    /**
+     * TaskExecutor creates FutureTask to analyze all classes in a given archive
+     */
+    private class TaskExecutor {
+        final ExecutorService pool;
+        final Dependency.Finder finder;
+        final JdepsFilter filter;
+        final boolean apiOnly;
+        final Set<String> doneClasses;
+        final Map<Archive, FutureTask<Void>> tasks = new HashMap<>();
+
+        TaskExecutor(Dependency.Finder finder,
+                     JdepsFilter filter,
+                     boolean apiOnly,
+                     ConcurrentLinkedDeque<String> deque,
+                     Set<String> doneClasses) {
+            this.pool = Executors.newFixedThreadPool(2);
+            this.finder = finder;
+            this.filter = filter;
+            this.apiOnly = apiOnly;
+            this.doneClasses = doneClasses;
+        }
+
+        /**
+         * Creates a new task to analyze class files in the given archive.
+         * The dependences are added to the given deque for analysis.
+         */
+        FutureTask<Void> task(Archive archive, final ConcurrentLinkedDeque<String> deque) {
+            trace("parsing %s %s%n", archive.getName(), archive.path());
+            FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
+                public Void call() throws Exception {
+                    for (ClassFile cf : archive.reader().getClassFiles()) {
+                        String classFileName;
+                        try {
+                            classFileName = cf.getName();
+                        } catch (ConstantPoolException e) {
+                            throw new Dependencies.ClassFileError(e);
+                        }
+
+                        // tests if this class matches the -include
+                        String cn = classFileName.replace('/', '.');
+                        if (!filter.matches(cn))
+                            continue;
+
+                        // if -apionly is specified, analyze only exported and public types
+                        if (apiOnly && !(isExported(archive, cn) && cf.access_flags.is(AccessFlags.ACC_PUBLIC)))
+                            continue;
+
+                        if (!doneClasses.contains(classFileName)) {
+                            doneClasses.add(classFileName);
+                        }
+
+                        for (Dependency d : finder.findDependencies(cf)) {
+                            if (filter.accepts(d) && filter.accept(archive)) {
+                                String name = d.getTarget().getName();
+                                if (!doneClasses.contains(name) && !deque.contains(name)) {
+                                    deque.add(name);
+                                }
+                                archive.addClass(d.getOrigin(), d.getTarget());
+                            } else {
+                                // ensure that the parsed class is added the archive
+                                archive.addClass(d.getOrigin());
+                            }
+                        }
+                    }
+                    return null;
+                }
+            });
+            tasks.put(archive, task);
+            pool.submit(task);
+            return task;
+        }
+
+        /*
+         * This task will parse all class files of the given archive, if it's a new task.
+         * This method waits until the task is completed.
+         */
+        void runTask(Archive archive, final ConcurrentLinkedDeque<String> deque) {
+            if (tasks.containsKey(archive))
+                return;
+
+            FutureTask<Void> task = task(archive, deque);
+            try {
+                // wait for completion
+                task.get();
+            } catch (InterruptedException|ExecutionException e) {
+                throw new Error(e);
+            }
+        }
+
+        /*
+         * Waits until all submitted tasks are completed.
+         */
+        void waitForTasksCompleted() {
+            try {
+                for (FutureTask<Void> t : tasks.values()) {
+                    if (t.isDone())
+                        continue;
+
+                    // wait for completion
+                    t.get();
+                }
+            } catch (InterruptedException|ExecutionException e) {
+                throw new Error(e);
+            }
+        }
+
+        /*
+         * Shutdown the executor service.
+         */
+        void shutdown() {
+            pool.shutdown();
+        }
+
+        /**
+         * Tests if the given class name is exported by the given archive.
+         *
+         * All packages are exported in unnamed module.
+         */
+        private boolean isExported(Archive archive, String classname) {
+            int i = classname.lastIndexOf('.');
+            String pn = i > 0 ? classname.substring(0, i) : "";
+            return archive.getModule().isExported(pn);
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java
new file mode 100644
index 0000000..84b04e2
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.Dependencies;
+import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
+
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/*
+ * Filter configured based on the input jdeps option
+ * 1. -p and -regex to match target dependencies
+ * 2. -filter:package to filter out same-package dependencies
+ *    This filter is applied when jdeps parses the class files
+ *    and filtered dependencies are not stored in the Analyzer.
+ * 3. -module specifies to match target dependencies from the given module
+ *    This gets expanded into package lists to be filtered.
+ * 4. -filter:archive to filter out same-archive dependencies
+ *    This filter is applied later in the Analyzer as the
+ *    containing archive of a target class may not be known until
+ *    the entire archive
+ */
+class JdepsFilter implements Dependency.Filter, Analyzer.Filter {
+    private final Dependency.Filter filter;
+    private final Pattern filterPattern;
+    private final boolean filterSamePackage;
+    private final boolean filterSameArchive;
+    private final boolean findJDKInternals;
+    private final Pattern includePattern;
+    private final Set<String> includePackages;
+    private final Set<String> excludeModules;
+
+    private JdepsFilter(Dependency.Filter filter,
+                        Pattern filterPattern,
+                        boolean filterSamePackage,
+                        boolean filterSameArchive,
+                        boolean findJDKInternals,
+                        Pattern includePattern,
+                        Set<String> includePackages,
+                        Set<String> excludeModules) {
+        this.filter = filter;
+        this.filterPattern = filterPattern;
+        this.filterSamePackage = filterSamePackage;
+        this.filterSameArchive = filterSameArchive;
+        this.findJDKInternals = findJDKInternals;
+        this.includePattern = includePattern;
+        this.includePackages = includePackages;
+        this.excludeModules = excludeModules;
+    }
+
+    /**
+     * Tests if the given class matches the pattern given in the -include option
+     *
+     * @param cn fully-qualified name
+     */
+    public boolean matches(String cn) {
+        if (includePackages.isEmpty() && includePattern == null)
+            return true;
+
+        int i = cn.lastIndexOf('.');
+        String pn = i > 0 ? cn.substring(0, i) : "";
+        if (includePackages.contains(pn))
+            return true;
+
+        if (includePattern != null)
+            return includePattern.matcher(cn).matches();
+
+        return false;
+    }
+
+    /**
+     * Tests if the given source includes classes specified in includePattern
+     * or includePackages filters.
+     *
+     * This method can be used to determine if the given source should eagerly
+     * be processed.
+     */
+    public boolean matches(Archive source) {
+        if (!includePackages.isEmpty() && source.getModule().isNamed()) {
+            boolean found = source.getModule().packages()
+                                  .stream()
+                                  .filter(pn -> includePackages.contains(pn))
+                                  .findAny().isPresent();
+            if (found)
+                return true;
+        }
+        if (!includePackages.isEmpty() || includePattern != null) {
+            return source.reader().entries()
+                         .stream()
+                         .map(name -> name.replace('/', '.'))
+                         .filter(this::matches)
+                         .findAny().isPresent();
+        }
+        return false;
+    }
+
+    // ----- Dependency.Filter -----
+
+    @Override
+    public boolean accepts(Dependency d) {
+        if (d.getOrigin().equals(d.getTarget()))
+            return false;
+
+        // filter same package dependency
+        String pn = d.getTarget().getPackageName();
+        if (filterSamePackage && d.getOrigin().getPackageName().equals(pn)) {
+            return false;
+        }
+
+        // filter if the target package matches the given filter
+        if (filterPattern != null && filterPattern.matcher(pn).matches()) {
+            return false;
+        }
+
+        // filter if the target matches the given filtered package name or regex
+        return filter != null ? filter.accepts(d) : true;
+    }
+
+    // ----- Analyzer.Filter ------
+
+    /**
+     * Filter depending on the containing archive or module
+     */
+    @Override
+    public boolean accepts(Location origin, Archive originArchive,
+                           Location target, Archive targetArchive) {
+        if (findJDKInternals) {
+            // accepts target that is JDK class but not exported
+            Module module = targetArchive.getModule();
+            return originArchive != targetArchive &&
+                    module.isJDK() && !module.isExported(target.getPackageName());
+        } else if (filterSameArchive) {
+            // accepts origin and target that from different archive
+            return originArchive != targetArchive;
+        }
+        return true;
+    }
+
+    /**
+     * Returns true if dependency should be recorded for the given source.
+     */
+    public boolean accept(Archive source) {
+        return !excludeModules.contains(source.getName());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("exclude modules: ")
+          .append(excludeModules.stream().sorted().collect(Collectors.joining(",")))
+          .append("\n");
+        sb.append("filter same archive: ").append(filterSameArchive).append("\n");
+        sb.append("filter same package: ").append(filterSamePackage).append("\n");
+        return sb.toString();
+    }
+
+    static class Builder {
+        Dependency.Filter filter;
+        Pattern filterPattern;
+        boolean filterSamePackage;
+        boolean filterSameArchive;
+        boolean findJDKInterals;
+        // source filters
+        Pattern includePattern;
+        Set<String> includePackages = new HashSet<>();
+        Set<String> includeModules = new HashSet<>();
+        Set<String> excludeModules = new HashSet<>();
+
+        public Builder packages(Set<String> packageNames) {
+            this.filter = Dependencies.getPackageFilter(packageNames, false);
+            return this;
+        }
+        public Builder regex(Pattern regex) {
+            this.filter = Dependencies.getRegexFilter(regex);
+            return this;
+        }
+        public Builder filter(Pattern regex) {
+            this.filterPattern = regex;
+            return this;
+        }
+        public Builder filter(boolean samePackage, boolean sameArchive) {
+            this.filterSamePackage = samePackage;
+            this.filterSameArchive = sameArchive;
+            return this;
+        }
+        public Builder findJDKInternals(boolean value) {
+            this.findJDKInterals = value;
+            return this;
+        }
+        public Builder includePattern(Pattern regex) {
+            this.includePattern = regex;
+            return this;
+        }
+        public Builder includePackage(String pn) {
+            this.includePackages.add(pn);
+            return this;
+        }
+        public Builder includeModules(Set<String> includes) {
+            this.includeModules.addAll(includes);
+            return this;
+        }
+        public Builder excludeModules(Set<String> excludes) {
+            this.excludeModules.addAll(excludes);
+            return this;
+        }
+
+        JdepsFilter build() {
+            return new JdepsFilter(filter,
+                                   filterPattern,
+                                   filterSamePackage,
+                                   filterSameArchive,
+                                   findJDKInterals,
+                                   includePattern,
+                                   includePackages,
+                                   excludeModules.stream()
+                                        .filter(mn -> !includeModules.contains(mn))
+                                        .collect(Collectors.toSet()));
+        }
+
+    }
+}
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 2c62683..649e53e 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
@@ -25,22 +25,34 @@
 
 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;
-import com.sun.tools.classfile.Dependencies.ClassFileError;
-import com.sun.tools.classfile.Dependency;
-import com.sun.tools.classfile.Dependency.Location;
 import static com.sun.tools.jdeps.Analyzer.Type.*;
-import java.io.*;
+import static com.sun.tools.jdeps.JdepsWriter.*;
+import static com.sun.tools.jdeps.ModuleAnalyzer.Graph;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.module.ResolutionException;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.text.MessageFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Implementation for the jdeps tool for static class dependency analysis.
@@ -145,11 +157,6 @@
                 }
             }
         },
-        new Option(true, "-cp", "-classpath") {
-            void process(JdepsTask task, String opt, String arg) {
-                task.options.classpath = arg;
-            }
-        },
         new Option(true, "-p", "-package") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.packageNames.add(arg);
@@ -157,17 +164,21 @@
         },
         new Option(true, "-e", "-regex") {
             void process(JdepsTask task, String opt, String arg) {
-                task.options.regex = arg;
+                task.options.regex = Pattern.compile(arg);
             }
         },
-
+        new Option(true, "-module") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.requires.add(arg);
+            }
+        },
         new Option(true, "-f", "-filter") {
             void process(JdepsTask task, String opt, String arg) {
-                task.options.filterRegex = arg;
+                task.options.filterRegex = Pattern.compile(arg);
             }
         },
         new Option(false, "-filter:package",
-                          "-filter:archive",
+                          "-filter:archive", "-filter:module",
                           "-filter:none") {
             void process(JdepsTask task, String opt, String arg) {
                 switch (opt) {
@@ -176,6 +187,7 @@
                         task.options.filterSameArchive = false;
                         break;
                     case "-filter:archive":
+                    case "-filter:module":
                         task.options.filterSameArchive = true;
                         task.options.filterSamePackage = false;
                         break;
@@ -197,7 +209,7 @@
                 task.options.showModule = false;
             }
         },
-        new Option(false, "-M", "-module") {
+        new Option(false, "-M") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 task.options.showModule = true;
                 task.options.showProfile = false;
@@ -216,6 +228,23 @@
                 task.options.filterSamePackage = false;
             }
         },
+        new Option(true, "-genmoduleinfo") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                Path p = Paths.get(arg);
+                if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
+                    throw new BadArgs("err.invalid.path", arg);
+                }
+                task.options.genModuleInfo = arg;
+            }
+        },
+        new Option(false, "-ct", "-compile-time") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.compileTimeView = true;
+                task.options.filterSamePackage = true;
+                task.options.filterSameArchive = true;
+                task.options.depth = 0;
+            }
+        },
         new Option(false, "-jdkinternals") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.findJDKInternals = true;
@@ -225,25 +254,55 @@
                 }
             }
         },
-            new HiddenOption(false, "-verify:access") {
-                void process(JdepsTask task, String opt, String arg) {
-                    task.options.verifyAccess = true;
-                    task.options.verbose = VERBOSE;
-                    task.options.filterSameArchive = false;
-                    task.options.filterSamePackage = false;
+        new Option(true, "-cp", "-classpath") {
+            void process(JdepsTask task, String opt, String arg) {
+                    task.options.classpath = arg;
                 }
-            },
-            new HiddenOption(true, "-mp") {
+        },
+        new Option(true, "-mp", "-modulepath") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.modulePath = arg;
+                task.options.showModule = true;
+            }
+        },
+        new Option(true, "-upgrademodulepath") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.upgradeModulePath = arg;
+                task.options.showModule = true;
+            }
+        },
+        new Option(true, "-m") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.rootModule = arg;
+                task.options.includes.add(arg);
+                task.options.showModule = true;
+            }
+        },
+        new Option(false, "-check") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                task.options.checkModuleDeps = true;
+            }
+        },
+        new HiddenOption(true, "-include-modules") {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                Arrays.stream(arg.split(","))
+                        .forEach(task.options.includes::add);
+                task.options.showModule = true;
+            }
+        },
+        new HiddenOption(true, "-exclude-modules") {
                 void process(JdepsTask task, String opt, String arg) throws BadArgs {
-                    task.options.mpath = Paths.get(arg);
-                    if (!Files.isDirectory(task.options.mpath)) {
-                        throw new BadArgs("err.invalid.path", arg);
-                    }
-                    if (task.options.includePattern == null) {
-                        task.options.includePattern = Pattern.compile(".*");
-                    }
+                    Arrays.stream(arg.split(","))
+                            .forEach(task.options.excludes::add);
+                    task.options.showModule = true;
                 }
-            },
+        },
+        new Option(false, "-q", "-quiet") {
+            void process(JdepsTask task, String opt, String arg) {
+                    task.options.nowarning = true;
+                }
+        },
+
         new Option(false, "-version") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.version = true;
@@ -259,11 +318,7 @@
                 task.options.showLabel = true;
             }
         },
-        new HiddenOption(false, "-q", "-quiet") {
-            void process(JdepsTask task, String opt, String arg) {
-                task.options.nowarning = true;
-            }
-        },
+
         new HiddenOption(true, "-depth") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 try {
@@ -305,7 +360,15 @@
             if (options.version || options.fullVersion) {
                 showVersion(options.fullVersion);
             }
-            if (classes.isEmpty() && options.includePattern == null) {
+            if (options.rootModule != null && !classes.isEmpty()) {
+                reportError("err.invalid.module.option", options.rootModule, classes);
+                return EXIT_CMDERR;
+            }
+            if (options.checkModuleDeps && options.rootModule == null) {
+                reportError("err.root.module.not.set");
+                return EXIT_CMDERR;
+            }
+            if (classes.isEmpty() && options.rootModule == null && options.includePattern == null) {
                 if (options.help || options.version || options.fullVersion) {
                     return EXIT_OK;
                 } else {
@@ -313,12 +376,28 @@
                     return EXIT_CMDERR;
                 }
             }
-            if (options.regex != null && options.packageNames.size() > 0) {
-                showHelp();
+            if (options.genModuleInfo != null) {
+                if (options.dotOutputDir != null || !options.classpath.isEmpty() || options.hasFilter()) {
+                    showHelp();
+                    return EXIT_CMDERR;
+                }
+                // default to compile time view analysis
+                options.compileTimeView = true;
+                for (String fn : classes) {
+                    Path p = Paths.get(fn);
+                    if (!Files.exists(p) || !fn.endsWith(".jar")) {
+                        reportError("err.genmoduleinfo.not.jarfile", fn);
+                        return EXIT_CMDERR;
+                    }
+                }
+            }
+
+            if (options.numFilters() > 1) {
+                reportError("err.invalid.filters");
                 return EXIT_CMDERR;
             }
-            if ((options.findJDKInternals || options.verifyAccess) &&
-                   (options.regex != null || options.packageNames.size() > 0 || options.showSummary)) {
+
+            if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) {
                 showHelp();
                 return EXIT_CMDERR;
             }
@@ -335,140 +414,233 @@
                 log.println(getMessage("main.usage.summary", PROGNAME));
             }
             return EXIT_CMDERR;
+        } catch (ResolutionException e) {
+            reportError("err.exception.message", e.getMessage());
+            return EXIT_CMDERR;
         } catch (IOException e) {
+            e.printStackTrace();
             return EXIT_ABNORMAL;
         } finally {
             log.flush();
         }
     }
 
-    private final List<Archive> sourceLocations = new ArrayList<>();
-    private final List<Archive> classpaths = new ArrayList<>();
-    private final List<Archive> initialArchives = new ArrayList<>();
-    private boolean run() throws IOException {
-        buildArchives();
+    private ModulePaths modulePaths;
+    private boolean run() throws BadArgs, IOException {
+        DependencyFinder dependencyFinder =
+            new DependencyFinder(options.compileTimeView);
 
-        if (options.verifyAccess) {
-            return verifyModuleAccess();
+        buildArchive(dependencyFinder);
+
+        if (options.rootModule != null &&
+                (options.checkModuleDeps || (options.dotOutputDir != null &&
+                                      options.verbose == SUMMARY))) {
+            // -dotfile -s prints the configuration of the given root
+            // -checkModuleDeps prints the suggested module-info.java
+            return analyzeModules(dependencyFinder);
+        }
+
+        // otherwise analyze the dependencies
+        if (options.genModuleInfo != null) {
+            return genModuleInfo(dependencyFinder);
         } else {
-            return analyzeDeps();
+            return analyzeDeps(dependencyFinder);
         }
     }
 
-    private boolean analyzeDeps() throws IOException {
-        Analyzer analyzer = new Analyzer(options.verbose, new Analyzer.Filter() {
-            @Override
-            public boolean accepts(Location origin, Archive originArchive,
-                                   Location target, Archive targetArchive)
-            {
-                if (options.findJDKInternals) {
-                    // accepts target that is JDK class but not exported
-                    return isJDKModule(targetArchive) &&
-                              !((Module) targetArchive).isExported(target.getClassName());
-                } else if (options.filterSameArchive) {
-                    // accepts origin and target that from different archive
-                    return originArchive != targetArchive;
-                }
-                return true;
+    private void buildArchive(DependencyFinder dependencyFinder)
+            throws BadArgs, IOException
+    {
+        // If -genmoduleinfo is specified, the input arguments must be JAR files
+        // Treat them as automatic modules for analysis
+        List<Path> jarfiles = options.genModuleInfo != null
+                                    ?  classes.stream().map(Paths::get)
+                                              .collect(Collectors.toList())
+                                    : Collections.emptyList();
+        // Set module paths
+        this.modulePaths = new ModulePaths(options.upgradeModulePath, options.modulePath, jarfiles);
+
+        // add modules to dependency finder for analysis
+        Map<String, Module> modules = modulePaths.getModules();
+        modules.values().stream()
+               .forEach(dependencyFinder::addModule);
+
+        // If -m option is set, add the specified module and its transitive dependences
+        // to the root set
+        if (options.rootModule != null) {
+            modulePaths.dependences(options.rootModule)
+                       .forEach(dependencyFinder::addRoot);
+        }
+
+        // check if any module specified in -requires is missing
+        Optional<String> req = options.requires.stream()
+                .filter(mn -> !modules.containsKey(mn))
+                .findFirst();
+        if (req.isPresent()) {
+            throw new BadArgs("err.module.not.found", req.get());
+        }
+
+        // classpath
+        for (Path p : getClassPaths(options.classpath)) {
+            if (Files.exists(p)) {
+                dependencyFinder.addClassPathArchive(p);
             }
-        });
+        }
+
+        // if -genmoduleinfo is not set, the input arguments are considered as
+        // unnamed module.  Add them to the root set
+        if (options.genModuleInfo == null) {
+            // add root set
+            for (String s : classes) {
+                Path p = Paths.get(s);
+                if (Files.exists(p)) {
+                    // add to the initial root set
+                    dependencyFinder.addRoot(p);
+                } else {
+                    if (isValidClassName(s)) {
+                        dependencyFinder.addClassName(s);
+                    } else {
+                        warning("warn.invalid.arg", s);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean analyzeDeps(DependencyFinder dependencyFinder) throws IOException {
+        JdepsFilter filter = dependencyFilter();
 
         // parse classfiles and find all dependencies
-        findDependencies(options.apiOnly);
+        findDependencies(dependencyFinder, filter, options.apiOnly);
 
-        // analyze the dependencies
-        analyzer.run(sourceLocations);
+        // analyze the dependencies collected
+        Analyzer analyzer = new Analyzer(options.verbose, filter);
+        analyzer.run(dependencyFinder.archives());
 
         // output result
+        final JdepsWriter writer;
         if (options.dotOutputDir != null) {
             Path dir = Paths.get(options.dotOutputDir);
             Files.createDirectories(dir);
-            generateDotFiles(dir, analyzer);
+            writer = new DotFileWriter(dir, options.verbose,
+                                       options.showProfile,
+                                       options.showModule,
+                                       options.showLabel);
         } else {
-            printRawOutput(log, analyzer);
+            writer = new SimpleWriter(log, options.verbose,
+                                      options.showProfile,
+                                      options.showModule);
         }
 
+        // Targets for reporting - include the root sets and other analyzed archives
+        final List<Archive> targets;
+        if (options.rootModule == null) {
+            // no module as the root set
+            targets = dependencyFinder.archives()
+                                      .filter(filter::accept)
+                                      .filter(a -> !a.getModule().isNamed())
+                                      .collect(Collectors.toList());
+        } else {
+            // named modules in topological order
+            Stream<Module> modules = dependencyFinder.archives()
+                                                     .filter(a -> a.getModule().isNamed())
+                                                     .map(Archive::getModule);
+            Graph<Module> graph = ModuleAnalyzer.graph(modulePaths, modules.toArray(Module[]::new));
+            // then add unnamed module
+            targets = graph.orderedNodes()
+                           .filter(filter::accept)
+                           .collect(Collectors.toList());
+
+            // in case any reference not found
+            dependencyFinder.archives()
+                    .filter(a -> !a.getModule().isNamed())
+                    .forEach(targets::add);
+        }
+
+        writer.generateOutput(targets, analyzer);
         if (options.findJDKInternals && !options.nowarning) {
-            showReplacements(analyzer);
+            showReplacements(targets, analyzer);
         }
         return true;
     }
 
-    private boolean verifyModuleAccess() throws IOException {
-        // two passes
-        // 1. check API dependences where the types of dependences must be re-exported
-        // 2. check all dependences where types must be accessible
+    private JdepsFilter dependencyFilter() {
+        // Filter specified by -filter, -package, -regex, and -module options
+        JdepsFilter.Builder builder = new JdepsFilter.Builder();
 
-        // pass 1
-        findDependencies(true /* api only */);
-        Analyzer analyzer = Analyzer.getExportedAPIsAnalyzer();
-        boolean pass1 = analyzer.run(sourceLocations);
-        if (!pass1) {
-            System.out.println("ERROR: Failed API access verification");
+        // Exclude JDK modules from analysis and reporting if -m specified.
+        modulePaths.getModules().values().stream()
+                   .filter(m -> m.isJDK())
+                   .map(Module::name)
+                   .forEach(options.excludes::add);
+
+        // source filters
+        builder.includePattern(options.includePattern);
+        builder.includeModules(options.includes);
+        builder.excludeModules(options.excludes);
+
+        builder.filter(options.filterSamePackage, options.filterSameArchive);
+        builder.findJDKInternals(options.findJDKInternals);
+
+        // -module
+        if (!options.requires.isEmpty()) {
+            Map<String, Module> modules = modulePaths.getModules();
+            builder.packages(options.requires.stream()
+                    .map(modules::get)
+                    .flatMap(m -> m.packages().stream())
+                    .collect(Collectors.toSet()));
         }
-        // pass 2
-        findDependencies(false);
-        analyzer =  Analyzer.getModuleAccessAnalyzer();
-        boolean pass2 = analyzer.run(sourceLocations);
-        if (!pass2) {
-            System.out.println("ERROR: Failed module access verification");
-        }
-        if (pass1 & pass2) {
-            System.out.println("Access verification succeeded.");
-        }
-        return pass1 & pass2;
+        // -regex
+        if (options.regex != null)
+            builder.regex(options.regex);
+        // -package
+        if (!options.packageNames.isEmpty())
+            builder.packages(options.packageNames);
+        // -filter
+        if (options.filterRegex != null)
+            builder.filter(options.filterRegex);
+
+        return builder.build();
     }
 
-    private void generateSummaryDotFile(Path dir, Analyzer analyzer) throws IOException {
-        // If verbose mode (-v or -verbose option),
-        // the summary.dot file shows package-level dependencies.
-        Analyzer.Type summaryType =
-            (options.verbose == PACKAGE || options.verbose == SUMMARY) ? SUMMARY : PACKAGE;
-        Path summary = dir.resolve("summary.dot");
-        try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
-             SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
-            for (Archive archive : sourceLocations) {
-                if (!archive.isEmpty()) {
-                    if (options.verbose == PACKAGE || options.verbose == SUMMARY) {
-                        if (options.showLabel) {
-                            // build labels listing package-level dependencies
-                            analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
-                        }
-                    }
-                    analyzer.visitDependences(archive, dotfile, summaryType);
-                }
+    private void findDependencies(DependencyFinder dependencyFinder,
+                                  JdepsFilter filter,
+                                  boolean apiOnly)
+        throws IOException
+    {
+        dependencyFinder.findDependencies(filter, apiOnly, options.depth);
+
+        // print skipped entries, if any
+        for (Archive a : dependencyFinder.roots()) {
+            for (String name : a.reader().skippedEntries()) {
+                warning("warn.skipped.entry", name, a.getPathName());
             }
         }
     }
 
-    private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException {
-        // output individual .dot file for each archive
-        if (options.verbose != SUMMARY) {
-            for (Archive archive : sourceLocations) {
-                if (analyzer.hasDependences(archive)) {
-                    Path dotfile = dir.resolve(archive.getName() + ".dot");
-                    try (PrintWriter pw = new PrintWriter(Files.newOutputStream(dotfile));
-                         DotFileFormatter formatter = new DotFileFormatter(pw, archive)) {
-                        analyzer.visitDependences(archive, formatter);
-                    }
-                }
-            }
-        }
-        // generate summary dot file
-        generateSummaryDotFile(dir, analyzer);
+    private boolean genModuleInfo(DependencyFinder dependencyFinder) throws IOException {
+        ModuleInfoBuilder builder = new ModuleInfoBuilder(modulePaths, dependencyFinder);
+        boolean result = builder.run(options.verbose, options.nowarning);
+        builder.build(Paths.get(options.genModuleInfo));
+        return result;
     }
 
-    private void printRawOutput(PrintWriter writer, Analyzer analyzer) {
-        RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
-        RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
-        for (Archive archive : sourceLocations) {
-            if (!archive.isEmpty()) {
-                analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
-                if (analyzer.hasDependences(archive) && options.verbose != SUMMARY) {
-                    analyzer.visitDependences(archive, depFormatter);
-                }
-            }
+    private boolean analyzeModules(DependencyFinder dependencyFinder)
+            throws IOException
+    {
+        ModuleAnalyzer analyzer = new ModuleAnalyzer(modulePaths,
+                                                     dependencyFinder,
+                                                     options.rootModule);
+        if (options.checkModuleDeps) {
+            return analyzer.run();
         }
+        if (options.dotOutputDir != null && options.verbose == SUMMARY) {
+            Path dir = Paths.get(options.dotOutputDir);
+            Files.createDirectories(dir);
+            analyzer.genDotFile(dir);
+            return true;
+        }
+        return false;
     }
 
     private boolean isValidClassName(String name) {
@@ -484,199 +656,6 @@
         return true;
     }
 
-    /*
-     * Dep Filter configured based on the input jdeps option
-     * 1. -p and -regex to match target dependencies
-     * 2. -filter:package to filter out same-package dependencies
-     *
-     * This filter is applied when jdeps parses the class files
-     * and filtered dependencies are not stored in the Analyzer.
-     *
-     * -filter:archive is applied later in the Analyzer as the
-     * containing archive of a target class may not be known until
-     * the entire archive
-     */
-    class DependencyFilter implements Dependency.Filter {
-        final Dependency.Filter filter;
-        final Pattern filterPattern;
-        DependencyFilter() {
-            if (options.regex != null) {
-                this.filter = Dependencies.getRegexFilter(Pattern.compile(options.regex));
-            } else if (options.packageNames.size() > 0) {
-                this.filter = Dependencies.getPackageFilter(options.packageNames, false);
-            } else {
-                this.filter = null;
-            }
-
-            this.filterPattern =
-                options.filterRegex != null ? Pattern.compile(options.filterRegex) : null;
-        }
-        @Override
-        public boolean accepts(Dependency d) {
-            if (d.getOrigin().equals(d.getTarget())) {
-                return false;
-            }
-            String pn = d.getTarget().getPackageName();
-            if (options.filterSamePackage && d.getOrigin().getPackageName().equals(pn)) {
-                return false;
-            }
-
-            if (filterPattern != null && filterPattern.matcher(pn).matches()) {
-                return false;
-            }
-            return filter != null ? filter.accepts(d) : true;
-        }
-    }
-
-    /**
-     * Tests if the given class matches the pattern given in the -include option
-     */
-    private boolean matches(String classname) {
-        if (options.includePattern != null) {
-            return options.includePattern.matcher(classname.replace('/', '.')).matches();
-        } else {
-            return true;
-        }
-    }
-
-    private void buildArchives() throws IOException {
-        for (String s : classes) {
-            Path p = Paths.get(s);
-            if (Files.exists(p)) {
-                initialArchives.add(Archive.getInstance(p));
-            }
-        }
-        sourceLocations.addAll(initialArchives);
-
-        classpaths.addAll(getClassPathArchives(options.classpath));
-        if (options.includePattern != null) {
-            initialArchives.addAll(classpaths);
-        }
-        classpaths.addAll(PlatformClassPath.getModules(options.mpath));
-        if (options.mpath != null) {
-            initialArchives.addAll(PlatformClassPath.getModules(options.mpath));
-        } else {
-            classpaths.addAll(PlatformClassPath.getJarFiles());
-        }
-        // add all classpath archives to the source locations for reporting
-        sourceLocations.addAll(classpaths);
-    }
-
-    private void findDependencies(boolean apiOnly) throws IOException {
-        Dependency.Finder finder =
-            apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
-                    : Dependencies.getClassDependencyFinder();
-        Dependency.Filter filter = new DependencyFilter();
-
-        Deque<String> roots = new LinkedList<>();
-        for (String s : classes) {
-            Path p = Paths.get(s);
-            if (!Files.exists(p)) {
-                if (isValidClassName(s)) {
-                    roots.add(s);
-                } else {
-                    warning("warn.invalid.arg", s);
-                }
-            }
-        }
-
-        // Work queue of names of classfiles to be searched.
-        // Entries will be unique, and for classes that do not yet have
-        // dependencies in the results map.
-        Deque<String> deque = new LinkedList<>();
-        Set<String> doneClasses = new HashSet<>();
-
-        // get the immediate dependencies of the input files
-        for (Archive a : initialArchives) {
-            for (ClassFile cf : a.reader().getClassFiles()) {
-                String classFileName;
-                try {
-                    classFileName = cf.getName();
-                } catch (ConstantPoolException e) {
-                    throw new ClassFileError(e);
-                }
-
-                // tests if this class matches the -include or -apiOnly option if specified
-                if (!matches(classFileName) || (apiOnly && !cf.access_flags.is(AccessFlags.ACC_PUBLIC))) {
-                    continue;
-                }
-
-                if (!doneClasses.contains(classFileName)) {
-                    doneClasses.add(classFileName);
-                }
-
-                for (Dependency d : finder.findDependencies(cf)) {
-                    if (filter.accepts(d)) {
-                        String cn = d.getTarget().getName();
-                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
-                            deque.add(cn);
-                        }
-                        a.addClass(d.getOrigin(), d.getTarget());
-                    } else {
-                        // ensure that the parsed class is added the archive
-                        a.addClass(d.getOrigin());
-                    }
-                }
-                for (String name : a.reader().skippedEntries()) {
-                    warning("warn.skipped.entry", name, a.getPathName());
-                }
-            }
-        }
-
-        // add Archive for looking up classes from the classpath
-        // for transitive dependency analysis
-        Deque<String> unresolved = roots;
-        int depth = options.depth > 0 ? options.depth : Integer.MAX_VALUE;
-        do {
-            String name;
-            while ((name = unresolved.poll()) != null) {
-                if (doneClasses.contains(name)) {
-                    continue;
-                }
-                ClassFile cf = null;
-                for (Archive a : classpaths) {
-                    cf = a.reader().getClassFile(name);
-                    if (cf != null) {
-                        String classFileName;
-                        try {
-                            classFileName = cf.getName();
-                        } catch (ConstantPoolException e) {
-                            throw new ClassFileError(e);
-                        }
-                        if (!doneClasses.contains(classFileName)) {
-                            // if name is a fully-qualified class name specified
-                            // from command-line, this class might already be parsed
-                            doneClasses.add(classFileName);
-
-                            for (Dependency d : finder.findDependencies(cf)) {
-                                if (depth == 0) {
-                                    // ignore the dependency
-                                    a.addClass(d.getOrigin());
-                                    break;
-                                } else if (filter.accepts(d)) {
-                                    a.addClass(d.getOrigin(), d.getTarget());
-                                    String cn = d.getTarget().getName();
-                                    if (!doneClasses.contains(cn) && !deque.contains(cn)) {
-                                        deque.add(cn);
-                                    }
-                                } else {
-                                    // ensure that the parsed class is added the archive
-                                    a.addClass(d.getOrigin());
-                                }
-                            }
-                        }
-                        break;
-                    }
-                }
-                if (cf == null) {
-                    doneClasses.add(name);
-                }
-            }
-            unresolved = deque;
-            deque = new LinkedList<>();
-        } while (!unresolved.isEmpty() && depth-- > 0);
-    }
-
     public void handleOptions(String[] args) throws BadArgs {
         // process options
         for (int i=0; i < args.length; i++) {
@@ -775,22 +754,45 @@
         boolean apiOnly;
         boolean showLabel;
         boolean findJDKInternals;
-        boolean nowarning;
+        boolean nowarning = false;
         // default is to show package-level dependencies
         // and filter references from same package
         Analyzer.Type verbose = PACKAGE;
         boolean filterSamePackage = true;
         boolean filterSameArchive = false;
-        String filterRegex;
+        Pattern filterRegex;
         String dotOutputDir;
+        String genModuleInfo;
         String classpath = "";
         int depth = 1;
+        Set<String> requires = new HashSet<>();
         Set<String> packageNames = new HashSet<>();
-        String regex;             // apply to the dependences
-        Pattern includePattern;   // apply to classes
-        // module boundary access check
-        boolean verifyAccess;
-        Path mpath;
+        Pattern regex;             // apply to the dependences
+        Pattern includePattern;    // apply to classes
+        boolean compileTimeView = false;
+        boolean checkModuleDeps = false;
+        String upgradeModulePath;
+        String modulePath;
+        String rootModule;
+        // modules to be included or excluded
+        Set<String> includes = new HashSet<>();
+        Set<String> excludes = new HashSet<>();
+
+        boolean hasFilter() {
+            return numFilters() > 0;
+        }
+
+        int numFilters() {
+            int count = 0;
+            if (requires.size() > 0) count++;
+            if (regex != null) count++;
+            if (packageNames.size() > 0) count++;
+            return count;
+        }
+
+        boolean isRootModule() {
+            return rootModule != null;
+        }
     }
     private static class ResourceBundleHelper {
         static final ResourceBundle versionRB;
@@ -821,12 +823,10 @@
      * Returns the list of Archive specified in cpaths and not included
      * initialArchives
      */
-    private List<Archive> getClassPathArchives(String cpaths)
-            throws IOException
+    private List<Path> getClassPaths(String cpaths) throws IOException
     {
-        List<Archive> result = new ArrayList<>();
         if (cpaths.isEmpty()) {
-            return result;
+            return Collections.emptyList();
         }
         List<Path> paths = new ArrayList<>();
         for (String p : cpaths.split(File.pathSeparator)) {
@@ -845,211 +845,7 @@
                 }
             }
         }
-        for (Path path : paths) {
-            boolean found = initialArchives.stream()
-                                           .map(Archive::path)
-                                           .anyMatch(p -> isSameFile(path, p));
-            if (!found && Files.exists(path)) {
-                result.add(Archive.getInstance(path));
-            }
-        }
-        return result;
-    }
-
-    private boolean isSameFile(Path p1, Path p2) {
-        try {
-            return Files.isSameFile(p1, p2);
-        } catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-    class RawOutputFormatter implements Analyzer.Visitor {
-        private final PrintWriter writer;
-        private String pkg = "";
-        RawOutputFormatter(PrintWriter writer) {
-            this.writer = writer;
-        }
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String tag = toTag(target, targetArchive);
-            if (options.verbose == VERBOSE) {
-                writer.format("   %-50s -> %-50s %s%n", origin, target, tag);
-            } else {
-                if (!origin.equals(pkg)) {
-                    pkg = origin;
-                    writer.format("   %s (%s)%n", origin, originArchive.getName());
-                }
-                writer.format("      -> %-50s %s%n", target, tag);
-            }
-        }
-    }
-
-    class RawSummaryFormatter implements Analyzer.Visitor {
-        private final PrintWriter writer;
-        RawSummaryFormatter(PrintWriter writer) {
-            this.writer = writer;
-        }
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String targetName =  targetArchive.getPathName();
-            if (options.showModule && isJDKModule(targetArchive)) {
-                targetName = ((Module)targetArchive).name();
-            }
-            writer.format("%s -> %s", originArchive.getName(), targetName);
-            if (options.showProfile && isJDKModule(targetArchive)) {
-                writer.format(" (%s)", target);
-            }
-            writer.format("%n");
-        }
-    }
-
-    class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
-        private final PrintWriter writer;
-        private final String name;
-        DotFileFormatter(PrintWriter writer, Archive archive) {
-            this.writer = writer;
-            this.name = archive.getName();
-            writer.format("digraph \"%s\" {%n", name);
-            writer.format("    // Path: %s%n", archive.getPathName());
-        }
-
-        @Override
-        public void close() {
-            writer.println("}");
-        }
-
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String tag = toTag(target, targetArchive);
-            writer.format("   %-50s -> \"%s\";%n",
-                          String.format("\"%s\"", origin),
-                          tag.isEmpty() ? target
-                                        : String.format("%s (%s)", target, tag));
-        }
-    }
-
-    class SummaryDotFile implements Analyzer.Visitor, AutoCloseable {
-        private final PrintWriter writer;
-        private final Analyzer.Type type;
-        private final Map<Archive, Map<Archive,StringBuilder>> edges = new HashMap<>();
-        SummaryDotFile(PrintWriter writer, Analyzer.Type type) {
-            this.writer = writer;
-            this.type = type;
-            writer.format("digraph \"summary\" {%n");
-        }
-
-        @Override
-        public void close() {
-            writer.println("}");
-        }
-
-        @Override
-        public void visitDependence(String origin, Archive originArchive,
-                                    String target, Archive targetArchive) {
-            String targetName = type == PACKAGE ? target : targetArchive.getName();
-            if (isJDKModule(targetArchive)) {
-                Module m = (Module)targetArchive;
-                String n = showProfileOrModule(m);
-                if (!n.isEmpty()) {
-                    targetName += " (" + n + ")";
-                }
-            } else if (type == PACKAGE) {
-                targetName += " (" + targetArchive.getName() + ")";
-            }
-            String label = getLabel(originArchive, targetArchive);
-            writer.format("  %-50s -> \"%s\"%s;%n",
-                          String.format("\"%s\"", origin), targetName, label);
-        }
-
-        String getLabel(Archive origin, Archive target) {
-            if (edges.isEmpty())
-                return "";
-
-            StringBuilder label = edges.get(origin).get(target);
-            return label == null ? "" : String.format(" [label=\"%s\",fontsize=9]", label.toString());
-        }
-
-        Analyzer.Visitor labelBuilder() {
-            // show the package-level dependencies as labels in the dot graph
-            return new Analyzer.Visitor() {
-                @Override
-                public void visitDependence(String origin, Archive originArchive, String target, Archive targetArchive) {
-                    edges.putIfAbsent(originArchive, new HashMap<>());
-                    edges.get(originArchive).putIfAbsent(targetArchive, new StringBuilder());
-                    StringBuilder sb = edges.get(originArchive).get(targetArchive);
-                    String tag = toTag(target, targetArchive);
-                    addLabel(sb, origin, target, tag);
-                }
-
-                void addLabel(StringBuilder label, String origin, String target, String tag) {
-                    label.append(origin).append(" -> ").append(target);
-                    if (!tag.isEmpty()) {
-                        label.append(" (" + tag + ")");
-                    }
-                    label.append("\\n");
-                }
-            };
-        }
-    }
-
-    /**
-     * Test if the given archive is part of the JDK
-     */
-    private boolean isJDKModule(Archive archive) {
-        return Module.class.isInstance(archive);
-    }
-
-    /**
-     * If the given archive is JDK archive, this method returns the profile name
-     * only if -profile option is specified; it accesses a private JDK API and
-     * the returned value will have "JDK internal API" prefix
-     *
-     * For non-JDK archives, this method returns the file name of the archive.
-     */
-    private String toTag(String name, Archive source) {
-        if (!isJDKModule(source)) {
-            return source.getName();
-        }
-
-        Module module = (Module)source;
-        boolean isExported = false;
-        if (options.verbose == CLASS || options.verbose == VERBOSE) {
-            isExported = module.isExported(name);
-        } else {
-            isExported = module.isExportedPackage(name);
-        }
-        if (isExported) {
-            // exported API
-            return showProfileOrModule(module);
-        } else {
-            return "JDK internal API (" + source.getName() + ")";
-        }
-    }
-
-    private String showProfileOrModule(Module m) {
-        String tag = "";
-        if (options.showProfile) {
-            Profile p = Profile.getProfile(m);
-            if (p != null) {
-                tag = p.profileName();
-            }
-        } else if (options.showModule) {
-            tag = m.name();
-        }
-        return tag;
-    }
-
-    private Profile getProfile(String name) {
-        String pn = name;
-        if (options.verbose == CLASS || options.verbose == VERBOSE) {
-            int i = name.lastIndexOf('.');
-            pn = i > 0 ? name.substring(0, i) : "";
-        }
-        return Profile.getProfile(pn);
+        return paths;
     }
 
     /**
@@ -1071,10 +867,10 @@
         return value;
     };
 
-    private void showReplacements(Analyzer analyzer) {
+    private void showReplacements(List<Archive> archives, Analyzer analyzer) {
         Map<String,String> jdkinternals = new TreeMap<>();
         boolean useInternals = false;
-        for (Archive source : sourceLocations) {
+        for (Archive source : archives) {
             useInternals = useInternals || analyzer.hasDependences(source);
             for (String cn : analyzer.dependences(source)) {
                 String repl = replacementFor(cn);
@@ -1095,6 +891,6 @@
                 log.format("%-40s %s%n", e.getKey(), e.getValue());
             }
         }
-
     }
+
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java
new file mode 100644
index 0000000..06449fa
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.sun.tools.jdeps.Analyzer.Type.*;
+
+public abstract class JdepsWriter {
+    final Analyzer.Type type;
+    final boolean showProfile;
+    final boolean showModule;
+
+    JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
+        this.type = type;
+        this.showProfile = showProfile;
+        this.showModule = showModule;
+    }
+
+    abstract void generateOutput(Collection<Archive> archives, Analyzer analyzer) throws IOException;
+
+    public static class DotFileWriter extends JdepsWriter {
+        final boolean showLabel;
+        final Path outputDir;
+        DotFileWriter(Path dir, Analyzer.Type type,
+                      boolean showProfile, boolean showModule, boolean showLabel) {
+            super(type, showProfile, showModule);
+            this.showLabel = showLabel;
+            this.outputDir = dir;
+        }
+
+        @Override
+        void generateOutput(Collection<Archive> archives, Analyzer analyzer)
+                throws IOException
+        {
+            // output individual .dot file for each archive
+            if (type != SUMMARY) {
+                archives.stream()
+                        .filter(analyzer::hasDependences)
+                        .forEach(archive -> {
+                            Path dotfile = outputDir.resolve(archive.getName() + ".dot");
+                            try (PrintWriter pw = new PrintWriter(Files.newOutputStream(dotfile));
+                                 DotFileFormatter formatter = new DotFileFormatter(pw, archive)) {
+                                analyzer.visitDependences(archive, formatter);
+                            } catch (IOException e) {
+                                throw new UncheckedIOException(e);
+                            }
+                        });
+            }
+            // generate summary dot file
+            generateSummaryDotFile(archives, analyzer);
+        }
+
+        private void generateSummaryDotFile(Collection<Archive> archives, Analyzer analyzer)
+                throws IOException
+        {
+            // If verbose mode (-v or -verbose option),
+            // the summary.dot file shows package-level dependencies.
+            Analyzer.Type summaryType =
+                (type == PACKAGE || type == SUMMARY) ? SUMMARY : PACKAGE;
+            Path summary = outputDir.resolve("summary.dot");
+            try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
+                 SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
+                for (Archive archive : archives) {
+                    if (type == PACKAGE || type == SUMMARY) {
+                        if (showLabel) {
+                            // build labels listing package-level dependencies
+                            analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
+                        }
+                    }
+                    analyzer.visitDependences(archive, dotfile, summaryType);
+                }
+            }
+        }
+
+        class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
+            private final PrintWriter writer;
+            private final String name;
+            DotFileFormatter(PrintWriter writer, Archive archive) {
+                this.writer = writer;
+                this.name = archive.getName();
+                writer.format("digraph \"%s\" {%n", name);
+                writer.format("    // Path: %s%n", archive.getPathName());
+            }
+
+            @Override
+            public void close() {
+                writer.println("}");
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+                String tag = toTag(originArchive, target, targetArchive);
+                writer.format("   %-50s -> \"%s\";%n",
+                              String.format("\"%s\"", origin),
+                              tag.isEmpty() ? target
+                                            : String.format("%s (%s)", target, tag));
+            }
+        }
+
+        class SummaryDotFile implements Analyzer.Visitor, AutoCloseable {
+            private final PrintWriter writer;
+            private final Analyzer.Type type;
+            private final Map<Archive, Map<Archive,StringBuilder>> edges = new HashMap<>();
+            SummaryDotFile(PrintWriter writer, Analyzer.Type type) {
+                this.writer = writer;
+                this.type = type;
+                writer.format("digraph \"summary\" {%n");
+            }
+
+            @Override
+            public void close() {
+                writer.println("}");
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+
+                String targetName = type == PACKAGE ? target : targetArchive.getName();
+                if (targetArchive.getModule().isJDK()) {
+                    Module m = (Module)targetArchive;
+                    String n = showProfileOrModule(m);
+                    if (!n.isEmpty()) {
+                        targetName += " (" + n + ")";
+                    }
+                } else if (type == PACKAGE) {
+                    targetName += " (" + targetArchive.getName() + ")";
+                }
+                String label = getLabel(originArchive, targetArchive);
+                writer.format("  %-50s -> \"%s\"%s;%n",
+                        String.format("\"%s\"", origin), targetName, label);
+            }
+
+            String getLabel(Archive origin, Archive target) {
+                if (edges.isEmpty())
+                    return "";
+
+                StringBuilder label = edges.get(origin).get(target);
+                return label == null ? "" : String.format(" [label=\"%s\",fontsize=9]", label.toString());
+            }
+
+            Analyzer.Visitor labelBuilder() {
+                // show the package-level dependencies as labels in the dot graph
+                return new Analyzer.Visitor() {
+                    @Override
+                    public void visitDependence(String origin, Archive originArchive,
+                                                String target, Archive targetArchive)
+                    {
+                        edges.putIfAbsent(originArchive, new HashMap<>());
+                        edges.get(originArchive).putIfAbsent(targetArchive, new StringBuilder());
+                        StringBuilder sb = edges.get(originArchive).get(targetArchive);
+                        String tag = toTag(originArchive, target, targetArchive);
+                        addLabel(sb, origin, target, tag);
+                    }
+
+                    void addLabel(StringBuilder label, String origin, String target, String tag) {
+                        label.append(origin).append(" -> ").append(target);
+                        if (!tag.isEmpty()) {
+                            label.append(" (" + tag + ")");
+                        }
+                        label.append("\\n");
+                    }
+                };
+            }
+        }
+    }
+
+    static class SimpleWriter extends JdepsWriter {
+        final PrintWriter writer;
+        SimpleWriter(PrintWriter writer, Analyzer.Type type,
+                     boolean showProfile, boolean showModule) {
+            super(type, showProfile, showModule);
+            this.writer = writer;
+        }
+
+        @Override
+        void generateOutput(Collection<Archive> archives, Analyzer analyzer) {
+            RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
+            RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
+            for (Archive archive : archives) {
+                // print summary
+                if (showModule && archive.getModule().isNamed()) {
+                    summaryFormatter.showModuleRequires(archive.getModule());
+                } else {
+                    analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
+                }
+
+                if (analyzer.hasDependences(archive) && type != SUMMARY) {
+                    // print the class-level or package-level dependences
+                    analyzer.visitDependences(archive, depFormatter);
+                }
+            }
+        }
+
+        class RawOutputFormatter implements Analyzer.Visitor {
+            private final PrintWriter writer;
+            private String pkg = "";
+
+            RawOutputFormatter(PrintWriter writer) {
+                this.writer = writer;
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+                String tag = toTag(originArchive, target, targetArchive);
+                if (showModule || type == VERBOSE) {
+                    writer.format("   %-50s -> %-50s %s%n", origin, target, tag);
+                } else {
+                    if (!origin.equals(pkg)) {
+                        pkg = origin;
+                        writer.format("   %s (%s)%n", origin, originArchive.getName());
+                    }
+                    writer.format("      -> %-50s %s%n", target, tag);
+                }
+            }
+        }
+
+        class RawSummaryFormatter implements Analyzer.Visitor {
+            private final PrintWriter writer;
+
+            RawSummaryFormatter(PrintWriter writer) {
+                this.writer = writer;
+            }
+
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive) {
+
+                String targetName = targetArchive.getPathName();
+                if (targetArchive.getModule().isNamed()) {
+                    targetName = targetArchive.getModule().name();
+                }
+                writer.format("%s -> %s", originArchive.getName(), targetName);
+                if (showProfile && targetArchive.getModule().isJDK()) {
+                    writer.format(" (%s)", target);
+                }
+                writer.format("%n");
+            }
+
+            public void showModuleRequires(Module module) {
+                if (!module.isNamed())
+                    return;
+
+                writer.format("module %s", module.name());
+                if (module.isAutomatic())
+                    writer.format(" (automatic)");
+                writer.println();
+                module.requires().keySet()
+                        .stream()
+                        .sorted()
+                        .forEach(req -> writer.format(" requires %s%s%n",
+                                                      module.requires.get(req) ? "public " : "",
+                                                      req));
+            }
+        }
+    }
+
+    /**
+     * If the given archive is JDK archive, this method returns the profile name
+     * only if -profile option is specified; it accesses a private JDK API and
+     * the returned value will have "JDK internal API" prefix
+     *
+     * For non-JDK archives, this method returns the file name of the archive.
+     */
+    String toTag(Archive source, String name, Archive target) {
+        if (source == target || !target.getModule().isNamed()) {
+            return target.getName();
+        }
+
+        Module module = target.getModule();
+        String pn = name;
+        if ((type == CLASS || type == VERBOSE)) {
+            int i = name.lastIndexOf('.');
+            pn = i > 0 ? name.substring(0, i) : "";
+        }
+
+        // exported API
+        boolean jdkunsupported = Module.isJDKUnsupported(module, pn);
+        if (module.isExported(pn) && !jdkunsupported) {
+            return showProfileOrModule(module);
+        }
+
+        // JDK internal API
+        if (!source.getModule().isJDK() && module.isJDK()){
+            return "JDK internal API (" + module.name() + ")";
+        }
+
+        // qualified exports or inaccessible
+        boolean isExported = module.isExported(pn, source.getModule().name());
+        return module.name() + (isExported ?  " (qualified)" : " (internal)");
+    }
+
+    String showProfileOrModule(Module m) {
+        String tag = "";
+        if (showProfile) {
+            Profile p = Profile.getProfile(m);
+            if (p != null) {
+                tag = p.profileName();
+            }
+        } else if (showModule) {
+            tag = m.name();
+        }
+        return tag;
+    }
+
+    Profile getProfile(String name) {
+        String pn = name;
+        if (type == CLASS || type == VERBOSE) {
+            int i = name.lastIndexOf('.');
+            pn = i > 0 ? name.substring(0, i) : "";
+        }
+        return Profile.getProfile(pn);
+    }
+
+}
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 9da197e4..a3ede30 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
@@ -25,35 +25,94 @@
 
 package com.sun.tools.jdeps;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.net.URI;
+import java.util.Arrays;
 import java.util.Collections;
 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.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 
 /**
  * JDeps internal representation of module for dependency analysis.
  */
-final class Module extends Archive {
-    private final String moduleName;
-    private final Map<String, Boolean> requires;
-    private final Map<String, Set<String>> exports;
-    private final Set<String> packages;
+class Module extends Archive {
+    static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
+    static void trace(String fmt, Object... args) {
+        if (traceOn) {
+            System.err.format(fmt, args);
+        }
+    }
 
-    private Module(ClassFileReader reader, String name,
+    /*
+     * Returns true if the given package name is JDK critical internal API
+     * in jdk.unsupported module
+     */
+    static boolean isJDKUnsupported(Module m, String pn) {
+        return JDK_UNSUPPORTED.equals(m.name()) || unsupported.contains(pn);
+    };
+
+    protected final ModuleDescriptor descriptor;
+    protected final Map<String, Boolean> requires;
+    protected final Map<String, Set<String>> exports;
+    protected final Set<String> packages;
+    protected final boolean isJDK;
+    protected final URI location;
+
+    private Module(String name,
+                   URI location,
+                   ModuleDescriptor descriptor,
                    Map<String, Boolean> requires,
                    Map<String, Set<String>> exports,
-                   Set<String> packages) {
-        super(name, reader);
-        this.moduleName = name;
+                   Set<String> packages,
+                   boolean isJDK,
+                   ClassFileReader reader) {
+        super(name, location, reader);
+        this.descriptor = descriptor;
+        this.location = location;
         this.requires = Collections.unmodifiableMap(requires);
         this.exports = Collections.unmodifiableMap(exports);
         this.packages = Collections.unmodifiableSet(packages);
+        this.isJDK = isJDK;
     }
 
+    /**
+     * Returns module name
+     */
     public String name() {
-        return moduleName;
+        return descriptor.name();
+    }
+
+    public boolean isNamed() {
+        return true;
+    }
+
+    public boolean isAutomatic() {
+        return descriptor.isAutomatic();
+    }
+
+    public Module getModule() {
+        return this;
+    }
+
+    public ModuleDescriptor descriptor() {
+        return descriptor;
+    }
+
+    public boolean isJDK() {
+        return isJDK;
     }
 
     public Map<String, Boolean> requires() {
@@ -64,89 +123,46 @@
         return exports;
     }
 
+    public Map<String, Set<String>> provides() {
+        return descriptor.provides().entrySet().stream()
+                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().providers()));
+    }
+
     public Set<String> packages() {
         return packages;
     }
 
     /**
-     * Tests if this module can read m
+     * Tests if the package of the given name is exported.
      */
-    public boolean canRead(Module m) {
-        // ## TODO: handle "re-exported=true"
-        // all JDK modules require all modules containing its direct dependences
-        // should not be an issue
-        return requires.containsKey(m.name());
-    }
-
-    /**
-     * Tests if a given fully-qualified name is an exported type.
-     */
-    public boolean isExported(String cn) {
-        int i = cn.lastIndexOf('.');
-        String pn = i > 0 ? cn.substring(0, i) : "";
-
-        return isExportedPackage(pn);
-    }
-
-    /**
-     * Tests if a given package name is exported.
-     */
-    public boolean isExportedPackage(String pn) {
+    public boolean isExported(String pn) {
         return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false;
     }
 
     /**
-     * Tests if the given classname is accessible to module m
+     * Converts this module to a strict module with the given dependences
+     *
+     * @throws IllegalArgumentException if this module is not an automatic module
      */
-    public boolean isAccessibleTo(String classname, Module m) {
-        int i = classname.lastIndexOf('.');
-        String pn = i > 0 ? classname.substring(0, i) : "";
-        if (!packages.contains(pn)) {
-            throw new IllegalArgumentException(classname + " is not a member of module " + name());
+    public Module toStrictModule(Map<String, Boolean> requires) {
+        if (!isAutomatic()) {
+            throw new IllegalArgumentException(name() + " already a strict module");
         }
-
-        if (m != null && !m.canRead(this)) {
-            trace("%s not readable by %s%n", this.name(), m.name());
-            return false;
-        }
-
-        // exported API
-        Set<String> ms = exports().get(pn);
-        String mname = m != null ? m.name() : "unnamed";
-        if (ms == null) {
-            trace("%s not exported in %s%n", classname, this.name());
-        } else if (!(ms.isEmpty() || ms.contains(mname))) {
-            trace("%s not permit to %s %s%n", classname, mname, ms);
-        }
-        return ms != null && (ms.isEmpty() || ms.contains(mname));
+        return new StrictModule(this, requires);
     }
 
-    private static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
-    private void trace(String fmt, Object... args) {
-        if (traceOn) {
-            System.err.format(fmt, args);
-        }
+    /**
+     * Tests if the package of the given name is qualifiedly exported
+     * to the target.
+     */
+    public boolean isExported(String pn, String target) {
+        return isExported(pn) || exports.containsKey(pn) && exports.get(pn).contains(target);
     }
 
-    @Override
-    public boolean equals(Object ob) {
-        if (!(ob instanceof Module))
-            return false;
-        Module that = (Module)ob;
-        return (moduleName.equals(that.moduleName)
-                && requires.equals(that.requires)
-                && exports.equals(that.exports)
-                && packages.equals(that.packages));
-    }
+    private final static String JDK_UNSUPPORTED = "jdk.unsupported";
 
-    @Override
-    public int hashCode() {
-        int hc = moduleName.hashCode();
-        hc = hc * 43 + requires.hashCode();
-        hc = hc * 43 + exports.hashCode();
-        hc = hc * 43 + packages.hashCode();
-        return hc;
-    }
+    // temporary until jdk.unsupported module
+    private final static List<String> unsupported = Arrays.asList("sun.misc", "sun.reflect");
 
     @Override
     public String toString() {
@@ -154,22 +170,35 @@
     }
 
     public final static class Builder {
-        String name;
-        ClassFileReader reader;
+        final String name;
         final Map<String, Boolean> requires = new HashMap<>();
         final Map<String, Set<String>> exports = new HashMap<>();
         final Set<String> packages = new HashSet<>();
+        final boolean isJDK;
+        ClassFileReader reader;
+        ModuleDescriptor descriptor;
+        URI location;
 
-        public Builder() {
+        public Builder(String name) {
+            this(name, false);
         }
 
-        public Builder name(String n) {
-            name = n;
+        public Builder(String name, boolean isJDK) {
+            this.name = name;
+            this.isJDK = isJDK;
+        }
+
+        public Builder location(URI location) {
+            this.location = location;
+            return this;
+        }
+
+        public Builder descriptor(ModuleDescriptor md) {
+            this.descriptor = md;
             return this;
         }
 
         public Builder require(String d, boolean reexport) {
-         //   System.err.format("%s depend %s reexports %s%n", name, d, reexport);
             requires.put(d, reexport);
             return this;
         }
@@ -185,14 +214,172 @@
             exports.put(p, new HashSet<>(ms));
             return this;
         }
-        public Builder classes(ClassFileReader.ModuleClassReader reader) {
+        public Builder classes(ClassFileReader reader) {
             this.reader = reader;
             return this;
         }
 
         public Module build() {
-            Module m = new Module(reader, name, requires, exports, packages);
-            return m;
+            if (descriptor.isAutomatic() && isJDK) {
+                throw new InternalError("JDK module: " + name + " can't be automatic module");
+            }
+
+            return new Module(name, location, descriptor, requires, exports, packages, isJDK, reader);
+        }
+    }
+
+    final static Module UNNAMED_MODULE = new UnnamedModule();
+    private static class UnnamedModule extends Module {
+        private UnnamedModule() {
+            super("unnamed", null, null,
+                  Collections.emptyMap(),
+                  Collections.emptyMap(),
+                  Collections.emptySet(),
+                  false, null);
+        }
+
+        @Override
+        public String name() {
+            return "unnamed";
+        }
+
+        @Override
+        public boolean isNamed() {
+            return false;
+        }
+
+        @Override
+        public boolean isAutomatic() {
+            return false;
+        }
+
+        @Override
+        public boolean isExported(String pn) {
+            return true;
+        }
+    }
+
+    private static class StrictModule extends Module {
+        private static final String SERVICES_PREFIX = "META-INF/services/";
+        private final Map<String, Set<String>> provides;
+        private final Module module;
+        private final JarFile jarfile;
+
+        /**
+         * Converts the given automatic module to a strict module.
+         *
+         * Replace this module's dependences with the given requires and also
+         * declare service providers, if specified in META-INF/services configuration file
+         */
+        private StrictModule(Module m, Map<String, Boolean> requires) {
+            super(m.name(), m.location, m.descriptor, requires, m.exports, m.packages, m.isJDK, m.reader());
+            this.module = m;
+            try {
+                this.jarfile = new JarFile(m.path().toFile(), false);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+            this.provides = providers(jarfile);
+        }
+
+        @Override
+        public Map<String, Set<String>> provides() {
+            return provides;
+        }
+
+        private Map<String, Set<String>> providers(JarFile jf) {
+            Map<String, Set<String>> provides = new HashMap<>();
+            // map names of service configuration files to service names
+            Set<String> serviceNames =  jf.stream()
+                    .map(e -> e.getName())
+                    .filter(e -> e.startsWith(SERVICES_PREFIX))
+                    .distinct()
+                    .map(this::toServiceName)
+                    .filter(Optional::isPresent)
+                    .map(Optional::get)
+                    .collect(Collectors.toSet());
+
+            // parse each service configuration file
+            for (String sn : serviceNames) {
+                JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
+                Set<String> providerClasses = new HashSet<>();
+                try (InputStream in = jf.getInputStream(entry)) {
+                    BufferedReader reader
+                            = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+                    String cn;
+                    while ((cn = nextLine(reader)) != null) {
+                        if (isJavaIdentifier(cn)) {
+                            providerClasses.add(cn);
+                        }
+                    }
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
+                }
+                if (!providerClasses.isEmpty())
+                    provides.put(sn, providerClasses);
+            }
+
+            return provides;
+        }
+
+        /**
+         * Returns a container with the service type corresponding to the name of
+         * a services configuration file.
+         *
+         * For example, if called with "META-INF/services/p.S" then this method
+         * returns a container with the value "p.S".
+         */
+        private Optional<String> toServiceName(String cf) {
+            assert cf.startsWith(SERVICES_PREFIX);
+            int index = cf.lastIndexOf("/") + 1;
+            if (index < cf.length()) {
+                String prefix = cf.substring(0, index);
+                if (prefix.equals(SERVICES_PREFIX)) {
+                    String sn = cf.substring(index);
+                    if (isJavaIdentifier(sn))
+                        return Optional.of(sn);
+                }
+            }
+            return Optional.empty();
+        }
+
+        /**
+         * Reads the next line from the given reader and trims it of comments and
+         * leading/trailing white space.
+         *
+         * Returns null if the reader is at EOF.
+         */
+        private String nextLine(BufferedReader reader) throws IOException {
+            String ln = reader.readLine();
+            if (ln != null) {
+                int ci = ln.indexOf('#');
+                if (ci >= 0)
+                    ln = ln.substring(0, ci);
+                ln = ln.trim();
+            }
+            return ln;
+        }
+
+        /**
+         * Returns {@code true} if the given identifier is a legal Java identifier.
+         */
+        private static boolean isJavaIdentifier(String id) {
+            int n = id.length();
+            if (n == 0)
+                return false;
+            if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
+                return false;
+            int cp = id.codePointAt(0);
+            int i = Character.charCount(cp);
+            for (; i < n; i += Character.charCount(cp)) {
+                cp = id.codePointAt(i);
+                if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
+                    return false;
+            }
+            if (cp == '.')
+                return false;
+
+            return true;
         }
     }
 }
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
new file mode 100644
index 0000000..f419e56
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.sun.tools.jdeps.Module.*;
+import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
+
+/**
+ * Analyze module dependences and compare with module descriptor.
+ * Also identify any qualified exports not used by the target module.
+ */
+class ModuleAnalyzer {
+    private final ModulePaths modulePaths;
+    private final DependencyFinder dependencyFinder;
+    private final Module root;
+    private final Set<Module> modules;
+    private final Set<String> requiresPublic = new HashSet<>();
+    private final Set<String> requires = new HashSet<>();
+    private final Set<Module> exportTargets = new HashSet<>();
+    private final JdepsFilter filter;
+    private Graph<Module> graph;
+    ModuleAnalyzer(ModulePaths modulePaths, DependencyFinder finder,
+                   String moduleName) {
+        this.modulePaths = modulePaths;
+        this.dependencyFinder = finder;
+        this.root = modulePaths.getModules().get(moduleName);
+        this.modules = modulePaths.dependences(moduleName);
+
+        root.exports().values().stream()
+             .flatMap(Set::stream)
+             .map(target -> modulePaths.getModules().get(target))
+             .forEach(this.exportTargets::add);
+
+        this.filter = new JdepsFilter.Builder().filter(true, true).build();
+    }
+
+    /**
+     * Returns a graph of transitive closure of the given modules.
+     *
+     * This method does not add the implicit read edges and is intended to
+     * get all transitive closures in (reverse) topological sort.
+     */
+    public static Graph<Module> graph(ModulePaths modulePaths, Module... modules) {
+        Graph.Builder<Module> gb = new Graph.Builder<>();
+        for (Module module : modules) {
+            module.descriptor().requires().stream()
+                    .map(ModuleDescriptor.Requires::name)
+                    .map(mn -> modulePaths.getModules().get(mn))
+                    .forEach(m -> {
+                        gb.addNode(m);
+                        gb.addEdge(module, m);
+                    });
+        }
+        return gb.build();
+    }
+
+    /**
+     * Do the analysis
+     */
+    public boolean run() {
+        try {
+            computeRequiresPublic();
+            computeRequires();
+            // apply transitive reduction and reports recommended requires.
+            analyzeDeps();
+            // detect any qualiifed exports not used by the target module
+            checkQualifiedExports();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return true;
+    }
+
+    /**
+     * Compute 'requires public' dependences by analyzing API dependencies
+     */
+    private void computeRequiresPublic() throws IOException {
+        JdepsFilter.Builder builder = new JdepsFilter.Builder();
+        // only analyze exported API
+        root.descriptor.exports().stream()
+                .filter(exp -> !exp.isQualified())
+                .map(ModuleDescriptor.Exports::source)
+                .forEach(builder::includePackage);
+
+        JdepsFilter filter = builder.filter(true, true).build();
+
+        // analyze dependences for exported packages
+        dependencyFinder.findDependencies(filter, true /* api only */, 1);
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(modules);
+
+        // record requires public
+        analyzer.requires(root)
+                .filter(m -> m != JAVA_BASE && m != root)
+                .map(Archive::getName)
+                .forEach(requiresPublic::add);
+        trace("requires public: %s%n", requiresPublic);
+    }
+
+    private void computeRequires() throws IOException {
+        // add the exportTargets of the qualified exports to the root set
+        exportTargets.stream()
+                .peek(target -> trace("add root: %s%n", target))
+                .forEach(dependencyFinder::addRoot);
+
+        // analyze all classes
+        dependencyFinder.findDependencies(filter, false /* all classes */, 1);
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(modules);
+
+        // record requires
+        analyzer.requires(root)
+                .filter(m -> m != JAVA_BASE && m != root)
+                .map(Archive::getName)
+                .forEach(requires::add);
+
+        this.graph = buildGraph(analyzer, root);
+        if (traceOn) {
+            trace("dependences: %s%n", graph.nodes());
+            graph.printGraph(System.out);
+        }
+    }
+
+    /**
+     * Apply transitive reduction on the resulting graph and reports
+     * recommended requires.
+     */
+    private void analyzeDeps() {
+        String moduleName = root.name();
+
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        requiresPublic.stream()
+                .forEach(mn -> {
+                    builder.addNode(mn);
+                    builder.addEdge(moduleName, mn);
+                });
+        // requires public graph
+        Graph<String> rbg = builder.build().reduce();
+
+        // convert the dependence graph from Module to name
+        Set<String> nodes = this.graph.nodes().stream()
+                .map(Module::name)
+                .collect(Collectors.toSet());
+        Map<String, Set<String>> edges = new HashMap<>();
+        this.graph.edges().keySet().stream()
+                .forEach(m -> {
+                    String mn = m.name();
+                    Set<String> es = edges.computeIfAbsent(mn, _k -> new HashSet<String>());
+                    this.graph.edges().get(m).stream()
+                            .map(Module::name)
+                            .forEach(es::add);
+                });
+
+        // transitive reduction
+        Graph<String> newGraph = new Graph<>(nodes, edges).reduce(rbg);
+        if (traceOn) {
+            System.out.println("after transitive reduction");
+            newGraph.printGraph(System.out);
+        };
+
+        Set<String> reducedRequires = newGraph.adjacentNodes(moduleName);
+        if (matches(root.descriptor(), requires, requiresPublic) &&
+                matches(root.descriptor(), reducedRequires, requiresPublic)) {
+            System.out.println("--- Analysis result: no change for " + root.name());
+        } else {
+            System.out.println("--- Analysis result: suggested requires for " + root.name());
+            System.out.format("module %s%n", root.name());
+                requires.stream()
+                        .sorted()
+                        .forEach(dn -> System.out.format("  requires %s%s;%n",
+                                requiresPublic.contains(dn) ? "public " : "", dn));
+            if (!requires.equals(reducedRequires) && !reducedRequires.isEmpty()) {
+                System.out.format("%nmodule %s (reduced)%n", root.name());
+                newGraph.adjacentNodes(moduleName)
+                     .stream()
+                     .sorted()
+                     .forEach(dn -> System.out.format("  requires %s%s;%n",
+                                requiresPublic.contains(dn) ? "public " : "", dn));
+            }
+            System.out.println("\n---  Module descriptor");
+            Graph<Module> mdGraph = graph(modulePaths, root);
+            mdGraph.reverse(m -> printModuleDescriptor(System.out, m.descriptor()));
+        }
+    }
+
+    /**
+     * Detects any qualified exports not used by the target module.
+     */
+    private void checkQualifiedExports() throws IOException {
+        Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
+        analyzer.run(dependencyFinder.roots());
+
+        // build the qualified exports map
+        Map<String, Set<String>> qualifiedExports =
+            root.exports().entrySet().stream()
+                .filter(e -> !e.getValue().isEmpty())
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toMap(Function.identity(), _k -> new HashSet<>()));
+
+        // adds to the qualified exports map if a module references it
+        for (Module m : exportTargets) {
+            analyzer.dependences(m).stream()
+                    .map(this::toPackageName)
+                    .filter(qualifiedExports::containsKey)
+                    .forEach(pn -> qualifiedExports.get(pn).add(m.name()));
+        }
+
+        // compare with the exports from ModuleDescriptor
+        Set<String> staleQualifiedExports =
+            qualifiedExports.keySet().stream()
+                .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn)))
+                .collect(Collectors.toSet());
+
+        if (!staleQualifiedExports.isEmpty()) {
+            System.out.println("--- Unused qualified exports in " + root.name());
+            for (String pn : staleQualifiedExports) {
+                Set<String> unused = new HashSet<>(root.exports().get(pn));
+                unused.removeAll(qualifiedExports.get(pn));
+                System.out.format("  exports %s to %s%n", pn,
+                                  unused.stream().collect(Collectors.joining(",")));
+            }
+        }
+    }
+
+    private String toPackageName(String cn) {
+        int i = cn.lastIndexOf('.');
+        return i > 0 ? cn.substring(0, i) : "";
+    }
+
+    private boolean matches(ModuleDescriptor md, Set<String> requires, Set<String> requiresPublic) {
+        Set<String> reqPublic = md.requires().stream()
+                .filter(req -> req.modifiers().contains(PUBLIC))
+                .map(ModuleDescriptor.Requires::name)
+                .collect(Collectors.toSet());
+        if (!requiresPublic.equals(reqPublic)) {
+            trace("mismatch requires public: %s%n", reqPublic);
+            return false;
+        }
+        // java.base is not in requires
+        int javaBase = md.name().equals(JAVA_BASE.name()) ? 0 : 1;
+        if (requires.size()+javaBase != md.requires().size()) {
+            trace("mismatch requires: %d != %d%n", requires.size()+1, md.requires().size());
+            return false;
+        }
+
+        Set<String> unused = md.requires().stream()
+                 .map(ModuleDescriptor.Requires::name)
+                 .filter(req -> !requires.contains(req) && !req.equals(JAVA_BASE.name()))
+                 .collect(Collectors.toSet());
+        if (!unused.isEmpty()) {
+            trace("mismatch requires: %s%n", unused);
+            return false;
+        }
+        return true;
+    }
+
+    private void printModuleDescriptor(PrintStream out, ModuleDescriptor descriptor) {
+        if (descriptor.name().equals("java.base"))
+            return;
+
+        out.format("module %s%n", descriptor.name());
+        descriptor.requires()
+                .stream()
+                .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
+                .forEach(req -> out.format("  requires %s;%n", req));
+    }
+
+    /**
+     * Returns a graph of modules required by the specified module.
+     *
+     * Requires public edges of the dependences are added to the graph.
+     */
+    private Graph<Module> buildGraph(Analyzer analyzer, Module module) {
+        Graph.Builder<Module> builder = new Graph.Builder<>();
+        builder.addNode(module);
+        Set<Module> visited = new HashSet<>();
+        visited.add(module);
+        Deque<Module> deque = new LinkedList<>();
+        analyzer.requires(module)
+                .map(Archive::getModule)
+                .filter(m -> m != JAVA_BASE)
+                .forEach(m -> {
+                    deque.add(m);
+                    builder.addEdge(module, m);
+                });
+
+        // read requires public from ModuleDescription
+        Module source;
+        while ((source = deque.poll()) != null) {
+            if (visited.contains(source))
+                continue;
+            visited.add(source);
+            builder.addNode(source);
+            Module from = source;
+            source.descriptor().requires().stream()
+                    .filter(req -> req.modifiers().contains(PUBLIC))
+                    .map(ModuleDescriptor.Requires::name)
+                    .map(req -> modulePaths.getModules().get(req))
+                    .filter(m -> m != JAVA_BASE)
+                    .forEach(m -> {
+                        deque.add(m);
+                        builder.addEdge(from, m);
+                    });
+        }
+        return builder.build();
+    }
+
+    static class Graph<T> {
+        private final Set<T> nodes;
+        private final Map<T, Set<T>> edges;
+
+        private Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+            this.nodes = nodes;
+            this.edges = edges;
+        }
+
+        public Set<T> nodes() {
+            return nodes;
+        }
+
+        public Map<T, Set<T>> edges() {
+            return edges;
+        }
+
+        public Set<T> adjacentNodes(T u) {
+            return edges.get(u);
+        }
+
+        /**
+         * Returns a new Graph after transitive reduction
+         */
+        public Graph<T> reduce() {
+            Graph.Builder<T> builder = new Builder<>();
+            nodes.stream()
+                    .forEach(u -> {
+                        builder.addNode(u);
+                        edges.get(u).stream()
+                                .filter(v -> !pathExists(u, v, false))
+                                .forEach(v -> builder.addEdge(u, v));
+                    });
+            return builder.build();
+        }
+
+        /**
+         * Returns a new Graph after transitive reduction.  All edges in
+         * the given g takes precedence over this graph.
+         *
+         * @throw IllegalArgumentException g must be a subgraph this graph
+         */
+        public Graph<T> reduce(Graph<T> g) {
+            boolean subgraph = nodes.containsAll(g.nodes) && g.edges.keySet().stream()
+                    .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u)));
+            if (!subgraph) {
+                throw new IllegalArgumentException(g + " is not a subgraph of " + this);
+            }
+
+            Graph.Builder<T> builder = new Builder<>();
+            nodes.stream()
+                    .forEach(u -> {
+                        builder.addNode(u);
+                        // filter the edge if there exists a path from u to v in the given g
+                        // or there exists another path from u to v in this graph
+                        edges.get(u).stream()
+                                .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false))
+                                .forEach(v -> builder.addEdge(u, v));
+                    });
+
+            // add the overlapped edges from this graph and the given g
+            g.edges().keySet().stream()
+                    .forEach(u -> g.adjacentNodes(u).stream()
+                                    .filter(v -> isAdjacent(u, v))
+                                    .forEach(v -> builder.addEdge(u, v)));
+            return builder.build();
+        }
+
+        /**
+         * Returns nodes sorted in topological order.
+         */
+        public Stream<T> orderedNodes() {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            return sorter.result.stream();
+        }
+
+        /**
+         * Iterates the nodes sorted in topological order and performs the
+         * given action.
+         */
+        public void ordered(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.ordered(action);
+        }
+
+        /**
+         * Iterates the nodes sorted in reverse topological order and
+         * performs the given action.
+         */
+        public void reverse(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.reverse(action);
+        }
+
+        private boolean isAdjacent(T u, T v) {
+            return edges.containsKey(u) && edges.get(u).contains(v);
+        }
+
+        private boolean pathExists(T u, T v) {
+            return pathExists(u, v, true);
+        }
+
+        /**
+         * Returns true if there exists a path from u to v in this graph.
+         * If includeAdjacent is false, it returns true if there exists
+         * another path from u to v of distance > 1
+         */
+        private boolean pathExists(T u, T v, boolean includeAdjacent) {
+            if (!nodes.contains(u) || !nodes.contains(v)) {
+                return false;
+            }
+            if (includeAdjacent && isAdjacent(u, v)) {
+                return true;
+            }
+            Deque<T> stack = new LinkedList<>();
+            Set<T> visited = new HashSet<>();
+            stack.push(u);
+            while (!stack.isEmpty()) {
+                T node = stack.pop();
+                if (node.equals(v)) {
+                    return true;
+                }
+                if (!visited.contains(node)) {
+                    visited.add(node);
+                    edges.get(node).stream()
+                            .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v))
+                            .forEach(e -> stack.push(e));
+                }
+            }
+            assert !visited.contains(v);
+            return false;
+        }
+
+        void printGraph(PrintStream out) {
+            out.println("graph for " + nodes);
+            nodes.stream()
+                 .forEach(u -> adjacentNodes(u).stream()
+                                   .forEach(v -> out.format("%s -> %s%n", u, v)));
+        }
+
+        @Override
+        public String toString() {
+            return nodes.toString();
+        }
+
+        static class Builder<T> {
+            final Set<T> nodes = new HashSet<>();
+            final Map<T, Set<T>> edges = new HashMap<>();
+
+            public void addNode(T node) {
+                if (nodes.contains(node)) {
+                    return;
+                }
+                nodes.add(node);
+                edges.computeIfAbsent(node, _e -> new HashSet<>());
+            }
+
+            public void addEdge(T u, T v) {
+                addNode(u);
+                addNode(v);
+                edges.get(u).add(v);
+            }
+
+            public Graph<T> build() {
+                return new Graph<>(nodes, edges);
+            }
+
+            void print(PrintStream out) {
+                out.println(nodes);
+                nodes.stream()
+                        .forEach(u -> edges.get(u).stream()
+                                        .forEach(v -> out.format("%s -> %s%n", u, v)));
+            }
+        }
+    }
+
+    static class TopoSorter<T> {
+        final Deque<T> result = new LinkedList<>();
+        final Deque<T> nodes;
+        final Graph<T> graph;
+        TopoSorter(Graph<T> graph) {
+            this.graph = graph;
+            this.nodes = new LinkedList<>(graph.nodes);
+            sort();
+        }
+
+        public void ordered(Consumer<T> action) {
+            result.iterator().forEachRemaining(action);
+        }
+
+        public void reverse(Consumer<T> action) {
+            result.descendingIterator().forEachRemaining(action);
+        }
+
+        private void sort() {
+            Deque<T> visited = new LinkedList<>();
+            Deque<T> done = new LinkedList<>();
+            T node;
+            while ((node = nodes.poll()) != null) {
+                if (!visited.contains(node)) {
+                    visit(node, visited, done);
+                }
+            }
+        }
+
+        private void visit(T node, Deque<T> visited, Deque<T> done) {
+            if (visited.contains(node)) {
+                if (!done.contains(node)) {
+                    throw new IllegalArgumentException("Cyclic detected: " +
+                            node + " " + graph.edges().get(node));
+                }
+                return;
+            }
+            visited.add(node);
+            graph.edges().get(node).stream()
+                 .forEach(x -> visit(x, visited, done));
+            done.add(node);
+            result.addLast(node);
+        }
+    }
+
+    static class DotGraph {
+        static final String ORANGE = "#e76f00";
+        static final String BLUE = "#437291";
+        static final String GRAY = "#dddddd";
+
+        static final String REEXPORTS = "";
+        static final String REQUIRES = "style=\"dashed\"";
+        static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
+
+        static final Set<String> javaModules = modules(name ->
+                (name.startsWith("java.") && !name.equals("java.smartcardio")));
+        static final Set<String> jdkModules = modules(name ->
+                (name.startsWith("java.") ||
+                        name.startsWith("jdk.") ||
+                        name.startsWith("javafx.")) && !javaModules.contains(name));
+
+        private static Set<String> modules(Predicate<String> predicate) {
+            return ModuleFinder.ofSystem().findAll()
+                               .stream()
+                               .map(ModuleReference::descriptor)
+                               .map(ModuleDescriptor::name)
+                               .filter(predicate)
+                               .collect(Collectors.toSet());
+        }
+
+        static void printAttributes(PrintStream out) {
+            out.format("  size=\"25,25\";%n");
+            out.format("  nodesep=.5;%n");
+            out.format("  ranksep=1.5;%n");
+            out.format("  pencolor=transparent;%n");
+            out.format("  node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n");
+            out.format("  edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n");
+        }
+
+        static void printNodes(PrintStream out, Graph<String> graph) {
+            out.format("  subgraph se {%n");
+            graph.nodes().stream()
+                 .filter(javaModules::contains)
+                 .forEach(mn -> out.format("  \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                           mn, ORANGE, "java"));
+            out.format("  }%n");
+            graph.nodes().stream()
+                 .filter(jdkModules::contains)
+                 .forEach(mn -> out.format("    \"%s\" [fontcolor=\"%s\", group=%s];%n",
+                                              mn, BLUE, "jdk"));
+
+            graph.nodes().stream()
+                    .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn))
+                    .forEach(mn -> out.format("  \"%s\";%n", mn));
+        }
+
+        static void printEdges(PrintStream out, Graph<String> graph,
+                               String node, Set<String> requiresPublic) {
+            graph.adjacentNodes(node).forEach(dn -> {
+                String attr = dn.equals("java.base") ? REQUIRES_BASE
+                        : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
+                out.format("  \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
+            });
+        }
+    }
+
+    public void genDotFile(Path dir) throws IOException {
+        String name = root.name();
+        try (PrintStream out
+                     = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
+            Configuration cf = modulePaths.configuration(name);
+
+            // transitive reduction
+            Graph<String> graph = gengraph(cf);
+
+            out.format("digraph \"%s\" {%n", name);
+            DotGraph.printAttributes(out);
+            DotGraph.printNodes(out, graph);
+
+            cf.modules().stream()
+                    .map(ResolvedModule::reference)
+                    .map(ModuleReference::descriptor)
+                    .sorted(Comparator.comparing(ModuleDescriptor::name))
+                    .forEach(md -> {
+                String mn = md.name();
+                Set<String> requiresPublic = md.requires().stream()
+                        .filter(d -> d.modifiers().contains(PUBLIC))
+                        .map(d -> d.name())
+                        .collect(Collectors.toSet());
+
+                DotGraph.printEdges(out, graph, mn, requiresPublic);
+            });
+
+            out.println("}");
+        }
+    }
+
+
+    /**
+     * 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
+     * (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(Configuration cf) {
+        // build a Graph containing only requires public edges
+        // with transitive reduction.
+        Graph.Builder<String> rpgbuilder = new Graph.Builder<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor md = resolvedModule.reference().descriptor();
+            String mn = md.name();
+            md.requires().stream()
+                    .filter(d -> d.modifiers().contains(PUBLIC))
+                    .map(d -> d.name())
+                    .forEach(d -> rpgbuilder.addEdge(mn, d));
+        }
+
+        Graph<String> rpg = rpgbuilder.build().reduce();
+
+        // build the readability graph
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            ModuleDescriptor md = resolvedModule.reference().descriptor();
+            String mn = md.name();
+            builder.addNode(mn);
+            resolvedModule.reads().stream()
+                    .map(ResolvedModule::name)
+                    .forEach(d -> builder.addEdge(mn, d));
+        }
+
+        // transitive reduction of requires edges
+        return builder.build().reduce(rpg);
+    }
+
+}
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
new file mode 100644
index 0000000..1afed6b
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import static com.sun.tools.jdeps.Analyzer.Type.CLASS;
+import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
+import static com.sun.tools.jdeps.Module.trace;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ModuleInfoBuilder {
+    final ModulePaths modulePaths;
+    final DependencyFinder dependencyFinder;
+    final JdepsFilter filter;
+    final Analyzer analyzer;
+    final Map<Module, Module> strictModules = new HashMap<>();
+    ModuleInfoBuilder(ModulePaths modulePaths, DependencyFinder finder) {
+        this.modulePaths = modulePaths;
+        this.dependencyFinder = finder;
+        this.filter = new JdepsFilter.Builder().filter(true, true).build();
+        this.analyzer = new Analyzer(CLASS, filter);
+    }
+
+    private Stream<Module> automaticModules() {
+        return modulePaths.getModules().values()
+                .stream()
+                .filter(Module::isAutomatic);
+    }
+
+    /**
+     * Compute 'requires public' dependences by analyzing API dependencies
+     */
+    Map<Module, Set<Module>> computeRequiresPublic() throws IOException {
+        dependencyFinder.findDependencies(filter, true /* api only */, 1);
+        Analyzer pass1 = new Analyzer(Analyzer.Type.CLASS, filter);
+
+        pass1.run(dependencyFinder.archives());
+
+        return automaticModules().collect(Collectors.toMap(Function.identity(),
+                source -> pass1.requires(source)
+                               .map(Archive::getModule)
+                               .collect(Collectors.toSet())));
+    }
+
+    boolean run(Analyzer.Type verbose, boolean quiet) throws IOException {
+        // add all automatic modules to the root set
+        automaticModules().forEach(dependencyFinder::addRoot);
+
+        // pass 1: find API dependencies
+        Map<Module, Set<Module>> requiresPublic = computeRequiresPublic();
+
+        // pass 2: analyze all class dependences
+        dependencyFinder.findDependencies(filter, false /* all classes */, 1);
+        analyzer.run(dependencyFinder.archives());
+
+        // computes requires and requires public
+        automaticModules().forEach(m -> {
+            Map<String, Boolean> requires;
+            if (requiresPublic.containsKey(m)) {
+                requires = requiresPublic.get(m)
+                        .stream()
+                        .collect(Collectors.toMap(Archive::getName, (v) -> Boolean.TRUE));
+            } else {
+                requires = new HashMap<>();
+            }
+            analyzer.requires(m)
+                    .forEach(d -> requires.putIfAbsent(d.getName(), Boolean.FALSE));
+
+            trace("strict module %s requires %s%n", m.name(), requires);
+            strictModules.put(m, m.toStrictModule(requires));
+        });
+
+        // find any missing dependences
+        Optional<Module> missingDeps = automaticModules()
+                .filter(this::missingDep)
+                .findAny();
+        if (missingDeps.isPresent()) {
+            automaticModules()
+                    .filter(this::missingDep)
+                    .forEach(m -> {
+                        System.err.format("Missing dependencies from %s%n", m.name());
+                        analyzer.visitDependences(m,
+                                new Analyzer.Visitor() {
+                                    @Override
+                                    public void visitDependence(String origin, Archive originArchive,
+                                                                String target, Archive targetArchive) {
+                                        if (targetArchive == NOT_FOUND)
+                                            System.err.format("   %-50s -> %-50s %s%n",
+                                                    origin, target, targetArchive.getName());
+                                    }
+                                }, verbose);
+                        System.err.println();
+                    });
+
+            System.err.println("ERROR: missing dependencies (check \"requires NOT_FOUND;\")");
+        }
+        return missingDeps.isPresent() ? false : true;
+    }
+
+    private boolean missingDep(Archive m) {
+        return analyzer.requires(m).filter(a -> a.equals(NOT_FOUND))
+                       .findAny().isPresent();
+    }
+
+    void build(Path dir) throws IOException {
+        ModuleInfoWriter writer = new ModuleInfoWriter(dir);
+        writer.generateOutput(strictModules.values(), analyzer);
+    }
+
+    private class ModuleInfoWriter {
+        private final Path outputDir;
+        ModuleInfoWriter(Path dir) {
+            this.outputDir = dir;
+        }
+
+        void generateOutput(Iterable<Module> modules, Analyzer analyzer) throws IOException {
+            // generate module-info.java file for each archive
+            for (Module m : modules) {
+                if (m.packages().contains("")) {
+                    System.err.format("ERROR: %s contains unnamed package.  " +
+                                      "module-info.java not generated%n", m.getPathName());
+                    continue;
+                }
+
+                String mn = m.getName();
+                Path srcFile = outputDir.resolve(mn).resolve("module-info.java");
+                Files.createDirectories(srcFile.getParent());
+                System.out.println("writing to " + srcFile);
+                try (PrintWriter pw = new PrintWriter(Files.newOutputStream(srcFile))) {
+                    printModuleInfo(pw, m);
+                }
+            }
+        }
+
+        private void printModuleInfo(PrintWriter writer, Module m) {
+            writer.format("module %s {%n", m.name());
+
+            Map<String, Module> modules = modulePaths.getModules();
+            Map<String, Boolean> requires = m.requires();
+            // first print the JDK modules
+            requires.keySet().stream()
+                    .filter(mn -> !mn.equals("java.base"))   // implicit requires
+                    .filter(mn -> modules.containsKey(mn) && modules.get(mn).isJDK())
+                    .sorted()
+                    .forEach(mn -> {
+                        String modifier = requires.get(mn) ? "public " : "";
+                        writer.format("    requires %s%s;%n", modifier, mn);
+                    });
+
+            // print requires non-JDK modules
+            requires.keySet().stream()
+                    .filter(mn -> !modules.containsKey(mn) || !modules.get(mn).isJDK())
+                    .sorted()
+                    .forEach(mn -> {
+                        String modifier = requires.get(mn) ? "public " : "";
+                        writer.format("    requires %s%s;%n", modifier, mn);
+                    });
+
+            m.packages().stream()
+                    .sorted()
+                    .forEach(pn -> writer.format("    exports %s;%n", pn));
+
+            m.provides().entrySet().stream()
+                    .sorted(Map.Entry.comparingByKey())
+                    .forEach(e -> {
+                        String service = e.getKey();
+                        e.getValue().stream()
+                                .sorted()
+                                .forEach(impl -> writer.format("    provides %s with %s;%n", service, impl));
+                    });
+
+            writer.println("}");
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java
new file mode 100644
index 0000000..8e1cdb8
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeps;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+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.ResolvedModule;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+public class ModulePaths {
+    final ModuleFinder finder;
+    final Map<String, Module> modules = new LinkedHashMap<>();
+
+    public ModulePaths(String upgradeModulePath, String modulePath) {
+        this(upgradeModulePath, modulePath, Collections.emptyList());
+    }
+
+    public ModulePaths(String upgradeModulePath, String modulePath, List<Path> jars) {
+        ModuleFinder finder = ModuleFinder.ofSystem();
+        if (upgradeModulePath != null) {
+            finder = ModuleFinder.compose(createModulePathFinder(upgradeModulePath), finder);
+        }
+        if (jars.size() > 0) {
+            finder = ModuleFinder.compose(finder, ModuleFinder.of(jars.toArray(new Path[0])));
+        }
+        if (modulePath != null) {
+            finder = ModuleFinder.compose(finder, createModulePathFinder(modulePath));
+        }
+        this.finder = finder;
+
+        // add modules from modulepaths
+        finder.findAll().stream().forEach(mref ->
+            modules.computeIfAbsent(mref.descriptor().name(), mn -> toModule(mn, mref))
+        );
+    }
+
+    /**
+     * Returns the list of Modules that can be found in the specified
+     * module paths.
+     */
+    Map<String, Module> getModules() {
+        return modules;
+    }
+
+    Set<Module> dependences(String... roots) {
+        Configuration cf = configuration(roots);
+        return cf.modules().stream()
+                .map(ResolvedModule::name)
+                .map(modules::get)
+                .collect(Collectors.toSet());
+    }
+
+    Configuration configuration(String... roots) {
+        return Configuration.empty().resolveRequires(finder, ModuleFinder.empty(), Set.of(roots));
+    }
+
+    private static ModuleFinder createModulePathFinder(String mpaths) {
+        if (mpaths == null) {
+            return null;
+        } else {
+            String[] dirs = mpaths.split(File.pathSeparator);
+            Path[] paths = new Path[dirs.length];
+            int i = 0;
+            for (String dir : dirs) {
+                paths[i++] = Paths.get(dir);
+            }
+            return ModuleFinder.of(paths);
+        }
+    }
+
+    private static Module toModule(String mn, ModuleReference mref) {
+        return SystemModulePath.find(mn)
+                               .orElse(toModule(new Module.Builder(mn), mref));
+    }
+
+    private static Module toModule(Module.Builder builder, ModuleReference mref) {
+        ModuleDescriptor md = mref.descriptor();
+        builder.descriptor(md);
+        for (ModuleDescriptor.Requires req : md.requires()) {
+            builder.require(req.name(), req.modifiers().contains(PUBLIC));
+        }
+        for (ModuleDescriptor.Exports exp : md.exports()) {
+            builder.export(exp.source(), exp.targets());
+        }
+        builder.packages(md.packages());
+
+        try {
+            URI location = mref.location()
+                               .orElseThrow(FileNotFoundException::new);
+            builder.location(location);
+            builder.classes(getClassReader(location, md.name()));
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return builder.build();
+    }
+
+    static class SystemModulePath {
+        final static Module JAVA_BASE;
+
+        private final static FileSystem fs;
+        private final static Path root;
+        private final static Map<String, Module> installed = new HashMap<>();
+        static {
+            if (isJrtAvailable()) {
+                // jrt file system
+                fs = FileSystems.getFileSystem(URI.create("jrt:/"));
+                root = fs.getPath("/modules");
+            } else {
+                // exploded image
+                String javahome = System.getProperty("java.home");
+                fs = FileSystems.getDefault();
+                root = Paths.get(javahome, "modules");
+            }
+
+            ModuleFinder.ofSystem().findAll().stream()
+                 .forEach(mref ->
+                     installed.computeIfAbsent(mref.descriptor().name(),
+                                               mn -> toModule(new Module.Builder(mn, true), mref))
+                 );
+            JAVA_BASE = installed.get("java.base");
+
+            Profile.init(installed);
+        }
+
+        private static boolean isJrtAvailable() {
+            try {
+                FileSystems.getFileSystem(URI.create("jrt:/"));
+                return true;
+            } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
+                return false;
+            }
+        }
+
+        public static Optional<Module> find(String mn) {
+            return installed.containsKey(mn) ? Optional.of(installed.get(mn))
+                                             : Optional.empty();
+        }
+
+        public static boolean contains(Module m) {
+            return installed.containsValue(m);
+        }
+
+        public static ClassFileReader getClassReader(String modulename) throws IOException {
+            Path mp = root.resolve(modulename);
+            if (Files.exists(mp) && Files.isDirectory(mp)) {
+                return ClassFileReader.newInstance(fs, mp);
+            } else {
+                throw new FileNotFoundException(mp.toString());
+            }
+        }
+    }
+
+    /**
+     * Returns a ModuleClassReader that only reads classes for the given modulename.
+     */
+    public static ClassFileReader getClassReader(URI location, String modulename)
+            throws IOException {
+        if (location.getScheme().equals("jrt")) {
+            return SystemModulePath.getClassReader(modulename);
+        } else {
+            Path path = Paths.get(location);
+            return ClassFileReader.newInstance(path);
+        }
+    }
+}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java
deleted file mode 100644
index be9d3d3..0000000
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.jdeps;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Set;
-import javax.xml.namespace.QName;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.XMLEvent;
-import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
-import com.sun.tools.jdeps.PlatformClassPath.ImageHelper;
-
-final class ModulesXmlReader {
-    public static Set<Module> load(ImageHelper helper,InputStream in)
-        throws IOException
-    {
-        try {
-            ModulesXmlReader reader = new ModulesXmlReader(helper);
-            return reader.load(in);
-        } catch (XMLStreamException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static final String MODULES   = "modules";
-    private static final String MODULE    = "module";
-    private static final String NAME      = "name";
-    private static final String DEPEND    = "depend";
-    private static final String EXPORT    = "export";
-    private static final String TO        = "to";
-    private static final QName  REEXPORTS = new QName("re-exports");
-    private final ImageHelper helper;
-    ModulesXmlReader(ImageHelper helper) {
-        this.helper = helper;
-    }
-
-    public Set<Module> load(InputStream in) throws XMLStreamException, IOException {
-        Set<Module> modules = new HashSet<>();
-        if (in == null) {
-            throw new RuntimeException("jdeps-modules.xml doesn't exist");
-        }
-        XMLInputFactory factory = XMLInputFactory.newInstance();
-        XMLEventReader reader = factory.createXMLEventReader(in, "UTF-8");
-        Module.Builder mb = null;
-        String modulename = null;
-        String exportedPackage = null;
-        Set<String> permits = new HashSet<>();
-        while (reader.hasNext()) {
-            XMLEvent event = reader.nextEvent();
-            if (event.isStartElement()) {
-                String startTag = event.asStartElement().getName().getLocalPart();
-                switch (startTag) {
-                    case MODULES:
-                        break;
-                    case MODULE:
-                        if (mb != null) {
-                            throw new RuntimeException("end tag for module is missing");
-                        }
-                        modulename = getNextTag(reader, NAME);
-                        mb = new Module.Builder();
-                        mb.name(modulename);
-                        break;
-                    case NAME:
-                        throw new RuntimeException(event.toString());
-                    case DEPEND:
-                        boolean reexports = false;
-                        Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS);
-                        if (attr != null) {
-                            String value = attr.getValue();
-                            if (value.equals("true") || value.equals("false")) {
-                                reexports = Boolean.parseBoolean(value);
-                            } else {
-                                throw new RuntimeException("unexpected attribute " + attr.toString());
-                            }
-                        }
-                        mb.require(getData(reader), reexports);
-                        break;
-                    case EXPORT:
-                        exportedPackage = getNextTag(reader, NAME);
-                        break;
-                    case TO:
-                        permits.add(getData(reader));
-                        break;
-                    default:
-                        throw new RuntimeException("invalid element: " + event);
-                }
-            } else if (event.isEndElement()) {
-                String endTag = event.asEndElement().getName().getLocalPart();
-                switch (endTag) {
-                    case MODULE:
-                        ModuleClassReader cfr = helper.getModuleClassReader(modulename);
-                        mb.classes(cfr);
-                        mb.packages(cfr.packages());
-                        modules.add(mb.build());
-                        mb = null;
-                        break;
-                    case EXPORT:
-                        if (exportedPackage == null) {
-                            throw new RuntimeException("export's name is missing");
-                        }
-                        mb.export(exportedPackage, permits);
-                        exportedPackage = null;
-                        permits.clear();
-                        break;
-                    default:
-                }
-            } else if (event.isCharacters()) {
-                String s = event.asCharacters().getData();
-                if (!s.trim().isEmpty()) {
-                    throw new RuntimeException("export-to is malformed");
-                }
-            }
-        }
-        return modules;
-    }
-    private String getData(XMLEventReader reader) throws XMLStreamException {
-        XMLEvent e = reader.nextEvent();
-        if (e.isCharacters()) {
-            return e.asCharacters().getData();
-        }
-        throw new RuntimeException(e.toString());
-    }
-
-    private String getNextTag(XMLEventReader reader, String tag) throws XMLStreamException {
-        XMLEvent e = reader.nextTag();
-        if (e.isStartElement()) {
-            String t = e.asStartElement().getName().getLocalPart();
-            if (!tag.equals(t)) {
-                throw new RuntimeException(e + " expected: " + tag);
-            }
-            return getData(reader);
-        }
-        throw new RuntimeException("export-to name is missing:" + e);
-    }
-}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
deleted file mode 100644
index 6142b4b..0000000
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.jdeps;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.jdeps.ClassFileReader.ModuleClassReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.net.URI;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * ClassPath for Java SE and JDK
- */
-class PlatformClassPath {
-    private static List<Archive> modules;
-    static synchronized List<Archive> getModules(Path mpath) throws IOException {
-        if (modules == null) {
-            initPlatformModules(mpath);
-        }
-        return modules;
-    }
-
-    private static void initPlatformModules(Path mpath) throws IOException {
-        ImageHelper helper = ImageHelper.getInstance(mpath);
-        String fn = System.getProperty("jdeps.modules.xml");
-        if (fn != null) {
-            Path p = Paths.get(fn);
-            try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
-                modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
-            }
-        } else {
-            try (InputStream in = PlatformClassPath.class
-                    .getResourceAsStream("resources/jdeps-modules.xml")) {
-                modules = new ArrayList<>(ModulesXmlReader.load(helper, in));
-            }
-        }
-        if (findModule("java.base") != null) {
-            Profile.initProfiles(modules);
-        }
-    }
-
-    /**
-     * Finds the module with the given name. Returns null
-     * if such module doesn't exist.
-     *
-     * @param mn module name
-     */
-    static Module findModule(String mn) {
-        for (Archive a : modules) {
-            if (Module.class.isInstance(a)) {
-                Module m = (Module)a;
-                if (mn.equals(m.name())) {
-                    return m;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns JAR files in $java.home/lib.  This is for transition until
-     * all components are linked into jimage.
-     */
-    static List<Archive> getJarFiles() throws IOException {
-        Path home = Paths.get(System.getProperty("java.home"), "lib");
-        return Files.find(home, 1, (Path p, BasicFileAttributes attr)
-                -> p.getFileName().toString().endsWith(".jar"))
-                .map(Archive::getInstance)
-                .collect(Collectors.toList());
-    }
-
-    static class ImageHelper {
-        private static boolean isJrtAvailable() {
-            try {
-                FileSystems.getFileSystem(URI.create("jrt:/"));
-                return true;
-            } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
-                return false;
-            }
-        }
-
-        static ImageHelper getInstance(Path mpath) throws IOException {
-            if (mpath != null) {
-                return new ImageHelper(mpath);
-            }
-
-            if (isJrtAvailable()) {
-                // jrt file system
-                FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-                return new ImageHelper(fs, fs.getPath("/modules"));
-            } else {
-                // exploded modules
-                String home = System.getProperty("java.home");
-                Path exploded = Paths.get(home, "modules");
-                if (!Files.isDirectory(exploded)) {
-                     throw new InternalError(home + " not a modular image");
-                }
-                return new ImageHelper(exploded);
-            }
-        }
-
-        private final FileSystem fs;
-        private final Path mpath;
-
-        ImageHelper(Path path) throws IOException {
-            this(FileSystems.getDefault(), path);
-        }
-
-        ImageHelper(FileSystem fs, Path path) throws IOException {
-            this.fs = fs;
-            this.mpath = path;
-        }
-
-        /**
-         * Returns a ModuleClassReader that only reads classes for the given modulename.
-         */
-        public ModuleClassReader getModuleClassReader(String modulename)
-            throws IOException
-        {
-            Path mp = mpath.resolve(modulename);
-            if (Files.exists(mp) && Files.isDirectory(mp)) {
-                return new ModuleClassReader(fs, modulename, mp);
-            } else {
-                // aggregator module or os-specific module in jdeps-modules.xml
-                // mdir not exist
-                return new NonExistModuleReader(fs, modulename, mp);
-            }
-        }
-
-        static class NonExistModuleReader extends ModuleClassReader {
-            private final List<ClassFile> classes = Collections.emptyList();
-
-            private NonExistModuleReader(FileSystem fs, String mn, Path mpath)
-                throws IOException
-            {
-                super(fs, mn, mpath);
-            }
-
-            public ClassFile getClassFile(String name) throws IOException {
-                return null;
-            }
-
-            public Iterable<ClassFile> getClassFiles() throws IOException {
-                return classes;
-            }
-
-            public Set<String> packages() {
-                return Collections.emptySet();
-            }
-        }
-    }
-}
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
index 1c45a2f..c0790ab 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, 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
@@ -26,7 +26,10 @@
 package com.sun.tools.jdeps;
 
 import java.io.IOException;
-import java.util.*;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Build the profile information.
@@ -38,7 +41,12 @@
                             "jdk.httpserver", "jdk.security.auth",
                             "jdk.naming.dns", "jdk.naming.rmi",
                             "jdk.management"),
-    FULL_JRE("Full JRE", 4, "java.se", "jdk.charsets",
+    // need a way to determine JRE modules
+    SE_JRE("Java SE JRE", 4, "java.se", "jdk.charsets",
+                            "jdk.crypto.ec", "jdk.crypto.pkcs11",
+                            "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
+                            "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"),
+    FULL_JRE("Full JRE", 5, "java.se.ee", "jdk.charsets",
                             "jdk.crypto.ec", "jdk.crypto.pkcs11",
                             "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
                             "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs");
@@ -94,25 +102,27 @@
     }
 
     private final static Set<Module> JDK = new HashSet<>();
-    static void initProfiles(List<Archive> modules) {
-        // add all modules into  JDK
-        modules.forEach(m -> JDK.add((Module)m));
-
+    static synchronized void init(Map<String, Module> installed) {
         for (Profile p : Profile.values()) {
             for (String mn : p.mnames) {
                 // this includes platform-dependent module that may not exist
-                Module m = PlatformClassPath.findModule(mn);
+                Module m = installed.get(mn);
                 if (m != null) {
-                    p.addModule(m);
+                    p.addModule(installed, m);
                 }
             }
         }
+
+        // JDK modules should include full JRE plus other jdk.* modules
+        // Just include all installed modules.  Assume jdeps is running
+        // in JDK image
+        JDK.addAll(installed.values());
     }
 
-    private void addModule(Module m) {
+    private void addModule(Map<String, Module> installed, Module m) {
         modules.add(m);
         for (String n : m.requires().keySet()) {
-            Module d = PlatformClassPath.findModule(n);
+            Module d = installed.get(n);
             if (d == null) {
                 throw new InternalError("module " + n + " required by " +
                         m.name() + " doesn't exist");
@@ -123,7 +133,6 @@
     // for debugging
     public static void main(String[] args) throws IOException {
         // find platform modules
-        PlatformClassPath.getModules(null);
         if (Profile.getProfileCount() == 0) {
             System.err.println("No profile is present in this JDK");
         }
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 5da8667..b0fc19b 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
@@ -1,99 +1,146 @@
 main.usage.summary=\
-Usage: {0} <options> <classes...>\n\
+Usage: {0} <options> [-m <module-name> | <classes...>]\n\
 use -h, -? or -help for a list of possible options
 
 main.usage=\
-Usage: {0} <options> <classes...>\n\
-where <classes> can be a pathname to a .class file, a directory, a JAR file,\n\
-or a fully-qualified class name.  Possible options include:
+Usage: {0} <options> [-m <module-name> | <classes...>]\n\
+If -m <module-name> is specified, the specified module will be analyzed\n\
+otherwise, <classes> can be a pathname to a .class file, a directory,\n\
+a JAR file, or a fully-qualified class name.\n\
+\n\
+Possible options include:
 
 error.prefix=Error:
 warn.prefix=Warning:
 
 main.opt.h=\
-\  -h -?        -help                 Print this usage message
+\  -h -?        -help                   Print this usage message
 
 main.opt.version=\
-\  -version                           Version information
+\  -version                             Version information
 
 main.opt.v=\
-\  -v           -verbose              Print all class level dependencies\n\
-\                                     Equivalent to -verbose:class -filter:none.\n\
-\  -verbose:package                   Print package-level dependencies excluding\n\
-\                                     dependencies within the same package by default\n\
-\  -verbose:class                     Print class-level dependencies excluding\n\
-\                                     dependencies within the same package by default
+\  -v           -verbose                Print all class level dependencies\n\
+\                                       Equivalent to -verbose:class -filter:none.\n\
+\  -verbose:package                     Print package-level dependencies excluding\n\
+\                                       dependencies within the same package by default\n\
+\  -verbose:class                       Print class-level dependencies excluding\n\
+\                                       dependencies within the same package by default
 
 main.opt.f=\
-\  -f <regex>   -filter <regex>       Filter dependences matching the given pattern\n\
-\                                     If given multiple times, the last one will be used.\n\
-\  -filter:package                    Filter dependences within the same package (default)\n\
-\  -filter:archive                    Filter dependences within the same archive\n\
-\  -filter:none                       No -filter:package and -filter:archive filtering\n\
-\                                     Filtering specified via the -filter option still applies.
+\  -f <regex>  -filter <regex>          Filter dependences matching the given pattern\n\
+\                                       If given multiple times, the last one will be used.\n\
+\  -filter:package                      Filter dependences within the same package (default)\n\
+\  -filter:module                       Filter dependences within the same module\n\
+\  -filter:archive                      Filter dependences within the same archive\n\
+\  -filter:none                         No -filter:package and -filter:archive filtering\n\
+\                                       Filtering specified via the -filter option still applies.
 
 main.opt.s=\
-\  -s           -summary              Print dependency summary only
+\  -s           -summary                Print dependency summary only.\n\
+\                                       If -s option is used with -m, the module descriptor of\n\
+\                                       the given module will be read to generate the graph.
 
 main.opt.p=\
-\  -p <pkgname> -package <pkgname>    Finds dependences matching the given package name\n\
-\                                     (may be given multiple times)
+\  -p <pkgname>                         Finds dependences matching the given package name\n\
+\  -package <pkgname>                   (may be given multiple times).
 
 main.opt.e=\
-\  -e <regex>   -regex <regex>        Finds dependences matching the given pattern\n\
-\                                     (-p and -e are exclusive)
+\  -e <regex>\n\
+\  -regex <regex>                       Finds dependences matching the given pattern.
+
+main.opt.module=\
+\  -module <module-name>                Finds dependences matching the given module name\n\
+\                                       (may be given multiple times).\n\
+\                                       -package, -regex, -requires are mutual exclusive.
 
 main.opt.include=\
-\  -include <regex>                   Restrict analysis to classes matching pattern\n\
-\                                     This option filters the list of classes to\n\
-\                                     be analyzed.  It can be used together with\n\
-\                                     -p and -e which apply pattern to the dependences
+\  -include <regex>                     Restrict analysis to classes matching pattern\n\
+\                                       This option filters the list of classes to\n\
+\                                       be analyzed.  It can be used together with\n\
+\                                       -p and -e which apply pattern to the dependences
 
 main.opt.P=\
-\  -P           -profile              Show profile or the file containing a package
+\  -P           -profile                Show profile containing a package
 
 main.opt.M=\
-\  -M           -module               Show module containing the package
+\  -M                                   Show module containing a package
 
 main.opt.cp=\
-\  -cp <path>   -classpath <path>     Specify where to find class files
+\  -cp <path>   -classpath <path>       Specify where to find class files
+
+main.opt.mp=\
+\  -mp <module path>...\n\
+\  -modulepath <module path>...         Specify module path
+
+main.opt.upgrademodulepath=\
+\  -upgrademodulepath <module path>...  Specify upgrade module path
+
+main.opt.m=\
+\  -m <module-name>                     Specify the name of the module and its transitive\n\
+\                                       dependences to be analyzed.
 
 main.opt.R=\
-\  -R           -recursive            Recursively traverse all dependencies.\n\
-\                                     The -R option implies -filter:none.  If -p, -e, -f\n\
-\                                     option is specified, only the matching dependences\n\
-\                                     are analyzed.
+\  -R           -recursive              Recursively traverse all run-time dependencies.\n\
+\                                       The -R option implies -filter:none.  If -p, -e, -f\n\
+\                                       option is specified, only the matching dependences\n\
+\                                       are analyzed.
+
+main.opt.ct=\
+\  -ct          -compile-time           Compile-time view of transitive dependencies\n\
+\                                       i.e. compile-time view of -R option.  If a dependence\n\
+\                                       is found from a directory, a JAR file or a module,\n\
+\                                       all class files in that containing archive are analyzed.
 
 main.opt.apionly=\
-\  -apionly                           Restrict analysis to APIs i.e. dependences\n\
-\                                     from the signature of public and protected\n\
-\                                     members of public classes including field\n\
-\                                     type, method parameter types, returned type,\n\
-\                                     checked exception types etc
+\  -apionly                             Restrict analysis to APIs i.e. dependences\n\
+\                                       from the signature of public and protected\n\
+\                                       members of public classes including field\n\
+\                                       type, method parameter types, returned type,\n\
+\                                       checked exception types etc
+
+main.opt.genmoduleinfo=\
+\  -genmoduleinfo <dir>                 Generate module-info.java under the specified directory.\n\
+\                                       The specified JAR files will be analyzed.\n\
+\                                       This option cannot be used with -dotoutput or -cp.
+
+main.opt.check=\
+\  -check                               Analyze the dependence of a given module specified via\n\
+\                                       -m option.  It prints out the resulting module dependency\n\
+\                                       graph after transition reduction and also identifies any\n\
+\                                       unused qualified exports.
+
 
 main.opt.dotoutput=\
-\  -dotoutput <dir>                   Destination directory for DOT file output
+\  -dotoutput <dir>                     Destination directory for DOT file output
 
 main.opt.jdkinternals=\
-\  -jdkinternals                      Finds class-level dependences on JDK internal APIs.\n\
-\                                     By default, it analyzes all classes on -classpath\n\
-\                                     and input files unless -include option is specified.\n\
-\                                     This option cannot be used with -p, -e and -s options.\n\
-\                                     WARNING: JDK internal APIs may not be accessible in\n\
-\                                     the next release.
+\  -jdkinternals                        Finds class-level dependences on JDK internal APIs.\n\
+\                                       By default, it analyzes all classes on -classpath\n\
+\                                       and input files unless -include option is specified.\n\
+\                                       This option cannot be used with -p, -e and -s options.\n\
+\                                       WARNING: JDK internal APIs may not be accessible in\n\
+\                                       the next release.
 
 main.opt.depth=\
-\  -depth=<depth>                     Specify the depth of the transitive\n\
-\                                     dependency analysis
+\  -depth=<depth>                       Specify the depth of the transitive\n\
+\                                       dependency analysis
 
+main.opt.q=\
+\  -q           -quiet                  Do not show missing dependencies from -genmoduleinfo output.
 
 err.unknown.option=unknown option: {0}
 err.missing.arg=no value given for {0}
 err.invalid.arg.for.option=invalid argument for option: {0}
 err.option.after.class=option must be specified before classes: {0}
-err.option.unsupported={0} not supported: {1}
+err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be JAR file)
 err.profiles.msg=No profile information
+err.exception.message={0}
 err.invalid.path=invalid path: {0}
+err.invalid.module.option=-m {0} is set but {1} is specified.
+err.invalid.filters=Only one of -package (-p), -regex (-e), -requires option can be set
+err.module.not.found=module not found: {0}
+err.root.module.not.set=-m is not set
 warn.invalid.arg=Invalid classname or pathname not exist: {0}
 warn.split.package=package {0} defined in {1} {2}
 warn.replace.useJDKInternals=\
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
index 56d7d0a..6dd8380 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
@@ -3,6 +3,7 @@
 com.sun.image.codec=Use javax.imageio @since 1.4
 com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6
 com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8
+com.sun.org.apache.xml.internal.resolver=Use javax.xml.catalog @since 9
 com.sun.net.ssl=Use javax.net.ssl @since 1.4
 com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(provider-name) @since 1.3
 com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7
@@ -11,7 +12,7 @@
 sun.awt.image.codec=Use javax.imageio @since 1.4
 sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
 sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
-sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2
+sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
 sun.misc.Service=Use java.util.ServiceLoader @since 1.6
 sun.security.action=Use java.security.PrivilegedAction @since 1.1
 sun.security.krb5=Use com.sun.security.jgss
@@ -20,3 +21,5 @@
 sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1
 sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
 sun.tools.jar=Use java.util.jar or jar tool @since 1.2
+jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
+
diff --git a/langtools/src/jdk.jdeps/share/classes/module-info.java b/langtools/src/jdk.jdeps/share/classes/module-info.java
new file mode 100644
index 0000000..7a1f730
--- /dev/null
+++ b/langtools/src/jdk.jdeps/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+module jdk.jdeps {
+    requires java.base;
+    requires java.compiler;
+    requires jdk.compiler;
+    exports com.sun.tools.classfile to
+        jdk.jlink;
+}
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
index 5ac073b..1a0cec3 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java
@@ -113,6 +113,8 @@
                     }
                     Method doitMethod;
                     try {
+                        this.getClass().getModule().addReads(klass.getModule());
+                        this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule());
                         doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class<?>[0]);
                         doitMethod.setAccessible(true);
                         Object res;
@@ -182,6 +184,7 @@
                         break;
                     }
                     try {
+                        this.getClass().getModule().addReads(klass.getModule());
                         Field var = klass.getDeclaredField(varname);
                         var.setAccessible(true);
                         Object res = var.get(null);
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
index 8f629fd..abaa5cb 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java
@@ -257,8 +257,7 @@
 
         String connectorName = "com.sun.jdi.CommandLineLaunch";
         String classPath = System.getProperty("java.class.path");
-        String bootclassPath = System.getProperty("sun.boot.class.path");
-        String javaArgs = "-classpath \"" + classPath + "\" -Xbootclasspath:\"" + bootclassPath + "\"";
+        String javaArgs = "-classpath " + classPath;
         Map<String, String> argumentName2Value = new HashMap<>();
         argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port);
         argumentName2Value.put("options", javaArgs);
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
index 2fbb46a..c7be108 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
@@ -657,7 +657,7 @@
     private PackageElement createPackageElement(AnalyzeTask at, String packageName) {
         Names names = Names.instance(at.getContext());
         Symtab syms = Symtab.instance(at.getContext());
-        PackageElement existing = syms.enterPackage(names.fromString(packageName));
+        PackageElement existing = syms.enterPackage(syms.unnamedModule, names.fromString(packageName));
 
         return existing;
     }
@@ -1297,7 +1297,7 @@
     }
 
     static boolean isJRTMarkerFile(Path path) {
-        return path.equals(Paths.get("JRT_MARKER_FILE"));
+        return path.equals(Paths.get(System.getProperty("java.home"), "lib", "modules"));
     }
 
     //create an index based on the content of the given dirs; the original JavaFileManager entry is originalPath.
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
index f27b0c7..8ad7862 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
@@ -249,7 +249,7 @@
 
         AnalyzeTask(final Collection<Unit> units) {
             this(units.stream(), new UnitSourceHandler(),
-                    "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-proc:none");
+                    "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
         }
 
         <T>AnalyzeTask(final Stream<T> stream, SourceHandler<T> sourceHandler,
@@ -291,7 +291,7 @@
 
         CompileTask(Collection<Unit> units) {
             super(units.stream(), new UnitSourceHandler(),
-                    "-Xlint:unchecked", "-proc:none");
+                    "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none");
         }
 
         boolean compile() {
diff --git a/langtools/src/jdk.jshell/share/classes/module-info.java b/langtools/src/jdk.jshell/share/classes/module-info.java
new file mode 100644
index 0000000..93b16ba
--- /dev/null
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jshell {
+    requires public java.compiler;
+    requires java.desktop;
+    requires java.prefs;
+    requires jdk.compiler;
+    requires jdk.internal.le;
+    requires jdk.jdi;
+
+    exports jdk.jshell;
+}
diff --git a/langtools/test/Makefile b/langtools/test/Makefile
index 28e3a0e..0940c51 100644
--- a/langtools/test/Makefile
+++ b/langtools/test/Makefile
@@ -87,11 +87,21 @@
 ifdef JPRT_JTREG_HOME
   JTREG_HOME = $(JPRT_JTREG_HOME)
 else
-  JTREG_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg
+  JTREG_HOME = $(SLASH_JAVA)/re/jtreg/4.1-jigsaw/nightly/binaries/jtreg/
 endif
 JTREG = $(JTREG_HOME)/bin/jtreg
 JTDIFF = $(JTREG_HOME)/bin/jtdiff
 
+# Problematic tests to be excluded
+PROBLEM_LISTS=ProblemList.txt
+
+# Create exclude list for this platform and arch
+ifdef NO_EXCLUDES
+  JTREG_EXCLUSIONS =
+else
+  JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%)
+endif
+
 # Default JCK to run
 ifdef JPRT_JCK_HOME
   JCK_HOME = $(JPRT_JCK_HOME)
@@ -284,6 +294,7 @@
           -w:$(JTREG_OUTPUT_DIR)/JTwork \
           -jdk:$(TESTJAVA) \
           $(JAVA_ARGS:%=-vmoption:%) \
+          $(JTREG_EXCLUSIONS) \
 	  $(JTREG_OPTIONS) \
           $(JTREG_TESTDIRS) \
 	|| ( $(call EXIT_IF_FATAL,$(FATAL_JTREG_EXIT)) ; \
diff --git a/langtools/test/ProblemList.txt b/langtools/test/ProblemList.txt
index 434b3ff..00546d4 100644
--- a/langtools/test/ProblemList.txt
+++ b/langtools/test/ProblemList.txt
@@ -1,6 +1,6 @@
 ###########################################################################
 #
-# 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,4 +23,8 @@
 #
 ###########################################################################
 
-# No langtools tests are on the problem list.
+
+##### javac ####################################################################
+
+tools/javac/Paths/MineField.sh                                                  8149599	generic-all   needs rewrite
+
diff --git a/langtools/test/TEST.ROOT b/langtools/test/TEST.ROOT
index 371b81d..878d04a 100644
--- a/langtools/test/TEST.ROOT
+++ b/langtools/test/TEST.ROOT
@@ -14,5 +14,5 @@
 # Group definitions
 groups=TEST.groups
 
-# Tests using jtreg 4.1 b12 features
-requiredVersion=4.1 b12
+# Tests using jtreg 4.2 b01 features
+requiredVersion=4.2 b01
diff --git a/langtools/test/com/sun/javadoc/testCustomTag/TestCustomTag.java b/langtools/test/com/sun/javadoc/testCustomTag/TestCustomTag.java
index d417701..f715671 100644
--- a/langtools/test/com/sun/javadoc/testCustomTag/TestCustomTag.java
+++ b/langtools/test/com/sun/javadoc/testCustomTag/TestCustomTag.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
@@ -48,6 +48,7 @@
                 "-tagletpath", testSrc, // TODO: probably useless
                 "-taglet", "taglets.CustomTag",
                 "-sourcepath",  testSrc,
+                "-XDaccessInternalAPI",
                 testSrc("TagTestClass.java"));
         checkExit(Exit.OK);
 
@@ -61,6 +62,7 @@
                 "-tagletpath", testSrc,  // TODO: probably useless
                 "-taglet", "taglets.CustomTag",
                 "-sourcepath", testSrc,
+                "-XDaccessInternalAPI",
                 testSrc("TagTestClass.java"));
         checkExit(Exit.FAILED);
 
diff --git a/langtools/test/com/sun/javadoc/testCustomTag/taglets/CustomTag.java b/langtools/test/com/sun/javadoc/testCustomTag/taglets/CustomTag.java
index d38e553..cb6f9e2 100644
--- a/langtools/test/com/sun/javadoc/testCustomTag/taglets/CustomTag.java
+++ b/langtools/test/com/sun/javadoc/testCustomTag/taglets/CustomTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -23,12 +23,16 @@
 
 package taglets;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.*;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
-import com.sun.javadoc.*;
-import java.util.*;
 
 public class CustomTag extends BaseTaglet {
 
diff --git a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java
index 9d1f63c..2b05eda 100644
--- a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java
+++ b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8072945 8081854 8141492 8148985
+ * @bug 8072945 8081854 8141492 8148985 8150188
  * @summary Test the version of HTML generated by the javadoc tool.
  * @author bpatel
  * @library ../lib
@@ -42,7 +42,6 @@
     @Test
     void test1() {
         javadoc("-d", "out-1", "-private", "-linksource", "-html5",
-                "-Xprofilespath", testSrc("profile-rtjar-includes.txt"),
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
@@ -55,7 +54,6 @@
     @Test
     void test2() {
         javadoc("-d", "out-2", "-private", "-linksource", "-html4",
-                "-Xprofilespath", testSrc("profile-rtjar-includes.txt"),
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
@@ -68,7 +66,6 @@
     @Test
     void test3() {
         javadoc("-d", "out-3", "-private", "-linksource",
-                "-Xprofilespath", testSrc("profile-rtjar-includes.txt"),
                 "-sourcepath", testSrc,
                 "-use",
                 "pkg", "pkg1", "pkg2", "pkg3");
@@ -114,26 +111,6 @@
                 + "<ul>\n"
                 + "<li>");
 
-        // Test for profile-overview-frame page
-        checkOutput("profile-overview-frame.html", true,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<nav role=\"navigation\" class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<main role=\"main\" class=\"indexContainer\">\n"
-                + "<h2 title=\"Profiles\">Profiles</h2>");
-
-        // Test for <profile-name>-frame page
-        checkOutput("compact1-frame.html", true,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<nav role=\"navigation\" class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<main role=\"main\" class=\"indexContainer\">\n"
-                + "<h2 title=\"compact1\"><a href=\"compact1-summary.html\" target=\"classFrame\">compact1</a>&nbsp;Packages</h2>");
-
         // Test for overview-summary page
         checkOutput("overview-summary.html", true,
                 "<!DOCTYPE HTML>",
@@ -147,10 +124,6 @@
                 + "<nav role=\"navigation\">\n"
                 + "<div class=\"fixedNav\">\n"
                 + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"contentContainer\">\n"
-                + "<div>\n"
-                + "<h2>Profiles</h2>",
                 "<footer role=\"contentinfo\">\n"
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
@@ -238,68 +211,6 @@
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
 
-        // Test for <profile-name>-package-frame page
-        checkOutput("pkg/compact1-package-frame.html", true,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<main role=\"main\">\n"
-                + "<h1 class=\"bar\"><a href=\"../compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a> - <a href=\"../pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h1>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Interfaces\">Interfaces</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Classes\">Classes</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Enums\">Enums</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Exceptions\">Exceptions</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Errors\">Errors</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Annotation Types\">Annotation Types</h2>");
-
-        // Test for <profile-name>-package-summary page
-        checkOutput("pkg/compact1-package-summary.html", true,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<a id=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\">",
-                "<header role=\"banner\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"header\">",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Package pkg Description\">Package pkg Description</h2>\n",
-                "<footer role=\"contentinfo\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
-
-        // Test for <profile-name>-summary page
-        checkOutput("compact1-summary.html", true,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<a id=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\">",
-                "<header role=\"banner\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<div class=\"fixedNav\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"header\">",
-                "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<section role=\"region\">\n"
-                + "<h3><a href=\"pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h3>\n",
-                "<footer role=\"contentinfo\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
-
         // Test for constant-values page
         checkOutput("constant-values.html", true,
                 "<!DOCTYPE HTML>",
@@ -724,26 +635,6 @@
                 + "<ul>\n"
                 + "<li>");
 
-        // Negated test for profile-overview-frame page
-        checkOutput("profile-overview-frame.html", false,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<div class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<div class=\"indexContainer\">\n"
-                + "<h2 title=\"Profiles\">Profiles</h2>");
-
-        // Negated test for <profile-name>-frame page
-        checkOutput("compact1-frame.html", false,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<div class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<div class=\"indexContainer\">\n"
-                + "<h2 title=\"compact1\"><a href=\"compact1-summary.html\" target=\"classFrame\">compact1</a>&nbsp;Packages</h2>");
-
         // Negated test for overview-summary page
         checkOutput("overview-summary.html", false,
                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
@@ -755,11 +646,7 @@
                 + "<caption>",
                 "</noscript>\n"
                 + "<div class=\"fixedNav\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
-                + "<div class=\"contentContainer\">\n"
-                + "<div>\n"
-                + "<h2>Profiles</h2>");
+                + "<!-- ========= START OF TOP NAVBAR ======= -->");
 
         // Negated test for package-frame page
         checkOutput("pkg/package-frame.html", false,
@@ -799,42 +686,6 @@
                 + "</a>",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">");
 
-        // Negated test for <profile-name>-package-frame page
-        checkOutput("pkg/compact1-package-frame.html", false,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<body>\n"
-                + "<h1 class=\"bar\"><a href=\"../compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a> - <a href=\"../pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h1>");
-
-        // Negated test for <profile-name>-package-summary page
-        checkOutput("pkg/compact1-package-summary.html", false,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<a name=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\" summary=\"Interface Summary table, listing interfaces, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Class Summary table, listing classes, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Enum Summary table, listing enums, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Exception Summary table, listing exceptions, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Error Summary table, listing errors, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Annotation Types Summary table, listing annotation types, and an explanation\">");
-
-        // Negated test for <profile-name>-summary page
-        checkOutput("compact1-summary.html", false,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<a name=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\" summary=\"Interface Summary table, listing interfaces, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Class Summary table, listing classes, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Enum Summary table, listing enums, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Exception Summary table, listing exceptions, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Error Summary table, listing errors, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Annotation Types Summary table, listing annotation types, and an explanation\">");
-
         // Negated test for constant-values page
         checkOutput("constant-values.html", false,
                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
@@ -844,6 +695,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"constantsSummary\" summary=\"Constant Field Values table, listing constant fields, and values\">");
 
@@ -856,6 +708,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">\n"
                 + "<h1 title=\"Deprecated API\" class=\"title\">Deprecated API</h1>\n"
                 + "<h2 title=\"Contents\">Contents</h2>",
@@ -879,6 +732,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<li class=\"blockList\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>");
@@ -892,6 +746,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<div class=\"contentContainer\">\n"
                 + "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>",
@@ -909,6 +764,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"contentContainer\">");
 
         // Negated test for src-html page
@@ -926,6 +782,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
@@ -1133,6 +990,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">",
                 "<li class=\"blockList\"><a name=\"pkg\">\n"
@@ -1175,26 +1033,6 @@
                 + "<ul>\n"
                 + "<li>");
 
-        // Test for profile-overview-frame page
-        checkOutput("profile-overview-frame.html", true,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<div class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<div class=\"indexContainer\">\n"
-                + "<h2 title=\"Profiles\">Profiles</h2>");
-
-        // Test for <profile-name>-frame page
-        checkOutput("compact1-frame.html", true,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<div class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<div class=\"indexContainer\">\n"
-                + "<h2 title=\"compact1\"><a href=\"compact1-summary.html\" target=\"classFrame\">compact1</a>&nbsp;Packages</h2>");
-
         // Test for overview-summary page
         checkOutput("overview-summary.html", true,
                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
@@ -1206,10 +1044,7 @@
                 + "<caption>",
                 "</noscript>\n"
                 + "<div class=\"fixedNav\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<div class=\"contentContainer\">\n"
-                + "<div>\n"
-                + "<h2>Profiles</h2>");
+                + "<!-- ========= START OF TOP NAVBAR ======= -->");
 
         // Test for package-frame page
         checkOutput("pkg/package-frame.html", true,
@@ -1250,42 +1085,6 @@
                 + "</a>",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">");
 
-        // Test for <profile-name>-package-frame page
-        checkOutput("pkg/compact1-package-frame.html", true,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<body>\n"
-                + "<h1 class=\"bar\"><a href=\"../compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a> - <a href=\"../pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h1>");
-
-        // Test for <profile-name>-package-summary page
-        checkOutput("pkg/compact1-package-summary.html", true,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<a name=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\" summary=\"Interface Summary table, listing interfaces, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Class Summary table, listing classes, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Enum Summary table, listing enums, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Exception Summary table, listing exceptions, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Error Summary table, listing errors, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Annotation Types Summary table, listing annotation types, and an explanation\">");
-
-        // Test for <profile-name>-summary page
-        checkOutput("compact1-summary.html", true,
-                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
-                "<meta name=\"date\"",
-                "<a name=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\" summary=\"Interface Summary table, listing interfaces, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Class Summary table, listing classes, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Enum Summary table, listing enums, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Exception Summary table, listing exceptions, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Error Summary table, listing errors, and an explanation\">",
-                "<table class=\"typeSummary\" summary=\"Annotation Types Summary table, listing annotation types, and an explanation\">");
-
         // Test for constant-values page
         checkOutput("constant-values.html", true,
                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
@@ -1295,6 +1094,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"constantsSummary\" summary=\"Constant Field Values table, listing constant fields, and values\">");
 
@@ -1307,6 +1107,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">\n"
                 + "<h1 title=\"Deprecated API\" class=\"title\">Deprecated API</h1>\n"
                 + "<h2 title=\"Contents\">Contents</h2>",
@@ -1330,6 +1131,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<li class=\"blockList\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>");
@@ -1344,6 +1146,7 @@
                 "<li class=\"circle\">",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<h1 class=\"title\">Hierarchy For All Packages</h1>\n"
                 + "<span class=\"packageHierarchyLabel\">Package Hierarchies:</span>",
@@ -1363,6 +1166,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"contentContainer\">");
 
         // Test for src-html page
@@ -1380,6 +1184,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
@@ -1587,6 +1392,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">",
                 "<li class=\"blockList\"><a name=\"pkg\">\n"
@@ -1634,26 +1440,6 @@
                 + "<ul>\n"
                 + "<li>");
 
-        // Negated test for profile-overview-frame page
-        checkOutput("profile-overview-frame.html", false,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<nav role=\"navigation\" class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<main role=\"main\" class=\"indexContainer\">\n"
-                + "<h2 title=\"Profiles\">Profiles</h2>");
-
-        // Negated test for <profile-name>-frame page
-        checkOutput("compact1-frame.html", false,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<nav role=\"navigation\" class=\"indexNav\">\n"
-                + "<ul>\n"
-                + "<li><a href=\"allclasses-frame.html\" target=\"packageFrame\">All&nbsp;Classes</a></li>",
-                "<main role=\"main\" class=\"indexContainer\">\n"
-                + "<h2 title=\"compact1\"><a href=\"compact1-summary.html\" target=\"classFrame\">compact1</a>&nbsp;Packages</h2>");
-
         // Negated test for overview-summary page
         checkOutput("overview-summary.html", false,
                 "<!DOCTYPE HTML>",
@@ -1665,14 +1451,7 @@
                 + "<caption>",
                 "<header role=\"banner\">\n"
                 + "<nav role=\"navigation\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"contentContainer\">\n"
-                + "<div>\n"
-                + "<h2>Profiles</h2>",
-                "<footer role=\"contentinfo\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
+                + "<!-- ========= START OF TOP NAVBAR ======= -->");
 
         // Negated test for package-frame page
         checkOutput("pkg/package-frame.html", false,
@@ -1753,66 +1532,6 @@
                 + "<nav role=\"navigation\">\n"
                 + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
 
-        // Negated test for <profile-name>-package-frame page
-        checkOutput("pkg/compact1-package-frame.html", false,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<main role=\"main\">\n"
-                + "<h1 class=\"bar\"><a href=\"../compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a> - <a href=\"../pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h1>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Interfaces\">Interfaces</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Classes\">Classes</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Enums\">Enums</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Exceptions\">Exceptions</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Errors\">Errors</h2>",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Annotation Types\">Annotation Types</h2>");
-
-        // Negated test for <profile-name>-package-summary page
-        checkOutput("pkg/compact1-package-summary.html", false,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<a id=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\">",
-                "<header role=\"banner\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"header\">",
-                "<section role=\"region\">\n"
-                + "<h2 title=\"Package pkg Description\">Package pkg Description</h2>\n",
-                "<footer role=\"contentinfo\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
-
-        // Negated test for <profile-name>-summary page
-        checkOutput("compact1-summary.html", false,
-                "<!DOCTYPE HTML>",
-                "<meta name=\"dc.created\"",
-                "<a id=\"navbar.top.firstrow\">\n"
-                + "<!--   -->\n"
-                + "</a>",
-                "<table class=\"typeSummary\">",
-                "<header role=\"banner\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ========= START OF TOP NAVBAR ======= -->",
-                "<main role=\"main\">\n"
-                + "<div class=\"header\">",
-                "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<section role=\"region\">\n"
-                + "<h3><a href=\"pkg/compact1-package-summary.html\" target=\"classFrame\">pkg</a></h3>\n",
-                "<footer role=\"contentinfo\">\n"
-                + "<nav role=\"navigation\">\n"
-                + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
-
         // Negated test for constant-values page
         checkOutput("constant-values.html", false,
                 "<!DOCTYPE HTML>",
diff --git a/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java b/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java
index 43fda5e..f4181fa 100644
--- a/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java
+++ b/langtools/test/com/sun/javadoc/testLinkOption/TestLinkOption.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -51,14 +51,21 @@
     // method and not in independent @Test methods.
     @Test
     void test() {
+        String mylib = "mylib";
+        String[] javacArgs = {
+            "-d", mylib, testSrc + "/extra/StringBuilder.java"
+        };
+        com.sun.tools.javac.Main.compile(javacArgs);
+
         // Generate the documentation using -linkoffline and a URL as the first parameter.
         String out1 = "out1";
-        String url = "http://java.sun.com/j2se/1.4/docs/api/";
+        String url = "http://acme.com/jdk/";
         javadoc("-d", out1,
+                "-classpath", mylib,
                 "-sourcepath", testSrc,
-                "-linkoffline", url, testSrc,
+                "-linkoffline", url, testSrc + "/jdk",
                 "-package",
-                "pkg", "java.lang");
+                "pkg", "mylib.lang");
         checkExit(Exit.OK);
 
         checkOutput("pkg/C.html", true,
@@ -73,7 +80,7 @@
                 + "      <a href=\"" + url + "java/lang/Object.html?is-external=true\" title=\"class or interface in java.lang\">"
                 + "Object</a>&nbsp;p3)");
 
-        checkOutput("java/lang/StringBuilderChild.html", true,
+        checkOutput("mylib/lang/StringBuilderChild.html", true,
                 "<pre>public abstract class <span class=\"typeNameLabel\">StringBuilderChild</span>\n"
                 + "extends <a href=\"" + url + "java/lang/Object.html?is-external=true\" "
                 + "title=\"class or interface in java.lang\">Object</a></pre>"
@@ -100,7 +107,7 @@
         String out4 = "out4";
         javadoc(createArguments(out4, out1, false)); // without trailing slash
         checkExit(Exit.OK);
-        // Note: the following test is very weak, and will fail if ever the test
+        // Note: the following test is very weak, and will fail if ever the text
         // of the message is changed. We should have a separate test to verify
         // this is the text that is given when there is a problem with a URL
         checkOutput(Output.WARNING, false,
diff --git a/langtools/test/com/sun/javadoc/testLinkOption/extra/StringBuilder.java b/langtools/test/com/sun/javadoc/testLinkOption/extra/StringBuilder.java
new file mode 100644
index 0000000..d59d286
--- /dev/null
+++ b/langtools/test/com/sun/javadoc/testLinkOption/extra/StringBuilder.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 mylib.lang;
+
+abstract class AbstractStringBuilder {
+    abstract void m();
+}
diff --git a/langtools/test/com/sun/javadoc/testLinkOption/java/lang/StringBuilderChild.java b/langtools/test/com/sun/javadoc/testLinkOption/java/lang/StringBuilderChild.java
deleted file mode 100644
index b44173c..0000000
--- a/langtools/test/com/sun/javadoc/testLinkOption/java/lang/StringBuilderChild.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 java.lang;
-
-/**
- * @author Jamie Ho
- */
-public abstract class StringBuilderChild extends AbstractStringBuilder {
-}
diff --git a/langtools/test/com/sun/javadoc/testLinkOption/package-list b/langtools/test/com/sun/javadoc/testLinkOption/jdk/package-list
similarity index 100%
rename from langtools/test/com/sun/javadoc/testLinkOption/package-list
rename to langtools/test/com/sun/javadoc/testLinkOption/jdk/package-list
diff --git a/langtools/test/com/sun/javadoc/testLinkOption/mylib/lang/StringBuilderChild.java b/langtools/test/com/sun/javadoc/testLinkOption/mylib/lang/StringBuilderChild.java
new file mode 100644
index 0000000..d81e3ce
--- /dev/null
+++ b/langtools/test/com/sun/javadoc/testLinkOption/mylib/lang/StringBuilderChild.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 mylib.lang;
+
+/**
+ * @author Jamie Ho
+ */
+public abstract class StringBuilderChild extends AbstractStringBuilder {
+}
diff --git a/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java b/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java
index 6a35d57..fa1dc3c 100644
--- a/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java
+++ b/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854
+ * @bug      4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854 8150188
  * @summary  Make sure the Next/Prev Class links iterate through all types.
  *           Make sure the navagation is 2 columns, not 3.
  * @author   jamieh
@@ -67,5 +67,85 @@
                 + "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>");
+
+        // Remaining tests check for additional padding to offset the fixed navigation bar.
+        checkOutput("pkg/A.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<div class=\"header\">");
+    }
+
+    // Test for checking additional padding to offset the fixed navigation bar in HTML5.
+    @Test
+    void test1() {
+        javadoc("-d", "out-1", "-html5",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>\n"
+                + "</header>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>");
+    }
+
+    // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML4.
+    @Test
+    void test2() {
+        javadoc("-d", "out-2", "-nonavbar",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<div class=\"header\">");
+    }
+
+    // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML5.
+    @Test
+    void test3() {
+        javadoc("-d", "out-3", "-html5", "-nonavbar",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>\n"
+                + "</header>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>");
     }
 }
diff --git a/langtools/test/com/sun/javadoc/testNestedInlineTag/TestNestedInlineTag.java b/langtools/test/com/sun/javadoc/testNestedInlineTag/TestNestedInlineTag.java
index 49c0967..a95b88f 100644
--- a/langtools/test/com/sun/javadoc/testNestedInlineTag/TestNestedInlineTag.java
+++ b/langtools/test/com/sun/javadoc/testNestedInlineTag/TestNestedInlineTag.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
@@ -72,6 +72,7 @@
                 "-taglet", "testtaglets.UnderlineTaglet",
                 "-taglet", "testtaglets.BoldTaglet",
                 "-taglet", "testtaglets.GreenTaglet",
+                "-XDaccessInternalAPI",
                 testSrc("TestNestedInlineTag.java"));
         checkExit(Exit.OK);
 
diff --git a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/BoldTaglet.java b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/BoldTaglet.java
index d77ec0c..951406e 100644
--- a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/BoldTaglet.java
+++ b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/BoldTaglet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,16 @@
 
 package testtaglets;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.*;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
-import com.sun.javadoc.*;
-import java.util.*;
-
 /**
  * An inline Taglet representing {@bold}
  *
diff --git a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/GreenTaglet.java b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/GreenTaglet.java
index 719d01c..daff71f 100644
--- a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/GreenTaglet.java
+++ b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/GreenTaglet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,16 @@
 
 package testtaglets;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.*;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
-import com.sun.javadoc.*;
-import java.util.*;
-
 
 /**
  * An inline Taglet representing {@green}
diff --git a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/UnderlineTaglet.java b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/UnderlineTaglet.java
index ad422bc..f22ebe4 100644
--- a/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/UnderlineTaglet.java
+++ b/langtools/test/com/sun/javadoc/testNestedInlineTag/testtaglets/UnderlineTaglet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,16 @@
 
 package testtaglets;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.*;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
-import com.sun.javadoc.*;
-import java.util.*;
-
 
 /**
  * An inline Taglet representing {@underline}
@@ -64,5 +67,4 @@
         inlineTags.add(new TextTag(tag.holder(), "</u>"));
         return writer.commentTagsToOutput(tag, (Tag[]) inlineTags.toArray(new Tag[] {}));
     }
-
 }
diff --git a/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java b/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java
deleted file mode 100644
index f8ad07d..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2013, 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      8006124 8009684 8016921 8023700 8024096 8008164 8026567 8026770
- * @summary  Test javadoc support for profiles.
- * @author   Bhavesh Patel, Evgeniya Stepanova
- * @library ../lib
- * @modules jdk.javadoc
- * @build    JavadocTester
- * @run main TestProfiles
- */
-public class TestProfiles extends JavadocTester {
-
-    public static void main(String... args) throws Exception {
-        TestProfiles tester = new TestProfiles();
-        tester.runTests();
-    }
-
-    @Test
-    void testProfiles() {
-        javadoc("-d", "out-profiles",
-                "-sourcepath", testSrc,
-                "-Xprofilespath", testSrc("profile-rtjar-includes.txt"),
-                "pkg1", "pkg2", "pkg3", "pkg4", "pkg5", "pkgDeprecated");
-        checkExit(Exit.OK);
-
-        // Tests for profile-overview-frame.html listing all profiles.
-        checkOutput("profile-overview-frame.html", true,
-                "<li><a href=\"overview-frame.html\" "
-                + "target=\"packageListFrame\">All&nbsp;Packages</a></li>",
-                "<li><a href=\"compact1-frame.html\" target=\"packageListFrame\">"
-                + "compact1</a></li>");
-
-        // Tests for profileName-frame.html listing all packages in a profile.
-        checkOutput("compact2-frame.html", true,
-                "<li><a href=\"overview-frame.html\" target=\"packageListFrame\">"
-                + "All&nbsp;Packages</a></li>\n<li><a href=\"profile-overview-frame.html\" "
-                + "target=\"packageListFrame\">All&nbsp;Profiles</a></li>",
-                "<li><a href=\"pkg4/compact2-package-frame.html\" "
-                + "target=\"packageFrame\">pkg4</a></li>");
-
-        // Test for profileName-package-frame.html listing all types in a
-        // package of a profile.
-        checkOutput("pkg2/compact2-package-frame.html", true,
-                "<a href=\"../compact2-summary.html\" target=\"classFrame\">"
-                + "compact2</a> - <a href=\"../pkg2/compact2-package-summary.html\" "
-                + "target=\"classFrame\">pkg2</a>");
-
-        // Tests for profileName-summary.html listing the summary for a profile.
-        checkOutput("compact2-summary.html", true,
-                "<li><a href=\"compact1-summary.html\">Prev&nbsp;Profile</a></li>\n"
-                + "<li><a href=\"compact3-summary.html\">Next&nbsp;Profile</a></li>",
-                "<h1 title=\"Profile\" class=\"title\">Profile&nbsp;compact2</h1>",
-                "<h3><a href=\"pkg2/compact2-package-summary.html\" "
-                + "target=\"classFrame\">pkg2</a></h3>",
-                "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<h3><a href=\"pkg2/compact2-package-summary.html\" target=\"classFrame\">"
-                + "pkg2</a></h3>\n"
-                + "<table class=\"typeSummary\" summary=\"Class Summary table, "
-                + "listing classes, and an explanation\">",
-                "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<h3><a href=\"pkg4/compact2-package-summary.html\" target=\"classFrame\">"
-                + "pkg4</a></h3>\n"
-                + "<table class=\"typeSummary\" summary=\"Class Summary table, "
-                + "listing classes, and an explanation\">");
-
-
-        // Tests for profileName-package-summary.html listing the summary for a
-        // package in a profile.
-        checkOutput("pkg5/compact3-package-summary.html", true,
-                "<li><a href=\"../pkg4/compact3-package-summary.html\">Prev&nbsp;Package"
-                + "</a></li>",
-                "<div class=\"subTitle\">compact3</div>",
-                "<ul class=\"blockList\">\n"
-                + "<li class=\"blockList\">\n"
-                + "<table class=\"typeSummary\" summary=\"Interface Summary table, listing "
-                + "interfaces, and an explanation\">");
-
-        // Test for "overview-frame.html" showing the "All Profiles" link.
-        checkOutput("overview-frame.html", true,
-                "<li><a href=\"profile-overview-frame.html\" "
-                + "target=\"packageListFrame\">All&nbsp;Profiles</a></li>");
-
-        // Test for "className.html" showing the profile information for the type.
-        checkOutput("pkg2/Class1Pkg2.html", true,
-                "<div class=\"subTitle\">compact1, compact2, compact3</div>");
-
-        checkOutput("index.html", true,
-                "<iframe src=\"overview-frame.html\" name=\"packageListFrame\" "
-                + "title=\"All Packages\">");
-
-        // Test for "overview-summary.html" showing the profile list.
-        checkOutput("overview-summary.html", true,
-                "<ul>\n"
-                + "<li><a href=\"compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a></li>\n"
-                + "<li><a href=\"compact2-summary.html\" "
-                + "target=\"classFrame\">compact2</a></li>\n"
-                + "<li><a href=\""
-                + "compact3-summary.html\" target=\"classFrame\">compact3</a></li>\n"
-                + "</ul>");
-
-        // Test deprecated class in profiles
-        checkOutput("compact1-summary.html", true,
-                "<td class=\"colFirst\"><a href=\"pkg2/Class1Pkg2.html\" title=\"class in pkg2\">Class1Pkg2</a></td>\n"
-                + "<td class=\"colLast\">Deprecated");
-
-        checkOutput("deprecated-list.html", true,
-                "<td class=\"colOne\"><a href=\"pkg2/Class1Pkg2.html\" title=\"class in pkg2\">pkg2.Class1Pkg2</a>\n"
-                + "<div class=\"block\"><span class=\"deprecationComment\">Class1Pkg2. This class is deprecated</span></div>");
-
-        //Test deprecated package in profile
-        checkOutput("deprecated-list.html", true,
-                "<td class=\"colOne\"><a href=\"pkgDeprecated/package-summary.html\">pkgDeprecated</a>\n"
-                + "<div class=\"block\"><span class=\"deprecationComment\">This package is <b>Deprecated</b>."
-                + " Use pkg1.</span></div>");
-
-        checkOutput("pkgDeprecated/package-summary.html", true,
-                "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
-                + "<div class=\"block\"><span class=\"deprecationComment\">This package is <b>Deprecated</b>."
-                + " Use pkg1.</span></div>");
-
-        // TODO: need to add teststring when JDK-8015496 will be fixed
-        // Test exception in profiles
-        checkOutput("compact1-summary.html", true,
-                "<table class=\"typeSummary\" "
-                + "summary=\"Exception Summary table, listing exceptions, and an explanation\">\n"
-                + "<caption><span>Exception Summary</span><span class=\"tabEnd\">"
-                + "&nbsp;</span></caption>\n"
-                + "<tr>\n"
-                + "<th class=\"colFirst\" scope=\"col\">Exception</th>\n"
-                + "<th class=\"colLast\" scope=\"col\">"
-                + "Description</th>\n"
-                + "</tr>\n"
-                + "<tbody>\n"
-                + "<tr class=\"altColor\">\n"
-                + "<td class=\"colFirst\"><a href=\"pkg2/ClassException.html\""
-                + " title=\"class in pkg2\">ClassException</a></td>");
-
-        //Test errors in profiles
-        checkOutput("compact1-summary.html", true,
-                "<table class=\"typeSummary\" summary=\"Error Summary table, listing errors, and an explanation\">\n"
-                + "<caption><span>Error Summary</span><span class=\"tabEnd\">&nbsp;"
-                + "</span></caption>\n"
-                + "<tr>\n"
-                + "<th class=\"colFirst\" scope=\"col\">Error</th>\n"
-                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>\n"
-                + "<tbody>\n"
-                + "<tr class=\"altColor\">\n"
-                + "<td class=\"colFirst\">"
-                + "<a href=\"pkg2/ClassError.html\" title=\"class in pkg2\">ClassError</a></td>");
-
-        // negative tests
-        checkOutput("pkg3/Class2Pkg3.html", false,
-            "<div class=\"subTitle\">compact1");
-
-        checkOutput("pkg3/Interface1Pkg3.html", false,
-            "<div class=\"subTitle\">compact1");
-
-        checkOutput("pkg4/compact2-package-frame.html", false,
-            "<li><a href=\"Anno1Pkg4.html\" title=\"annotation in pkg4\" "
-            + "target=\"classFrame\">Anno1Pkg4</a></li>");
-
-        checkOutput("compact1-summary.html", false,
-                "<li>Use</li>");
-
-        checkOutput("compact2-summary.html", false,
-            "<ul class=\"blockList\">\n" +
-            "<li class=\"blockList\">\n"
-            + "<h3><a href=\"pkg2/compact2-package-summary.html\" target=\"classFrame\">"
-            + "pkg2</a></h3>\n" +
-            "<li class=\"blockList\">\n"
-            + "<table class=\"typeSummary\" summary=\"Class Summary table, "
-            + "listing classes, and an explanation\">");
-
-        checkOutput("pkg5/compact3-package-summary.html", false,
-            "<ul class=\"blockList\">\n" +
-            "<li class=\"blockList\">\n"
-            + "<li class=\"blockList\">\n"
-            + "<table class=\"typeSummary\" summary=\"Interface Summary table, listing "
-            + "interfaces, and an explanation\">");
-    }
-
-    @Test
-    void testPackages() {
-        javadoc("-d", "out-packages",
-                "-sourcepath", testSrc,
-                "pkg1", "pkg2", "pkg3", "pkg4", "pkg5");
-        checkExit(Exit.OK);
-
-        checkOutput("overview-frame.html", true,
-                "<h2 title=\"Packages\">Packages</h2>");
-
-        checkOutput("pkg4/package-frame.html", true,
-                "<h1 class=\"bar\"><a href=\"../pkg4/package-summary.html\" "
-                + "target=\"classFrame\">pkg4</a></h1>");
-
-        checkOutput("pkg4/package-summary.html", true,
-                "<div class=\"header\">\n"
-                + "<h1 title=\"Package\" "
-                + "class=\"title\">Package&nbsp;pkg4</h1>\n"
-                + "</div>");
-
-        checkOutput("overview-frame.html", false,
-                "<span><a href=\"profile-overview-frame.html\" "
-                + "target=\"packageListFrame\">All&nbsp;Profiles</a></span>");
-
-        checkOutput("pkg2/Class1Pkg2.html", false,
-                "<div class=\"subTitle\">compact1, compact2, compact3</div>");
-
-        checkOutput("overview-summary.html", false,
-                "<ul>\n"
-                + "<li><a href=\"compact1-summary.html\" target=\"classFrame\">"
-                + "compact1</a></li>\n"
-                + "<li><a href=\"compact2-summary.html\" "
-                + "target=\"classFrame\">compact2</a></li>\n"
-                + "<li><a href=\""
-                + "compact3-summary.html\" target=\"classFrame\">compact3</a></li>\n"
-                + "</ul>");
-
-        checkFiles(false,
-                "profile-overview-frame.html",
-                "compact2-frame.html",
-                "pkg2/compact2-package-frame.html",
-                "compact2-summary.html",
-                "pkg5/compact3-package-summary.html");
-    }
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java b/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java
deleted file mode 100644
index 38020f0..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2013, 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      8006124 8009684 8015663 8015496 8026567
- * @summary  Test javadoc options support for profiles.
- * @author   Evgeniya Stepanova
- * @library  ../lib
- * @modules jdk.javadoc
- * @build    JavadocTester
- * @run main TestProfilesConfiguration
- */
-public class TestProfilesConfiguration extends JavadocTester {
-
-    public static void main(String... args) throws Exception {
-        TestProfilesConfiguration tester = new TestProfilesConfiguration();
-        tester.runTests();
-//        tester.run(ARGS3, PROFILES_CONFIGURATION_TEST, PROFILES_CONFIGURATION_NEGATED_TEST);
-//        tester.run(ARGS4, NODEPR_NOPKGS_TEST, NODEPR_NOPKGS_NEGATED_TEST);
-//        tester.printSummary();
-    }
-
-    @Test
-    void testProfiles() {
-        javadoc("-d", "out-profiles",
-                "-sourcepath", testSrc,
-                "-nocomment",
-                "-keywords",
-                "-Xprofilespath", testSrc("profile-rtjar-includes.txt"),
-                "-doctitle", "Simple doctitle",
-                "-use",
-                "-packagesheader", "Simple packages header",
-                "pkg3", "pkg1", "pkg2", "pkg4", "pkg5", "pkgDeprecated");
-        checkExit(Exit.OK);
-
-        checkOutput("compact1-summary.html", true,
-                //-use option test string fo profile view page
-                "<li>Use</li>",
-                // -keywords option test string for profiles
-                "<meta name=\"keywords\" content=\"compact1 profile\">",
-                // Deprecated information on a package
-                "<h3><a href=\"pkgDeprecated/compact1-package-summary.html\" target=\""
-                + "classFrame\">pkgDeprecated</a></h3>\n"
-                + "<div class=\"deprecatedContent\">"
-                + "<span class=\"deprecatedLabel\">Deprecated.</span></div>"
-        );
-
-        //-nocomments option test string
-        checkOutput("compact1-summary.html", false,
-                "<div class=\"block\"><i>Class1Pkg2.</i></div>"
-        );
-
-        // -doctitle option test string
-        checkOutput("overview-summary.html", true,
-                "<div class=\"header\">\n"
-                + "<h1 class=\"title\">Simple doctitle</h1>"
-        );
-
-        // -packagesheader option test string fo profiles
-        checkOutput("profile-overview-frame.html", true,
-                "<h1 title=\"Simple packages header\" class=\"bar\">Simple packages header</h1>"
-        );
-    }
-
-
-    @Test
-    void testNoDeprNoPackages() {
-        javadoc("-d", "out-noDeprNoPackages",
-                "-sourcepath", testSrc,
-                "-nocomment",
-                "-nodeprecated",
-                "-keywords",
-                "-Xprofilespath", testSrc("profile-rtjar-includes-nopkgs.txt"),
-                "-doctitle", "Simple doctitle",
-                "-use",
-                "-packagesheader", "Simple packages header",
-                "pkg1", "pkg2", "pkg3", "pkg4", "pkg5", "pkgDeprecated");
-        checkExit(Exit.OK);
-
-        checkOutput("overview-summary.html", true,
-                "<ul>\n"
-                + "<li><a href=\"compact2-summary.html\" target=\"classFrame\">"
-                + "compact2</a></li>\n"
-                + "<li><a href=\"compact3-summary.html\" target=\""
-                + "classFrame\">compact3</a></li>\n"
-                + "</ul>"
-        );
-
-        checkOutput("profile-overview-frame.html", true,
-                "<ul title=\"Profiles\">\n"
-                + "<li><a href=\"compact2-frame.html\" target=\"packageListFrame\">"
-                + "compact2</a></li>\n"
-                + "<li><a href=\"compact3-frame.html\" target=\""
-                + "packageListFrame\">compact3</a></li>\n"
-                + "</ul>"
-        );
-
-        checkOutput("overview-summary.html", false,
-                "compact1"
-        );
-
-    }
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class1Pkg1.java b/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class1Pkg1.java
deleted file mode 100644
index dc5c50d..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class1Pkg1.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg1;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class1Pkg1 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class2Pkg1.java b/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class2Pkg1.java
deleted file mode 100644
index 33ecb01..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class2Pkg1.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg1;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class2Pkg1 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class3Pkg1.java b/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class3Pkg1.java
deleted file mode 100644
index 162cbfb..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Class3Pkg1.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg1;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class3Pkg1 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Interface1Pkg1.java b/langtools/test/com/sun/javadoc/testProfiles/pkg1/Interface1Pkg1.java
deleted file mode 100644
index e2a4337..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg1/Interface1Pkg1.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg1;
-
-/**
- * A sample interface.
- *
- * @author Bhavesh Patel
- */
-public interface Interface1Pkg1 {
-
-    /**
-     * A test method.
-     *
-     * @param a blah.
-     * @param b blah.
-     */
-    void method1(int a, int b);
-
-    /**
-     * Another test method.
-     *
-     * @param c blah.
-     */
-    void method2(int c);
-
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno1Pkg2.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno1Pkg2.java
deleted file mode 100644
index 54fd75f..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno1Pkg2.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg2;
-
-import java.lang.annotation.*;
-
-/**
- * Test Annotation class.
- *
- * @author Bhavesh Patel
- */
-public @interface Anno1Pkg2 {
-    /**
-     * Comment.
-     */
-    String[] value();
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno2Pkg2.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno2Pkg2.java
deleted file mode 100644
index 87e657d..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Anno2Pkg2.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg2;
-
-import java.lang.annotation.*;
-
-/*
- * A sample interface.
- */
-public @interface Anno2Pkg2 {
-    boolean value() default true;
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java
deleted file mode 100644
index 935bd36..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg2;
-
-/**
- * @deprecated Class1Pkg2. This class is deprecated
- *
- * @author Bhavesh Patel
- */
-public class Class1Pkg2 {
-
-    /**
-     * A sample enum.
-     */
-    public static enum ModalExclusionType {
-        /**
-         * Test comment.
-         */
-        NO_EXCLUDE,
-        /**
-         * Another comment.
-         */
-        APPLICATION_EXCLUDE
-    };
-
-    /**
-     * A string constant.
-     */
-    public static final String CONSTANT1 = "C2";
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java
deleted file mode 100644
index 427b8f9..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg2;
-
-/**
- * Simple error class.
- *
- * @author Evgeniya Stepanova
- */
-public class ClassError extends Error {}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java
deleted file mode 100644
index d56412e..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg2;
-
-/**
- * Simple exception class.
- *
- * @author Evgeniya Stepanova
- */
-public class ClassException extends Exception {}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class1Pkg3.java b/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class1Pkg3.java
deleted file mode 100644
index ec340af..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class1Pkg3.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg3;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class1Pkg3 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class2Pkg3.java b/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class2Pkg3.java
deleted file mode 100644
index 45272d0..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Class2Pkg3.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg3;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class2Pkg3 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Interface1Pkg3.java b/langtools/test/com/sun/javadoc/testProfiles/pkg3/Interface1Pkg3.java
deleted file mode 100644
index 09db1af..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg3/Interface1Pkg3.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg3;
-
-/**
- * A sample interface.
- *
- * @author Bhavesh Patel
- */
-public interface Interface1Pkg3 {
-
-    /**
-     * A test method.
-     *
-     * @param a blah.
-     * @param b blah.
-     */
-    void method1(int a, int b);
-
-    /**
-     * Another test method.
-     *
-     * @param c blah.
-     */
-    void method2(int c);
-
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg4/Anno1Pkg4.java b/langtools/test/com/sun/javadoc/testProfiles/pkg4/Anno1Pkg4.java
deleted file mode 100644
index 9332690..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg4/Anno1Pkg4.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg4;
-
-import java.lang.annotation.*;
-
-/**
- * Test Annotation class.
- *
- * @author Bhavesh Patel
- */
-public @interface Anno1Pkg4 {
-    /**
-     * Comment.
-     */
-    String[] value();
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg4/Class1Pkg4.java b/langtools/test/com/sun/javadoc/testProfiles/pkg4/Class1Pkg4.java
deleted file mode 100644
index 7c9966b..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg4/Class1Pkg4.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg4;
-
-/**
- * Another test class.
- *
- * @author Bhavesh Patel
- */
-public class Class1Pkg4 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg5/Class1Pkg5.java b/langtools/test/com/sun/javadoc/testProfiles/pkg5/Class1Pkg5.java
deleted file mode 100644
index 606d838..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg5/Class1Pkg5.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg5;
-
-/**
- * A test class.
- *
- * @author Bhavesh Patel
- */
-public class Class1Pkg5 {
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg5/Interface1Pkg5.java b/langtools/test/com/sun/javadoc/testProfiles/pkg5/Interface1Pkg5.java
deleted file mode 100644
index 4660a30..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkg5/Interface1Pkg5.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkg5;
-
-/**
- * A sample interface.
- *
- * @author Bhavesh Patel
- */
-public interface Interface1Pkg5 {
-
-    /**
-     * A test method.
-     *
-     * @param a blah.
-     * @param b blah.
-     */
-    void method1(int a, int b);
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java
deleted file mode 100644
index 5147549..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package pkgDeprecated;
-
-/**
- * Simple deprecated class of deprecated package.
- *
- * @author Evgeniya Stepanova
- */
-public class Class1PkgDeprecated {
-
-    public void method(int t) {
-        return null;
-    }
-}
diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java
deleted file mode 100644
index 0cc0700..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Deprecated package.
- *
- * @deprecated This package is <b>Deprecated</b>. Use pkg1.
- */
-package pkgDeprecated;
diff --git a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt
deleted file mode 100644
index c63a4e8..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-PROFILE_1_RTJAR_INCLUDE_PACKAGES := 
-
-PROFILE_1_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_1_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_1_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_2_RTJAR_INCLUDE_PACKAGES := \
-    pkg4 \
-    pkgDeprecated 
-
-PROFILE_2_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_2_RTJAR_EXCLUDE_TYPES := \
-    pkg4/Anno1Pkg4.class 
-
-PROFILE_2_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_3_RTJAR_INCLUDE_PACKAGES := \
-    pkg5 
-
-PROFILE_3_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_3_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_3_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_4_RTJAR_INCLUDE_PACKAGES := \
-    pkg1 
-
-PROFILE_4_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_4_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_4_INCLUDE_METAINF_SERVICES :=  
-
-
diff --git a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt
deleted file mode 100644
index eff8d14..0000000
--- a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-PROFILE_1_RTJAR_INCLUDE_PACKAGES := \
-    pkg2 \
-    pkgDeprecated
-
-PROFILE_1_RTJAR_INCLUDE_TYPES := \
-    pkg3/Class1Pkg3.class
-
-PROFILE_1_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_1_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_2_RTJAR_INCLUDE_PACKAGES := \
-    pkg4 
-
-PROFILE_2_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_2_RTJAR_EXCLUDE_TYPES := \
-    pkg4/Anno1Pkg4.class 
-
-PROFILE_2_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_3_RTJAR_INCLUDE_PACKAGES := \
-    pkg5 
-
-PROFILE_3_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_3_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_3_INCLUDE_METAINF_SERVICES := 
-
-
-PROFILE_4_RTJAR_INCLUDE_PACKAGES := \
-    pkg1 
-
-PROFILE_4_RTJAR_INCLUDE_TYPES := 
-
-PROFILE_4_RTJAR_EXCLUDE_TYPES := 
-
-PROFILE_4_INCLUDE_METAINF_SERVICES :=  
-
-
diff --git a/langtools/test/com/sun/javadoc/testSubTitle/TestSubTitle.java b/langtools/test/com/sun/javadoc/testSubTitle/TestSubTitle.java
index 374e48f..f4c535a 100644
--- a/langtools/test/com/sun/javadoc/testSubTitle/TestSubTitle.java
+++ b/langtools/test/com/sun/javadoc/testSubTitle/TestSubTitle.java
@@ -50,7 +50,8 @@
             "<div class=\"block\">This is the description of package pkg.</div>");
 
         checkOutput("pkg/C.html", true,
-            "<div class=\"subTitle\">pkg</div>");
+                "<div class=\"subTitle\"><span class=\"packageLabelInClass\">Package</span>&nbsp;"
+                + "<a href=\"../pkg/package-summary.html\" target=\"classFrame\">pkg</a></div>");
 
         checkOutput("pkg/package-summary.html", false,
             "<p class=\"subTitle\">\n" +
diff --git a/langtools/test/com/sun/javadoc/testTaglets/TestTaglets.java b/langtools/test/com/sun/javadoc/testTaglets/TestTaglets.java
index 790b252..c309e8c 100644
--- a/langtools/test/com/sun/javadoc/testTaglets/TestTaglets.java
+++ b/langtools/test/com/sun/javadoc/testTaglets/TestTaglets.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
@@ -50,6 +50,7 @@
                 "-tagletpath", testSrc, // TODO: probably does no good
                 "-taglet", "taglets.Foo",
                 "-sourcepath", testSrc,
+                "-XDaccessInternalAPI",
                 testSrc("C.java"));
         checkExit(Exit.OK);
 
diff --git a/langtools/test/com/sun/javadoc/testTaglets/taglets/Foo.java b/langtools/test/com/sun/javadoc/testTaglets/taglets/Foo.java
index d318371..da37f80 100644
--- a/langtools/test/com/sun/javadoc/testTaglets/taglets/Foo.java
+++ b/langtools/test/com/sun/javadoc/testTaglets/taglets/Foo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,12 +23,16 @@
 
 package taglets;
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.*;
+
+import com.sun.javadoc.*;
+
 import com.sun.tools.doclets.internal.toolkit.*;
 import com.sun.tools.doclets.internal.toolkit.taglets.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
-import com.sun.javadoc.*;
-import java.util.*;
 
 public class Foo extends BaseTaglet {
 
diff --git a/langtools/test/jdk/javadoc/doclet/5093723/T5093723.java b/langtools/test/jdk/javadoc/doclet/5093723/T5093723.java
index 1dba9fd..3fa71fb 100644
--- a/langtools/test/jdk/javadoc/doclet/5093723/T5093723.java
+++ b/langtools/test/jdk/javadoc/doclet/5093723/T5093723.java
@@ -26,7 +26,7 @@
  * @bug      5093723
  * @summary  REGRESSION: ClassCastException in SingleIndexWriter
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main T5093723
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java b/langtools/test/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java
index 7e94452..ba7ccfe 100644
--- a/langtools/test/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java
+++ b/langtools/test/jdk/javadoc/doclet/AccessAsciiArt/AccessAsciiArt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Add text equivalent of class tree ASCII art for accessibility
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main AccessAsciiArt
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AccessFrameTitle/AccessFrameTitle.java b/langtools/test/jdk/javadoc/doclet/AccessFrameTitle/AccessFrameTitle.java
index cc262bd..70a7637 100644
--- a/langtools/test/jdk/javadoc/doclet/AccessFrameTitle/AccessFrameTitle.java
+++ b/langtools/test/jdk/javadoc/doclet/AccessFrameTitle/AccessFrameTitle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Add title attribute to <FRAME> tags for accessibility
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main AccessFrameTitle
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AccessH1/AccessH1.java b/langtools/test/jdk/javadoc/doclet/AccessH1/AccessH1.java
index 78a3ac5..14e3508 100644
--- a/langtools/test/jdk/javadoc/doclet/AccessH1/AccessH1.java
+++ b/langtools/test/jdk/javadoc/doclet/AccessH1/AccessH1.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Use <H1, <H2>, and <H3> in proper sequence for accessibility
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main AccessH1
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java b/langtools/test/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java
index ce17788..d93b728 100644
--- a/langtools/test/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java
+++ b/langtools/test/jdk/javadoc/doclet/AccessSkipNav/AccessSkipNav.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Add ability to skip over nav bar for accessibility
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main AccessSkipNav
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AccessSummary/AccessSummary.java b/langtools/test/jdk/javadoc/doclet/AccessSummary/AccessSummary.java
index 9eb8847..3f0eb7d 100644
--- a/langtools/test/jdk/javadoc/doclet/AccessSummary/AccessSummary.java
+++ b/langtools/test/jdk/javadoc/doclet/AccessSummary/AccessSummary.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Test the tables for summary attribute
  * @author   dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main AccessSummary
  */
diff --git a/langtools/test/jdk/javadoc/doclet/AuthorDD/AuthorDD.java b/langtools/test/jdk/javadoc/doclet/AuthorDD/AuthorDD.java
index b57604b..bc7a8b2 100644
--- a/langtools/test/jdk/javadoc/doclet/AuthorDD/AuthorDD.java
+++ b/langtools/test/jdk/javadoc/doclet/AuthorDD/AuthorDD.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Javadoc wrongly inserts </DD> tags when using multiple @author tags
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main AuthorDD
  */
diff --git a/langtools/test/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java b/langtools/test/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java
index d1bc9ff..a4612f2 100644
--- a/langtools/test/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java
+++ b/langtools/test/jdk/javadoc/doclet/DocRootSlash/DocRootSlash.java
@@ -27,7 +27,7 @@
  * @summary stddoclet: {@docRoot} inserts an extra trailing "/"
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main DocRootSlash
  */
diff --git a/langtools/test/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java b/langtools/test/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java
index c37ed93..a6b7e47 100644
--- a/langtools/test/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java
+++ b/langtools/test/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.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
@@ -27,7 +27,7 @@
  * @summary Using {@inheritDoc} in simple tag defined via -tag fails
  * @author Mike Duigou
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main DocTest
  */
diff --git a/langtools/test/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java b/langtools/test/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java
index 4ce8d37..4423ca2 100644
--- a/langtools/test/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java
+++ b/langtools/test/jdk/javadoc/doclet/JavascriptWinTitle/JavascriptWinTitle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  *           Window title shouldn't change when loading left frames (javascript)
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main JavascriptWinTitle
  */
diff --git a/langtools/test/jdk/javadoc/doclet/MetaTag/MetaTag.java b/langtools/test/jdk/javadoc/doclet/MetaTag/MetaTag.java
index 3cd3a53..70d9b6e 100644
--- a/langtools/test/jdk/javadoc/doclet/MetaTag/MetaTag.java
+++ b/langtools/test/jdk/javadoc/doclet/MetaTag/MetaTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  *           class and member names to improve API search
  * @author   dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main MetaTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/PackagesHeader/PackagesHeader.java b/langtools/test/jdk/javadoc/doclet/PackagesHeader/PackagesHeader.java
index a69a543..9f1bd00 100644
--- a/langtools/test/jdk/javadoc/doclet/PackagesHeader/PackagesHeader.java
+++ b/langtools/test/jdk/javadoc/doclet/PackagesHeader/PackagesHeader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -29,7 +29,7 @@
  *           (2) -packagesheader, and (3) -header -packagesheader
  * @author   dkramer
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main PackagesHeader
  */
diff --git a/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java b/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java
index 8b08345..23eba5f 100644
--- a/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java
+++ b/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.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
@@ -26,7 +26,7 @@
  * @bug 6735320
  * @summary javadoc throws exception if serialField value is missing
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main T6735320
  */
diff --git a/langtools/test/jdk/javadoc/doclet/ValidHtml/ValidHtml.java b/langtools/test/jdk/javadoc/doclet/ValidHtml/ValidHtml.java
index fb0b045..48c302a 100644
--- a/langtools/test/jdk/javadoc/doclet/ValidHtml/ValidHtml.java
+++ b/langtools/test/jdk/javadoc/doclet/ValidHtml/ValidHtml.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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,7 +30,7 @@
  *           HTML table tags inserted in wrong place in pakcage use page
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main ValidHtml
  */
diff --git a/langtools/test/jdk/javadoc/doclet/VersionNumber/VersionNumber.java b/langtools/test/jdk/javadoc/doclet/VersionNumber/VersionNumber.java
index 1ea553f..8c88fa5 100644
--- a/langtools/test/jdk/javadoc/doclet/VersionNumber/VersionNumber.java
+++ b/langtools/test/jdk/javadoc/doclet/VersionNumber/VersionNumber.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Standard doclet contains hard-coded version number
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main VersionNumber
  */
diff --git a/langtools/test/jdk/javadoc/doclet/WindowTitles/WindowTitles.java b/langtools/test/jdk/javadoc/doclet/WindowTitles/WindowTitles.java
index cd11450..94a51a4 100644
--- a/langtools/test/jdk/javadoc/doclet/WindowTitles/WindowTitles.java
+++ b/langtools/test/jdk/javadoc/doclet/WindowTitles/WindowTitles.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary stddoclet: With frames off, window titles have "()" appended
  * @author dkramer
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main WindowTitles
  */
diff --git a/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java b/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
index 80d32e4..882e876 100644
--- a/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
+++ b/langtools/test/jdk/javadoc/doclet/constantValues/TestConstantValuesDriver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Test the generation of constant-values.html.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestConstantValuesDriver
  */
diff --git a/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java b/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java
index 30e50dc..ecdb295 100644
--- a/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java
+++ b/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Determine if duplicate throws tags can be used.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDupThrowsTags
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java b/langtools/test/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java
index 9988dae..3e715a8 100644
--- a/langtools/test/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java
+++ b/langtools/test/jdk/javadoc/doclet/testAbsLinkPath/TestAbsLinkPath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary This test verifys that the -link option handles absolute paths.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestAbsLinkPath
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java b/langtools/test/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java
index 991ad9d..a878160 100644
--- a/langtools/test/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.java
+++ b/langtools/test/jdk/javadoc/doclet/testAbstractMethod/TestAbstractMethod.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
@@ -28,7 +28,7 @@
  *           if the abstract modifier is present explicitly or implicitly.
  * @author   bpatel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestAbstractMethod
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java b/langtools/test/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java
index f04ad41..cf2209e 100644
--- a/langtools/test/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.java
+++ b/langtools/test/jdk/javadoc/doclet/testAnchorNames/TestAnchorNames.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
@@ -27,7 +27,7 @@
  * @summary Test for valid name attribute in HTML anchors.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestAnchorNames
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java b/langtools/test/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java
index 9061e10..8285e1c 100644
--- a/langtools/test/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java
+++ b/langtools/test/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  *           element headers
  * @author   Mahmood Ali
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestAnnotationOptional
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
index 29f7d70..15355fa 100644
--- a/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
+++ b/langtools/test/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java
@@ -28,7 +28,7 @@
  *           extra HR tags.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestAnnotationTypes
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java b/langtools/test/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java
index 2266911..e567315 100644
--- a/langtools/test/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java
+++ b/langtools/test/jdk/javadoc/doclet/testBackSlashInLink/TestBackSlashInLink.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * has a forward slash.  It would be wrong to use a back slash.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestBackSlashInLink
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java b/langtools/test/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java
index 7c81a61..38dc0e7 100644
--- a/langtools/test/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java
+++ b/langtools/test/jdk/javadoc/doclet/testBadPackageFileInJar/TestBadPackageFileInJar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * when a bad package.html file is in the JAR.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestBadPackageFileInJar
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java b/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java
index 6dc9c6c..15f5fc1 100644
--- a/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java
+++ b/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.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
@@ -28,7 +28,7 @@
  *           file in the same directory as the file being documented.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestBadSourceFile
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java b/langtools/test/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java
index 09d1db6..ffa9ce5 100644
--- a/langtools/test/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java
+++ b/langtools/test/jdk/javadoc/doclet/testBaseClass/TestBaseClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Javadoc does not process base class.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build BaseClass
  * @build JavadocTester
  * @run main TestBaseClass
diff --git a/langtools/test/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java b/langtools/test/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java
index c2e5717..b626ccb 100644
--- a/langtools/test/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java
+++ b/langtools/test/jdk/javadoc/doclet/testBreakIterator/TestBreakIterator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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,7 +30,7 @@
  * Wrong Answer: "This is a class (i.e."
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestBreakIterator
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java b/langtools/test/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java
index 514bff8..e361b97 100644
--- a/langtools/test/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java
+++ b/langtools/test/jdk/javadoc/doclet/testCRLineSeparator/TestCRLineSeparator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary  Make sure tool parses CR line separators properly.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestCRLineSeparator
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testCharset/TestCharset.java b/langtools/test/jdk/javadoc/doclet/testCharset/TestCharset.java
index a273340..7eb51f5 100644
--- a/langtools/test/jdk/javadoc/doclet/testCharset/TestCharset.java
+++ b/langtools/test/jdk/javadoc/doclet/testCharset/TestCharset.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
@@ -28,7 +28,7 @@
  *           part of the meta tag.
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestCharset
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java b/langtools/test/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java
index 28120d4..546171b 100644
--- a/langtools/test/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java
+++ b/langtools/test/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary This test verifies that class cross references work properly.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @build TestClassCrossReferences
  * @run main TestClassCrossReferences
diff --git a/langtools/test/jdk/javadoc/doclet/testClassTree/TestClassTree.java b/langtools/test/jdk/javadoc/doclet/testClassTree/TestClassTree.java
index 4603593..7c774a7 100644
--- a/langtools/test/jdk/javadoc/doclet/testClassTree/TestClassTree.java
+++ b/langtools/test/jdk/javadoc/doclet/testClassTree/TestClassTree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  *           types.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestClassTree
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java b/langtools/test/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java
index e03b498..7d1d554 100644
--- a/langtools/test/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java
+++ b/langtools/test/jdk/javadoc/doclet/testCmndLineClass/TestCmndLineClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -29,7 +29,7 @@
  * classes.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestCmndLineClass
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java b/langtools/test/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java
index 2968d6a..1cafc76 100644
--- a/langtools/test/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.java
+++ b/langtools/test/jdk/javadoc/doclet/testCompletionFailure/TestCompletionFailure.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
@@ -27,7 +27,7 @@
  * @summary Test to verify javadoc executes without CompletionFailure exception.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestCompletionFailure
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java b/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java
index 68c4c9b..0d674d7 100644
--- a/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java
+++ b/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * generated when doclet has nothing to document.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestConstantValuesPage
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java b/langtools/test/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java
index d4e5784..32d9e8f 100644
--- a/langtools/test/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.java
+++ b/langtools/test/jdk/javadoc/doclet/testConstructorIndent/TestConstructorIndent.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
@@ -28,7 +28,7 @@
  *           <dl></dl>.  Check for this in the output.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestConstructorIndent
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testConstructors/TestConstructors.java b/langtools/test/jdk/javadoc/doclet/testConstructors/TestConstructors.java
index 176a1f7..f1afc69 100644
--- a/langtools/test/jdk/javadoc/doclet/testConstructors/TestConstructors.java
+++ b/langtools/test/jdk/javadoc/doclet/testConstructors/TestConstructors.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
@@ -27,7 +27,7 @@
  * @summary Test for constructor name which should be a non-qualified name.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestConstructors
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java b/langtools/test/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java
index 0da414f..bbc5a8c 100644
--- a/langtools/test/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java
+++ b/langtools/test/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.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
@@ -27,7 +27,7 @@
  * @summary  <DESC>
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestDeprecatedDocs
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java b/langtools/test/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java
index 1f6c585..7a0e786 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocEncoding/TestDocEncoding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
              used for stylesheet as well.
  * @author   jayashree viswanathan
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestDocEncoding
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java b/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java
index 74100d2..76a0d2a 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.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
@@ -28,7 +28,7 @@
  *           DocErrorReporter.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestDocErrorReporter
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java b/langtools/test/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java
index 6bcdbcc..ce2df24 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocFileDir/TestDocFileDir.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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,7 +30,7 @@
  *          Also test that -docfilessubdirs and -excludedocfilessubdir both work.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDocFileDir
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java b/langtools/test/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java
index 8bf77ba..ec0863c 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocFiles/TestDocFiles.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocFiles/TestDocFiles.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
@@ -26,7 +26,7 @@
  * @bug 8008949
  * @summary verify that doc-files get copied
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDocFiles
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java b/langtools/test/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java
index 841b110..c0b9a20 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -29,7 +29,7 @@
  * Make sure that the docRoot tag works with the -bottom option.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDocRootInlineTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java b/langtools/test/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java
index 2011ac3..6a9ef4f 100644
--- a/langtools/test/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.java
+++ b/langtools/test/jdk/javadoc/doclet/testDocRootLink/TestDocRootLink.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
@@ -27,7 +27,7 @@
  * @summary This test verifies the -Xdocrootparent option.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDocRootLink
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java b/langtools/test/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java
index eb68d08..7127cdc 100644
--- a/langtools/test/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java
+++ b/langtools/test/jdk/javadoc/doclet/testDupParamWarn/TestDupParamWarn.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * warning messages about duplicate param tags.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestDupParamWarn
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java b/langtools/test/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java
index aacbb78..54d2d85 100644
--- a/langtools/test/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.java
+++ b/langtools/test/jdk/javadoc/doclet/testEmptyClass/TestEmptyClass.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
@@ -28,7 +28,7 @@
  * run on a completely empty class (no comments or members).
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestEmptyClass
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java b/langtools/test/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java
index e3b0a4e..0673d3b 100644
--- a/langtools/test/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java
+++ b/langtools/test/jdk/javadoc/doclet/testEnclosingClass/TestEnclosingClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary  Check the outer class when documenting enclosing class/interface.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestEnclosingClass
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testEncoding/TestEncoding.java b/langtools/test/jdk/javadoc/doclet/testEncoding/TestEncoding.java
index a972225..4f8326b 100644
--- a/langtools/test/jdk/javadoc/doclet/testEncoding/TestEncoding.java
+++ b/langtools/test/jdk/javadoc/doclet/testEncoding/TestEncoding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * properly passed from Javadoc to the source file parser.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestEncoding
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java b/langtools/test/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java
index 74e06d7..761e893 100644
--- a/langtools/test/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java
+++ b/langtools/test/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.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
@@ -29,7 +29,7 @@
  * "overrides" documentation even though the method is external.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester TestExternalOverridenMethod
  * @run main TestExternalOverridenMethod
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java b/langtools/test/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java
index e0f3736..6e6220d 100644
--- a/langtools/test/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.java
+++ b/langtools/test/jdk/javadoc/doclet/testGeneratedBy/TestGeneratedBy.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
@@ -26,7 +26,7 @@
  * @bug 8000418 8024288
  * @summary Verify that files use a common Generated By string
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestGeneratedBy
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java b/langtools/test/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java
index 2d9d0d5..8bf8562 100644
--- a/langtools/test/jdk/javadoc/doclet/testGroupOption/TestGroupOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testGroupOption/TestGroupOption.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
@@ -28,7 +28,7 @@
  *           to be printed.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestGroupOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java b/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java
index 1d0d82b..e93becd 100644
--- a/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.java
+++ b/langtools/test/jdk/javadoc/doclet/testHeadings/TestHeadings.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
@@ -27,7 +27,7 @@
  * @summary  Make sure that headings use the TH tag instead of the TD tag.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @build    TestHeadings
  * @run main TestHeadings
diff --git a/langtools/test/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java b/langtools/test/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java
index 7a75e43..43d743f 100644
--- a/langtools/test/jdk/javadoc/doclet/testHelpFile/TestHelpFile.java
+++ b/langtools/test/jdk/javadoc/doclet/testHelpFile/TestHelpFile.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
@@ -27,7 +27,7 @@
  * @summary  Make sure that the help file is generated correctly.
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestHelpFile
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java b/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java
index 1351e7f..b0b34e5 100644
--- a/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java
@@ -27,7 +27,7 @@
  * @summary  Make sure that -help, -helpfile and -nohelp options work correctly.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester TestHelpOption
  * @run main TestHelpOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java b/langtools/test/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java
index 84a7ec70..69e2d3e 100644
--- a/langtools/test/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java
+++ b/langtools/test/jdk/javadoc/doclet/testHiddenMembers/TestHiddenMembers.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * documented as inherited.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHiddenMembers
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHref/TestHref.java b/langtools/test/jdk/javadoc/doclet/testHref/TestHref.java
index ad34ced..06d36b3 100644
--- a/langtools/test/jdk/javadoc/doclet/testHref/TestHref.java
+++ b/langtools/test/jdk/javadoc/doclet/testHref/TestHref.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
@@ -27,7 +27,7 @@
  * @summary  Verify that spaces do not appear in hrefs and anchors.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestHref
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java b/langtools/test/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java
index 5242faa..9b6d828 100644
--- a/langtools/test/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java
+++ b/langtools/test/jdk/javadoc/doclet/testHrefInDocComment/TestHrefInDocComment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * appear in doc comments.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHrefInDocComment
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java b/langtools/test/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java
index 4a2d302..f865a68 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlComments/TestHtmlComments.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
@@ -28,7 +28,7 @@
  *           are no fields to document.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestHtmlComments
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java b/langtools/test/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java
index 6a1f316..7584be0 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary This test verifies the nesting of definition list tags.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHtmlDefinitionListTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java b/langtools/test/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java
index 64a0547..eb86baf 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.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
@@ -26,8 +26,9 @@
  * @bug 6851834
  * @summary This test verifies the HTML document generation for javadoc output.
  * @library ../lib
- * @modules jdk.javadoc/com.sun.tools.doclets.formats.html.markup
- *          jdk.javadoc/com.sun.tools.doclets.internal.toolkit
+ * @modules jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.markup
+ *          jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util
+ *          jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @author Bhavesh Patel
  * @run main TestHtmlDocument
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java b/langtools/test/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java
index cf0db1e..ec4ccac 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlStrongTag/TestHtmlStrongTag.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,7 +27,7 @@
  * @summary This test verifies the use of <strong> HTML tag instead of <B> by Javadoc std doclet.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHtmlStrongTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java b/langtools/test/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java
index 543ad19..01139ad 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlTableStyles/TestHtmlTableStyles.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
@@ -27,7 +27,7 @@
  * @summary Test styles on HTML tables generated by javadoc.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHtmlTableStyles
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java b/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
index b3766d2..e11de5b 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlTableTags/TestHtmlTableTags.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary  HTML tables should have table summary, caption and table headers.
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestHtmlTableTags
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java b/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java
index e70816f..a11386a 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary This test verifies the use of lang attribute by <HTML>.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHtmlTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java
index a04e2bf..e9dc703 100644
--- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java
@@ -23,11 +23,11 @@
 
 /*
  * @test
- * @bug 8072945 8081854 8141492 8148985
+ * @bug 8072945 8081854 8141492 8148985 8150188
  * @summary Test the version of HTML generated by the javadoc tool.
  * @author bpatel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestHtmlVersion
  */
@@ -695,6 +695,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"constantsSummary\" summary=\"Constant Field Values table, listing constant fields, and values\">");
 
@@ -707,6 +708,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">\n"
                 + "<h1 title=\"Deprecated API\" class=\"title\">Deprecated API</h1>\n"
                 + "<h2 title=\"Contents\">Contents</h2>",
@@ -730,6 +732,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<li class=\"blockList\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>");
@@ -743,6 +746,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<div class=\"contentContainer\">\n"
                 + "<h2 title=\"Class Hierarchy\">Class Hierarchy</h2>",
@@ -760,6 +764,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"contentContainer\">");
 
         // Negated test for src-html page
@@ -777,6 +782,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
@@ -984,6 +990,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">",
                 "<li class=\"blockList\"><a name=\"pkg\">\n"
@@ -1087,6 +1094,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"constantsSummary\" summary=\"Constant Field Values table, listing constant fields, and values\">");
 
@@ -1099,6 +1107,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">\n"
                 + "<h1 title=\"Deprecated API\" class=\"title\">Deprecated API</h1>\n"
                 + "<h2 title=\"Contents\">Contents</h2>",
@@ -1122,6 +1131,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<li class=\"blockList\">\n"
                 + "<h2 title=\"Package\">Package&nbsp;pkg</h2>");
@@ -1136,6 +1146,7 @@
                 "<li class=\"circle\">",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<h1 class=\"title\">Hierarchy For All Packages</h1>\n"
                 + "<span class=\"packageHierarchyLabel\">Package Hierarchies:</span>",
@@ -1155,6 +1166,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"contentContainer\">");
 
         // Test for src-html page
@@ -1172,6 +1184,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
@@ -1379,6 +1392,7 @@
                 + "</a>",
                 "<!-- ========= END OF TOP NAVBAR ========= -->\n"
                 + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
                 + "<div class=\"header\">",
                 "<table class=\"useSummary\" summary=\"Use table, listing packages, and an explanation\">",
                 "<li class=\"blockList\"><a name=\"pkg\">\n"
diff --git a/langtools/test/jdk/javadoc/doclet/testIndentation/TestIndentation.java b/langtools/test/jdk/javadoc/doclet/testIndentation/TestIndentation.java
index 1cd3dc3..69eb7a5 100644
--- a/langtools/test/jdk/javadoc/doclet/testIndentation/TestIndentation.java
+++ b/langtools/test/jdk/javadoc/doclet/testIndentation/TestIndentation.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
@@ -26,7 +26,7 @@
  * @bug      8011288 8062647
  * @summary  Erratic/inconsistent indentation of signatures
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestIndentation
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testIndex/TestIndex.java b/langtools/test/jdk/javadoc/doclet/testIndex/TestIndex.java
index 1ad4838..2cafcf0 100644
--- a/langtools/test/jdk/javadoc/doclet/testIndex/TestIndex.java
+++ b/langtools/test/jdk/javadoc/doclet/testIndex/TestIndex.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
@@ -29,7 +29,7 @@
  *           Test for unnamed package in index.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestIndex
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java b/langtools/test/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java
index 396bf41..0512bf9 100644
--- a/langtools/test/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java
+++ b/langtools/test/jdk/javadoc/doclet/testInlineLinkLabel/TestInlineLinkLabel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Test to make sure label is used for inline links.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestInlineLinkLabel
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java b/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
index 948a742..e96edec 100644
--- a/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
+++ b/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
@@ -30,7 +30,7 @@
  *           implementing classes in the documentation for I.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestInterface
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
index 9e17061..b7543b5 100644
--- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
+++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
@@ -27,7 +27,7 @@
  * @summary Test of the JavaFX doclet features.
  * @author jvalenta
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestJavaFX
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java
index 21eb3ab..1c19488 100644
--- a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java
+++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java
@@ -27,7 +27,7 @@
  * @summary  Verify that the output has the right javascript.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestJavascript
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLambdaFeature/TestLambdaFeature.java b/langtools/test/jdk/javadoc/doclet/testLambdaFeature/TestLambdaFeature.java
index a0848d0..d303160 100644
--- a/langtools/test/jdk/javadoc/doclet/testLambdaFeature/TestLambdaFeature.java
+++ b/langtools/test/jdk/javadoc/doclet/testLambdaFeature/TestLambdaFeature.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
@@ -28,7 +28,7 @@
  *           javadoc.
  * @author   bpatel
  * @library  ../lib/
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester TestLambdaFeature
  * @run main TestLambdaFeature
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java b/langtools/test/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java
index 7752f91..6b32f8a 100644
--- a/langtools/test/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.java
+++ b/langtools/test/jdk/javadoc/doclet/testLeadingSpaces/LeadingSpaces.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
@@ -30,7 +30,7 @@
  *    spaces stripped
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main LeadingSpaces
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java b/langtools/test/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java
index cee94c4..685724c 100644
--- a/langtools/test/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.java
+++ b/langtools/test/jdk/javadoc/doclet/testLegacyTaglet/TestLegacyTaglet.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
@@ -28,7 +28,7 @@
  * doclet still works with Taglets that implement the 1.4.0 interface.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester ToDoTaglet UnderlineTaglet Check
  * @run main TestLegacyTaglet
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java
index c4e0a5a..44ba649 100644
--- a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.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
@@ -27,7 +27,7 @@
  * @summary Make sure that bad -link arguments trigger warnings.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestBadLinkOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java
index effaefa..a4378fc 100644
--- a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * right files, and URLs with and without trailing slash are accepted.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestLinkOption
  */
@@ -51,14 +51,21 @@
     // method and not in independent @Test methods.
     @Test
     void test() {
+        String mylib = "mylib";
+        String[] javacArgs = {
+            "-d", mylib, testSrc + "/extra/StringBuilder.java"
+        };
+        com.sun.tools.javac.Main.compile(javacArgs);
+
         // Generate the documentation using -linkoffline and a URL as the first parameter.
         String out1 = "out1";
-        String url = "http://java.sun.com/j2se/1.4/docs/api/";
+        String url = "http://acme.com/jdk/";
         javadoc("-d", out1,
+                "-classpath", mylib,
                 "-sourcepath", testSrc,
-                "-linkoffline", url, testSrc,
+                "-linkoffline", url, testSrc + "/jdk",
                 "-package",
-                "pkg", "java.lang");
+                "pkg", "mylib.lang");
         checkExit(Exit.OK);
 
         checkOutput("pkg/C.html", true,
@@ -75,7 +82,7 @@
 
         checkOutput("pkg/B.html", true,
                 "<div class=\"block\">A method with html tag the method "
-                + "<a href=\"http://java.sun.com/j2se/1.4/docs/api/java/lang/ClassLoader.html?is-external=true#getSystemClassLoader--\""
+                + "<a href=\"" + url + "java/lang/ClassLoader.html?is-external=true#getSystemClassLoader--\""
                 + " title=\"class or interface in java.lang\"><code><tt>getSystemClassLoader()</tt>"
                 + "</code></a> as the parent class loader.</div>",
                 "<div class=\"block\">is equivalent to invoking <code>"
@@ -96,7 +103,7 @@
                 "URISyntaxException</a></dd>\n" +
                 "</dl>");
 
-        checkOutput("java/lang/StringBuilderChild.html", true,
+        checkOutput("mylib/lang/StringBuilderChild.html", true,
                 "<pre>public abstract class <span class=\"typeNameLabel\">StringBuilderChild</span>\n"
                 + "extends <a href=\"" + url + "java/lang/Object.html?is-external=true\" "
                 + "title=\"class or interface in java.lang\">Object</a></pre>"
@@ -123,7 +130,7 @@
         String out4 = "out4";
         javadoc(createArguments(out4, out1, false)); // without trailing slash
         checkExit(Exit.OK);
-        // Note: the following test is very weak, and will fail if ever the test
+        // Note: the following test is very weak, and will fail if ever the text
         // of the message is changed. We should have a separate test to verify
         // this is the text that is given when there is a problem with a URL
         checkOutput(Output.OUT, false,
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java
index 889b69d..48a2262 100644
--- a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * link and label.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestNewLineInLink
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/extra/StringBuilder.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/extra/StringBuilder.java
new file mode 100644
index 0000000..d59d286
--- /dev/null
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/extra/StringBuilder.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 mylib.lang;
+
+abstract class AbstractStringBuilder {
+    abstract void m();
+}
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/java/lang/StringBuilderChild.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/java/lang/StringBuilderChild.java
deleted file mode 100644
index b44173c..0000000
--- a/langtools/test/jdk/javadoc/doclet/testLinkOption/java/lang/StringBuilderChild.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 java.lang;
-
-/**
- * @author Jamie Ho
- */
-public abstract class StringBuilderChild extends AbstractStringBuilder {
-}
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/package-list b/langtools/test/jdk/javadoc/doclet/testLinkOption/jdk/package-list
similarity index 100%
rename from langtools/test/jdk/javadoc/doclet/testLinkOption/package-list
rename to langtools/test/jdk/javadoc/doclet/testLinkOption/jdk/package-list
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/mylib/lang/StringBuilderChild.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/mylib/lang/StringBuilderChild.java
new file mode 100644
index 0000000..d81e3ce
--- /dev/null
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/mylib/lang/StringBuilderChild.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 mylib.lang;
+
+/**
+ * @author Jamie Ho
+ */
+public abstract class StringBuilderChild extends AbstractStringBuilder {
+}
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java b/langtools/test/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java
index 96e6e40..fb016ce 100644
--- a/langtools/test/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java
+++ b/langtools/test/jdk/javadoc/doclet/testLinkTaglet/TestLinkTaglet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  *           non-qualified name, furthermore, ensure the right one is linked.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestLinkTaglet
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java b/langtools/test/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java
index ae94eda..cd57b64 100644
--- a/langtools/test/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java
+++ b/langtools/test/jdk/javadoc/doclet/testLinkToSerialForm/TestLinkToSerialForm.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * from a serializable class to serialized-form.html.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestLinkToSerialForm
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java b/langtools/test/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
index f08c4bf..bd34513 100644
--- a/langtools/test/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
+++ b/langtools/test/jdk/javadoc/doclet/testLiteralCodeInPre/TestLiteralCodeInPre.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -26,7 +26,7 @@
  * @bug      8002387 8014636 8078320
  * @summary  Improve rendered HTML formatting for {@code}
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestLiteralCodeInPre
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java b/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
index f0b4635..9b1b425 100644
--- a/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
+++ b/langtools/test/jdk/javadoc/doclet/testMemberInheritence/TestMemberInheritence.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  *          Verify that inheritence labels are correct.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestMemberInheritence
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java b/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java
index 9c91b39..4dc5ce5 100644
--- a/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java
+++ b/langtools/test/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.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
@@ -29,7 +29,7 @@
  *           documentation is inherited but the return type isn't.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestMemberSummary
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java b/langtools/test/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java
index f429730..24e09f2 100644
--- a/langtools/test/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.java
+++ b/langtools/test/jdk/javadoc/doclet/testMethodTypes/TestMethodTypes.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
@@ -27,7 +27,7 @@
  * @summary  Test for various method types in the method summary table
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestMethodTypes
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java b/langtools/test/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java
index 1abc52a..0d4224c 100644
--- a/langtools/test/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java
+++ b/langtools/test/jdk/javadoc/doclet/testModifierEx/TestModifierEx.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
  * @test
  * @summary Ensure the modifiers are correct
  * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestModifierEx
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/langtools/test/jdk/javadoc/doclet/testNavigation/TestNavigation.java
index 6a35d57..04a4e3f 100644
--- a/langtools/test/jdk/javadoc/doclet/testNavigation/TestNavigation.java
+++ b/langtools/test/jdk/javadoc/doclet/testNavigation/TestNavigation.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
@@ -23,12 +23,12 @@
 
 /*
  * @test
- * @bug      4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854
+ * @bug      4131628 4664607 7025314 8023700 7198273 8025633 8026567 8081854 8150188
  * @summary  Make sure the Next/Prev Class links iterate through all types.
  *           Make sure the navagation is 2 columns, not 3.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestNavigation
  */
@@ -67,5 +67,85 @@
                 + "<a name=\"navbar.top.firstrow\">\n"
                 + "<!--   -->\n"
                 + "</a>");
+
+        // Remaining tests check for additional padding to offset the fixed navigation bar.
+        checkOutput("pkg/A.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<div class=\"header\">");
+    }
+
+    // Test for checking additional padding to offset the fixed navigation bar in HTML5.
+    @Test
+    void test1() {
+        javadoc("-d", "out-1", "-html5",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>\n"
+                + "</header>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", true,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>");
+    }
+
+    // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML4.
+    @Test
+    void test2() {
+        javadoc("-d", "out-2", "-nonavbar",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "<div class=\"header\">");
+    }
+
+    // Test to make sure that no extra padding for nav bar gets generated if -nonavbar is specified for HTML5.
+    @Test
+    void test3() {
+        javadoc("-d", "out-3", "-html5", "-nonavbar",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>\n"
+                + "</header>\n"
+                + "<!-- ======== START OF CLASS DATA ======== -->");
+
+        checkOutput("pkg/package-summary.html", false,
+                "<!-- ========= END OF TOP NAVBAR ========= -->\n"
+                + "</div>\n"
+                + "<div class=\"navPadding\">&nbsp;</div>\n"
+                + "</nav>");
     }
 }
diff --git a/langtools/test/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java b/langtools/test/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java
index fd6388d..176902b 100644
--- a/langtools/test/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.java
+++ b/langtools/test/jdk/javadoc/doclet/testNestedGenerics/TestNestedGenerics.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
@@ -27,7 +27,7 @@
  * @summary  Test HTML output for nested generic types.
  * @author   bpatel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestNestedGenerics
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java
index 7686329..0558f19 100644
--- a/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java
+++ b/langtools/test/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.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
@@ -29,7 +29,7 @@
  *           language features are properly documented.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestNewLanguageFeatures
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java b/langtools/test/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java
index 5306ae0..a1f342a 100644
--- a/langtools/test/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.java
+++ b/langtools/test/jdk/javadoc/doclet/testNoPackagesFile/TestNoPackagesFile.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
@@ -28,7 +28,7 @@
  *           longer used.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestNoPackagesFile
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testNotifications/TestNotifications.java b/langtools/test/jdk/javadoc/doclet/testNotifications/TestNotifications.java
index d56fc5e..bd4e4d0 100644
--- a/langtools/test/jdk/javadoc/doclet/testNotifications/TestNotifications.java
+++ b/langtools/test/jdk/javadoc/doclet/testNotifications/TestNotifications.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
@@ -29,7 +29,7 @@
  *           Make sure classname is not include in javadoc usage message.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestNotifications
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOptions/TestOptions.java b/langtools/test/jdk/javadoc/doclet/testOptions/TestOptions.java
index 3aaf576..21e68ea 100644
--- a/langtools/test/jdk/javadoc/doclet/testOptions/TestOptions.java
+++ b/langtools/test/jdk/javadoc/doclet/testOptions/TestOptions.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
@@ -27,7 +27,7 @@
  * @summary  Test the output for -header and -footer options.
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestOptions
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java
index 6cdd880..3e7f769 100644
--- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java
+++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary test to determine if members are ordered correctly
  * @author ksrini
  * @library ../lib/
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestOrdering
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestMultiInheritence.java b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestMultiInheritence.java
index 51ad72d..ef11527 100644
--- a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestMultiInheritence.java
+++ b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestMultiInheritence.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
@@ -28,7 +28,7 @@
  *           interfaces are documented
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestMultiInheritence
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenMethodDocCopy.java b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenMethodDocCopy.java
index 7d6f5d4..fec75c0 100644
--- a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenMethodDocCopy.java
+++ b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenMethodDocCopy.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
@@ -28,7 +28,7 @@
  *           class
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestOverridenMethodDocCopy
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethods.java b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethods.java
index d595705..51fd917b 100644
--- a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethods.java
+++ b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethods.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * -protected (default) visibility flag is used.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestOverridenPrivateMethods
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPackageFlag.java b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPackageFlag.java
index ecb9bc5..ae59a16 100644
--- a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPackageFlag.java
+++ b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPackageFlag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * -protected (default) visibility flag is used.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestOverridenPrivateMethodsWithPackageFlag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPrivateFlag.java b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPrivateFlag.java
index c2f9481..46d97eb 100644
--- a/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPrivateFlag.java
+++ b/langtools/test/jdk/javadoc/doclet/testOverridenMethods/TestOverridenPrivateMethodsWithPrivateFlag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * -protected (default) visibility flag is used.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestOverridenPrivateMethodsWithPrivateFlag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java b/langtools/test/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java
index 647f105..9216276 100644
--- a/langtools/test/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.java
+++ b/langtools/test/jdk/javadoc/doclet/testPackageDeprecation/TestPackageDeprecation.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
@@ -27,7 +27,7 @@
  * @summary  Test package deprecation.
  * @author   bpatel
  * @library  ../lib/
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester TestPackageDeprecation
  * @run main TestPackageDeprecation
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java b/langtools/test/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java
index 05c343e..4acd342 100644
--- a/langtools/test/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java
+++ b/langtools/test/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -29,7 +29,7 @@
  * when single or multiple packages are documented.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestPackagePage
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java b/langtools/test/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java
index 302693b..dc109e8 100644
--- a/langtools/test/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.java
+++ b/langtools/test/jdk/javadoc/doclet/testParamTaglet/TestParamTaglet.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
@@ -29,7 +29,7 @@
  *           Make sure inheritDoc cannot be used in an invalid param tag.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestParamTaglet
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java b/langtools/test/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java
index 9d6b097..6b59270 100644
--- a/langtools/test/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java
+++ b/langtools/test/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.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
@@ -38,7 +38,7 @@
  *           signature is displayed correctly without extra space at the beginning.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestPrivateClasses
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java b/langtools/test/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java
index 38983a9..f1089be 100644
--- a/langtools/test/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java
+++ b/langtools/test/jdk/javadoc/doclet/testRecurseSubPackages/TestRecurseSubPackages.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Make Javadoc capable of traversing/recursing all of given subpackages.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestRecurseSubPackages
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java b/langtools/test/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java
index 3b8c16e..bd3bece 100644
--- a/langtools/test/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.java
+++ b/langtools/test/jdk/javadoc/doclet/testRelativeLinks/TestRelativeLinks.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
@@ -28,7 +28,7 @@
  *           output so that they are not broken.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestRelativeLinks
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java
index 38380fc..0979d25 100644
--- a/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.java
+++ b/langtools/test/jdk/javadoc/doclet/testRepeatedAnnotations/TestRepeatedAnnotations.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
@@ -27,7 +27,7 @@
  * @summary  Test repeated annotations output.
  * @author   bpatel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestRepeatedAnnotations
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java b/langtools/test/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java
index 7534031..c3986f1 100644
--- a/langtools/test/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testReturnTag/TestReturnTag.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
@@ -27,7 +27,7 @@
  * @summary  Warn when a return tag is used on a method without a return type.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestReturnTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.java b/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.java
index daad22e..41905b9 100644
--- a/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.java
+++ b/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.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,7 +27,7 @@
  * @summary Test the search feature of javadoc.
  * @author bpatel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSearch
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/langtools/test/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java
index cf622b5..993bf9d 100644
--- a/langtools/test/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary  Javadoc is confused by at-link to imported classes outside of the set of generated packages
  * @author   jjg
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSeeTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java b/langtools/test/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java
index fe8d6e5..6e06fce 100644
--- a/langtools/test/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java
+++ b/langtools/test/jdk/javadoc/doclet/testSerialVersionUID/TestSerialVersionUID.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * documented in the serialized form.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSerialVersionUID
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java b/langtools/test/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java
index ed84479..c487a2e 100644
--- a/langtools/test/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java
+++ b/langtools/test/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.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
@@ -33,7 +33,7 @@
  * Make sure see tags work in serialized form.
  * @author jamieh
  * @library ../lib/
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @build TestSerializedForm
  * @run main TestSerializedForm
diff --git a/langtools/test/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java b/langtools/test/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java
index 3e3d173..8923615 100644
--- a/langtools/test/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java
+++ b/langtools/test/jdk/javadoc/doclet/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary This test verifies deprecation info in serialized-form.html.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSerializedFormDeprecationInfo
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java b/langtools/test/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java
index ff5b0fa..83a0746 100644
--- a/langtools/test/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testSimpleTag/TestSimpleTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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,7 +30,7 @@
  * considered a separator when parsing the simple tag argument.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSimpleTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java b/langtools/test/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java
index 032348f..099e5a7 100644
--- a/langtools/test/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java
+++ b/langtools/test/jdk/javadoc/doclet/testSimpleTagExclude/TestSimpleTagExclude.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * exclude a simple tag by using -tag tagname:X
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSimpleTagExclude
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java b/langtools/test/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java
index 2071c10..99f8893 100644
--- a/langtools/test/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.java
+++ b/langtools/test/jdk/javadoc/doclet/testSimpleTagInherit/TestSimpleTagInherit.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
@@ -26,7 +26,7 @@
  * @bug      8008768 8026567
  * @summary  Using {@inheritDoc} in simple tag defined via -tag fails
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSimpleTagInherit
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java b/langtools/test/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java
index d71299e..e733b21 100644
--- a/langtools/test/jdk/javadoc/doclet/testSinceTag/TestSinceTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testSinceTag/TestSinceTag.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
@@ -27,7 +27,7 @@
  * @summary  Test to make sure that the since tag works correctly
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSinceTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java b/langtools/test/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java
index 78e8d26..a9118ef 100644
--- a/langtools/test/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java
+++ b/langtools/test/jdk/javadoc/doclet/testSingleQuotedLink/TestSingleQuotedLink.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary Verify that a link in single quotes copied to the class-use page as is.
  * @author Yuri Nesterenko
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSingleQuotedLink
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java b/langtools/test/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java
index 43753f0..4f4d9b4 100644
--- a/langtools/test/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java
+++ b/langtools/test/jdk/javadoc/doclet/testSourceTab/TestSourceTab.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * when -linksourcetab is used.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSourceTab
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java
index 23340e5..c5ab9d9 100644
--- a/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java
+++ b/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.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
@@ -27,7 +27,7 @@
  * @summary  Run tests on doclet stylesheet.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestStylesheet
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java b/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java
index 3a93d64..810d503 100644
--- a/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java
+++ b/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java
@@ -27,7 +27,7 @@
  * @summary Test for correct sub title generation.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSubTitle
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java b/langtools/test/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java
index 124c1e1..4d4f81f 100644
--- a/langtools/test/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.java
+++ b/langtools/test/jdk/javadoc/doclet/testSummaryHeading/TestSummaryHeading.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
@@ -29,7 +29,7 @@
  *           inherits methods.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSummaryHeading
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java b/langtools/test/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java
index 6ae60fd..b4dfd38 100644
--- a/langtools/test/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java
+++ b/langtools/test/jdk/javadoc/doclet/testSuperclassInSerialForm/TestSuperClassInSerialForm.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * each class in serialized form page.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSuperClassInSerialForm
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java b/langtools/test/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java
index e4b8deb..5414abd 100644
--- a/langtools/test/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java
+++ b/langtools/test/jdk/javadoc/doclet/testSupplementary/TestSupplementary.java
@@ -28,7 +28,7 @@
  *    characters correctly.  This test case needs to be run in en_US locale.
  * @author Naoto Sato
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestSupplementary
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java b/langtools/test/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java
index 1f8012d..7a7b498 100644
--- a/langtools/test/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java
+++ b/langtools/test/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary <DESC>
  * @author  jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestTagInheritence
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java b/langtools/test/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java
index de07e71..473231e 100644
--- a/langtools/test/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.java
+++ b/langtools/test/jdk/javadoc/doclet/testTagMisuse/TestTagMisuse.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
@@ -26,7 +26,7 @@
  * @summary Determine if proper warning messages are printed.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @build TestTagMisuse
  * @run main TestTagMisuse
diff --git a/langtools/test/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java b/langtools/test/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java
index 9c33514..b361114 100644
--- a/langtools/test/jdk/javadoc/doclet/testTagOutput/TestTagOutput.java
+++ b/langtools/test/jdk/javadoc/doclet/testTagOutput/TestTagOutput.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
@@ -27,7 +27,7 @@
  * @summary This test checks the generated tag output.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestTagOutput
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java b/langtools/test/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java
index 950ae05..e73e6bd 100644
--- a/langtools/test/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java
+++ b/langtools/test/jdk/javadoc/doclet/testThrowsHead/TestThrowsHead.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -29,7 +29,7 @@
  * throws section.  Make sure that the link is below a Throws heading.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestThrowsHead
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java b/langtools/test/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java
index 9c59aee..de28b82 100644
--- a/langtools/test/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java
+++ b/langtools/test/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java
@@ -29,7 +29,7 @@
  * the case where the name of one exception is not fully qualified.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestThrowsTagInheritence
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java b/langtools/test/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java
index c33fb92..ffa1a3e 100644
--- a/langtools/test/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testThrowsTag/TestThrowsTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  *           correct order.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestThrowsTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java b/langtools/test/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java
index 169a2f3..6a2fd8e 100644
--- a/langtools/test/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java
+++ b/langtools/test/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary Test to make sure that the title attribute shows up in links.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestTitleInHref
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTopOption/TestTopOption.java b/langtools/test/jdk/javadoc/doclet/testTopOption/TestTopOption.java
index df9f69a..b418c77 100644
--- a/langtools/test/jdk/javadoc/doclet/testTopOption/TestTopOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testTopOption/TestTopOption.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
@@ -27,7 +27,7 @@
  * @summary  Test the new -top option.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestTopOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
index dbbee51..21bbbf5 100644
--- a/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
+++ b/langtools/test/jdk/javadoc/doclet/testTypeAnnotations/TestTypeAnnotations.java
@@ -27,7 +27,7 @@
  * @summary  Make sure that type annotations are displayed correctly
  * @author   Bhavesh Patel
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestTypeAnnotations
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java b/langtools/test/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java
index 4c6c8cc..d53210d 100644
--- a/langtools/test/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java
+++ b/langtools/test/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.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
@@ -31,7 +31,7 @@
  *           parameter links in the class/annotation signature section when -linksource is set.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestTypeParameters
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java b/langtools/test/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java
index 9310817..b23af6b 100644
--- a/langtools/test/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java
+++ b/langtools/test/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.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
@@ -28,7 +28,7 @@
  *           Generate a package summary for the unnamed package.
  * @author   jamieh
  * @library  ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestUnnamedPackage
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java b/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
index 2955df3..3b8760d 100644
--- a/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testUseOption/TestUseOption.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,7 +27,7 @@
  * @summary A simple test to ensure class-use files are correct.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestUseOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testValueTag/TestValueTag.java b/langtools/test/jdk/javadoc/doclet/testValueTag/TestValueTag.java
index 895c704..046a73a 100644
--- a/langtools/test/jdk/javadoc/doclet/testValueTag/TestValueTag.java
+++ b/langtools/test/jdk/javadoc/doclet/testValueTag/TestValueTag.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
@@ -28,7 +28,7 @@
  * use cases. The explainations for each test case are written below.
  * @author   jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestValueTag
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java b/langtools/test/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java
index b05ca3b..5e3d6ca 100644
--- a/langtools/test/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java
+++ b/langtools/test/jdk/javadoc/doclet/testWarnBadParamNames/TestWarnBadParamNames.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -28,7 +28,7 @@
  * name is used with param.
  * @author jamieh
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestWarnBadParamNames
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testWindowTitle/TestWindowTitle.java b/langtools/test/jdk/javadoc/doclet/testWindowTitle/TestWindowTitle.java
index 2894a02..5e34d40 100644
--- a/langtools/test/jdk/javadoc/doclet/testWindowTitle/TestWindowTitle.java
+++ b/langtools/test/jdk/javadoc/doclet/testWindowTitle/TestWindowTitle.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
@@ -27,7 +27,7 @@
  * @summary Test for window title.
  * @author Bhavesh Patel
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build JavadocTester
  * @run main TestWindowTitle
  */
diff --git a/langtools/test/jdk/javadoc/doclet/testXOption/TestXOption.java b/langtools/test/jdk/javadoc/doclet/testXOption/TestXOption.java
index 39f98bc..238015b 100644
--- a/langtools/test/jdk/javadoc/doclet/testXOption/TestXOption.java
+++ b/langtools/test/jdk/javadoc/doclet/testXOption/TestXOption.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
@@ -26,7 +26,7 @@
  * @bug      8007687
  * @summary  Make sure that the -X option works properly.
  * @library ../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestXOption
  */
diff --git a/langtools/test/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java b/langtools/test/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java
index d8651d3..d400d3d 100644
--- a/langtools/test/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java
+++ b/langtools/test/jdk/javadoc/doclet/typeAnnotations/smoke/TestSmoke.java
@@ -28,7 +28,7 @@
  *
  * @author   Mahmood Ali <mali>
  * @library  ../../lib
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build    JavadocTester
  * @run main TestSmoke
  */
diff --git a/langtools/test/jdk/javadoc/tool/6227454/Test.java b/langtools/test/jdk/javadoc/tool/6227454/Test.java
index 9cf762b..da171be 100644
--- a/langtools/test/jdk/javadoc/tool/6227454/Test.java
+++ b/langtools/test/jdk/javadoc/tool/6227454/Test.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 6227454
  * @summary package.html and overview.html may not be read fully
- * @modules jdk.javadoc
+ *  * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.*;
@@ -81,18 +81,12 @@
         System.err.println("test " + testNum);
         File file = writeFile("overview" + testNum + ".html", text);
         String thisClassName = Test.class.getName();
+        File testSrc = new File(System.getProperty("test.src"));
         String[] args = {
-            "-bootclasspath",
-                System.getProperty("java.class.path")
-                + File.pathSeparator
-                + System.getProperty("sun.boot.class.path"),
             "-classpath", ".",
-            "-docletpath", System.getProperty("test.classes"),
-            "-doclet", thisClassName,
             "-package",
             "-overview", file.getPath(),
-            "-sourcepath", ".",
-            referenceFile.getPath()
+            new File(testSrc, thisClassName + ".java").getPath()
         };
 
         StringWriter sw = new StringWriter();
diff --git a/langtools/test/jdk/javadoc/tool/6942366/T6942366.java b/langtools/test/jdk/javadoc/tool/6942366/T6942366.java
index 72a54c2..e376267 100644
--- a/langtools/test/jdk/javadoc/tool/6942366/T6942366.java
+++ b/langtools/test/jdk/javadoc/tool/6942366/T6942366.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6942366
  * @summary javadoc no longer inherits doc from sourcepath
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @build p.Base Test
  * @run main T6942366
  */
diff --git a/langtools/test/jdk/javadoc/tool/6958836/Test.java b/langtools/test/jdk/javadoc/tool/6958836/Test.java
index 281d331..e59be76 100644
--- a/langtools/test/jdk/javadoc/tool/6958836/Test.java
+++ b/langtools/test/jdk/javadoc/tool/6958836/Test.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6958836 8002168
  * @summary javadoc should support -Xmaxerrs and -Xmaxwarns
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.*;
diff --git a/langtools/test/jdk/javadoc/tool/6964914/Test.java b/langtools/test/jdk/javadoc/tool/6964914/Test.java
index 04e7675..d8fcdfb 100644
--- a/langtools/test/jdk/javadoc/tool/6964914/Test.java
+++ b/langtools/test/jdk/javadoc/tool/6964914/Test.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6964914
  * @summary javadoc does not output number of warnings using user written doclet
- * @modules jdk.javadoc/com.sun.tools.doclets.standard
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.*;
@@ -48,7 +48,6 @@
         String[] args = {
             "-Xdoclint:none",
             "-source", "8",
-            "-bootclasspath", System.getProperty("sun.boot.class.path"),
             "-classpath", ".",
             "-package",
             new File(testSrc, path).getPath()
diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java
index 533f3ad..3fff0e1 100644
--- a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java
+++ b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java
@@ -56,7 +56,7 @@
         String thisClassName = TestStdDoclet.class.getName();
         Process p = new ProcessBuilder()
             .command(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
+                "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""),
                 "-classpath", ".", // insulates us from ambient classpath
                 "-Xdoclint:none",
                 "-package",
diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java
index f866573..cec6d27 100644
--- a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java
+++ b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java
@@ -65,7 +65,7 @@
         String thisClassName = TestUserDoclet.class.getName();
         Process p = new ProcessBuilder()
             .command(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
+                "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""),
                 "-doclet", thisClassName,
                 "-docletpath", testClasses.getPath(),
                 new File(testSrc, thisClassName + ".java").getPath())
diff --git a/langtools/test/jdk/javadoc/tool/BreakIteratorWarning.java b/langtools/test/jdk/javadoc/tool/BreakIteratorWarning.java
index dea37c6..d41d007 100644
--- a/langtools/test/jdk/javadoc/tool/BreakIteratorWarning.java
+++ b/langtools/test/jdk/javadoc/tool/BreakIteratorWarning.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
@@ -27,7 +27,7 @@
  * @summary Verify that (verbose) warnings are no longer generated when
  *          the default first-sentence algorithm doesn't match the
  *          BreakIterator algorithm.
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.util.ArrayList;
diff --git a/langtools/test/jdk/javadoc/tool/CheckResourceKeys.java b/langtools/test/jdk/javadoc/tool/CheckResourceKeys.java
index dc14da8..aecaaae 100644
--- a/langtools/test/jdk/javadoc/tool/CheckResourceKeys.java
+++ b/langtools/test/jdk/javadoc/tool/CheckResourceKeys.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
@@ -25,10 +25,13 @@
  * @test
  * @bug 8000612
  * @summary need test program to validate javadoc resource bundles
- * @modules jdk.jdeps/com.sun.tools.classfile
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ *          jdk.jdeps/com.sun.tools.classfile
  */
 
 import java.io.*;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.*;
 import javax.tools.*;
 import com.sun.tools.classfile.*;
@@ -253,6 +256,7 @@
      * Get the set of keys from the javadoc resource bundles.
      */
     Set<String> getResourceKeys() {
+        Module jdk_javadoc = Layer.boot().findModule("jdk.javadoc").get();
         String[] names = {
                 "jdk.javadoc.internal.doclets.formats.html.resources.standard",
                 "jdk.javadoc.internal.doclets.toolkit.resources.doclets",
@@ -260,7 +264,7 @@
         };
         Set<String> results = new TreeSet<String>();
         for (String name : names) {
-            ResourceBundle b = ResourceBundle.getBundle(name);
+            ResourceBundle b = ResourceBundle.getBundle(name, jdk_javadoc);
             results.addAll(b.keySet());
         }
         return results;
diff --git a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java
index 0dc45eb..9d9547e 100644
--- a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java
+++ b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.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
@@ -62,7 +62,6 @@
     // make sure new doclet is invoked by default
     void run1() throws Exception {
         List<String> output = doTest(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
                 "-classpath", ".", // insulates us from ambient classpath
                 "-Xdoclint:none",
                 "-package",
@@ -80,7 +79,6 @@
     void run2() throws Exception {
         List<String> output = doTest(javadoc.getPath(),
                 "-Xold",
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
                 "-classpath", ".", // insulates us from ambient classpath
                 "-Xdoclint:none",
                 "-package",
diff --git a/langtools/test/jdk/javadoc/tool/FlagsTooEarly.java b/langtools/test/jdk/javadoc/tool/FlagsTooEarly.java
index 03eba88..c711839 100644
--- a/langtools/test/jdk/javadoc/tool/FlagsTooEarly.java
+++ b/langtools/test/jdk/javadoc/tool/FlagsTooEarly.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
@@ -26,7 +26,7 @@
  * @bug 4904495
  * @summary Compilation may go awry if we ask a symbol for its flags during
  *          javac's Enter phase, before the flags are generally available.
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 
diff --git a/langtools/test/jdk/javadoc/tool/MaxWarns.java b/langtools/test/jdk/javadoc/tool/MaxWarns.java
index c7b91c2..d60284a 100644
--- a/langtools/test/jdk/javadoc/tool/MaxWarns.java
+++ b/langtools/test/jdk/javadoc/tool/MaxWarns.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8005644
  * @summary set default max errs and max warns
- * @modules jdk.javadoc/com.sun.tools.doclets.standard
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.File;
diff --git a/langtools/test/jdk/javadoc/tool/NoStar.java b/langtools/test/jdk/javadoc/tool/NoStar.java
index 5b98b09..7c1431a 100644
--- a/langtools/test/jdk/javadoc/tool/NoStar.java
+++ b/langtools/test/jdk/javadoc/tool/NoStar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -26,7 +26,7 @@
  * @bug 4587562
  * @summary tool: Indentation messed up for javadoc comments omitting preceding *
  * @author gafter
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @run main NoStar
  */
 
diff --git a/langtools/test/jdk/javadoc/tool/QuietOption.java b/langtools/test/jdk/javadoc/tool/QuietOption.java
index cd18383..cf8491f 100644
--- a/langtools/test/jdk/javadoc/tool/QuietOption.java
+++ b/langtools/test/jdk/javadoc/tool/QuietOption.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
@@ -61,7 +61,6 @@
     // make sure javadoc is quiet
     void run1() throws Exception {
         List<String> output = doTest(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
                 "-classpath", ".", // insulates us from ambient classpath
                 "-quiet",
                 new File(testSrc, thisClassName + ".java").getPath());
@@ -75,7 +74,6 @@
     // make sure javadoc is chatty
     void run2() throws Exception {
         List<String> output = doTest(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
                 "-classpath", ".", // insulates us from ambient classpath
                 new File(testSrc, thisClassName + ".java").getPath());
 
diff --git a/langtools/test/jdk/javadoc/tool/ReleaseOption.java b/langtools/test/jdk/javadoc/tool/ReleaseOption.java
index 02b2155..fde6395 100644
--- a/langtools/test/jdk/javadoc/tool/ReleaseOption.java
+++ b/langtools/test/jdk/javadoc/tool/ReleaseOption.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
@@ -34,6 +34,7 @@
  * @bug 8086737
  * @summary Test -release option in javadoc
  * @run main ReleaseOption
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 public class ReleaseOption {
     public static void main(String... args) {
diff --git a/langtools/test/jdk/javadoc/tool/T4994049/T4994049.java b/langtools/test/jdk/javadoc/tool/T4994049/T4994049.java
index 09cd17a..4303b6c 100644
--- a/langtools/test/jdk/javadoc/tool/T4994049/T4994049.java
+++ b/langtools/test/jdk/javadoc/tool/T4994049/T4994049.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
@@ -26,7 +26,7 @@
  * @bug     4994049
  * @summary Unit test for SourcePosition.column with respect to tab expansion
  * @author  Peter von der Ah\u00e9
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @run main T4994049 FileWithTabs.java
  */
 
diff --git a/langtools/test/jdk/javadoc/tool/T6551367.java b/langtools/test/jdk/javadoc/tool/T6551367.java
index 6709016..2504750 100644
--- a/langtools/test/jdk/javadoc/tool/T6551367.java
+++ b/langtools/test/jdk/javadoc/tool/T6551367.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
@@ -26,17 +26,20 @@
  * @bug     6551367
  * @summary javadoc throws ClassCastException when an link tag tries to reference constructor.
  * @author  A. Sundararajan
- * @modules jdk.javadoc/com.sun.tools.doclets.standard
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @run main T6551367 T6551367.java
  */
 
+/*
+ * ***NOTE: This is not a tool test!, should be moved to doclets.***
+ */
 import java.io.File;
 
 import jdk.javadoc.doclet.DocletEnvironment;
 
 import static jdk.javadoc.internal.tool.Main.execute;
 
-public class T6551367 extends jdk.javadoc.internal.doclets.standard.Standard {
+public class T6551367 {
     public T6551367() {}
     public boolean run(DocletEnvironment root) {
         return true;
@@ -50,8 +53,6 @@
         for (String file : args) {
             File source = new File(testSrc, file);
             String[] array = {
-                "-docletpath", System.getProperty("test.classes", "."),
-                "-doclet", "T6551367",
                 "-Xdoclint:none",
                 source.getPath(),
                 "-d",
diff --git a/langtools/test/jdk/javadoc/tool/T6968833.java b/langtools/test/jdk/javadoc/tool/T6968833.java
index d489342..8f576fa7 100644
--- a/langtools/test/jdk/javadoc/tool/T6968833.java
+++ b/langtools/test/jdk/javadoc/tool/T6968833.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6968833
  * @summary javadoc reports error but still returns 0
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.*;
diff --git a/langtools/test/jdk/javadoc/tool/VerifyLocale.java b/langtools/test/jdk/javadoc/tool/VerifyLocale.java
index 6aed87a..3b6684c 100644
--- a/langtools/test/jdk/javadoc/tool/VerifyLocale.java
+++ b/langtools/test/jdk/javadoc/tool/VerifyLocale.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8035473
  * @summary Verify that init method works correctly.
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.util.Collections;
diff --git a/langtools/test/jdk/javadoc/tool/XWerror.java b/langtools/test/jdk/javadoc/tool/XWerror.java
index a544778..5e73a23 100644
--- a/langtools/test/jdk/javadoc/tool/XWerror.java
+++ b/langtools/test/jdk/javadoc/tool/XWerror.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -26,7 +26,7 @@
  * @bug 4099527
  * @summary javadoc tool: want flag to exit nonzero if there were warnings.
  * @author gafter
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @run main XWerror
  */
 
diff --git a/langtools/test/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java b/langtools/test/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java
index c245d66..7f99eeb 100644
--- a/langtools/test/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java
+++ b/langtools/test/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.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
@@ -27,7 +27,8 @@
  * @summary javadoc should have a javax.tools.Tool service provider
  * @modules jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.util
- *          jdk.javadoc/com.sun.tools.javadoc.api
+ *          jdk.javadoc/jdk.javadoc.internal.api
+ *          jdk.javadoc/jdk.javadoc.internal.tool
  * @build APITest
  * @run main JavadocTaskImplTest
  */
diff --git a/langtools/test/jdk/javadoc/tool/completionFailure/CompletionFailure.java b/langtools/test/jdk/javadoc/tool/completionFailure/CompletionFailure.java
index 7b618e2..608e62b 100644
--- a/langtools/test/jdk/javadoc/tool/completionFailure/CompletionFailure.java
+++ b/langtools/test/jdk/javadoc/tool/completionFailure/CompletionFailure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -26,7 +26,7 @@
  * @bug 4670772 6328529
  * @summary Completion failures should be ignored in javadoc.
  * @author gafter
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 
diff --git a/langtools/test/jdk/javadoc/tool/doclint/DocLintTest.java b/langtools/test/jdk/javadoc/tool/doclint/DocLintTest.java
index 30b1a81..7975856 100644
--- a/langtools/test/jdk/javadoc/tool/doclint/DocLintTest.java
+++ b/langtools/test/jdk/javadoc/tool/doclint/DocLintTest.java
@@ -142,6 +142,7 @@
         fm = javadoc.getStandardFileManager(null, null, null);
         try {
             fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
+            fm.setLocation(StandardLocation.CLASS_PATH, Collections.<File>emptyList());
             files = Arrays.asList(new TestJFO("Test.java", code));
 
             test(Collections.<String>emptyList(),
diff --git a/langtools/test/jdk/javadoc/tool/doclint/ImplicitHeadersTest.java b/langtools/test/jdk/javadoc/tool/doclint/ImplicitHeadersTest.java
index da48307..a68ea01 100644
--- a/langtools/test/jdk/javadoc/tool/doclint/ImplicitHeadersTest.java
+++ b/langtools/test/jdk/javadoc/tool/doclint/ImplicitHeadersTest.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8006346
  * @summary doclint should make allowance for headers generated by standard doclet
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.File;
diff --git a/langtools/test/jdk/javadoc/tool/dupOk/DupOk.java b/langtools/test/jdk/javadoc/tool/dupOk/DupOk.java
index d4a12c8..05f6958 100644
--- a/langtools/test/jdk/javadoc/tool/dupOk/DupOk.java
+++ b/langtools/test/jdk/javadoc/tool/dupOk/DupOk.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -26,7 +26,7 @@
  * @bug 4673477
  * @summary The first definition found for each class should be documented
  * @author gafter
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.File;
diff --git a/langtools/test/jdk/javadoc/tool/nonConstExprs/Test.java b/langtools/test/jdk/javadoc/tool/nonConstExprs/Test.java
index 3fd1adf..889945b 100644
--- a/langtools/test/jdk/javadoc/tool/nonConstExprs/Test.java
+++ b/langtools/test/jdk/javadoc/tool/nonConstExprs/Test.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
@@ -25,7 +25,7 @@
  * @test
  * @bug     8010310
  * @summary Error processing sources with -private
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  */
 
 import java.io.File;
diff --git a/langtools/test/jdk/javadoc/tool/outputRedirect/Test.java b/langtools/test/jdk/javadoc/tool/outputRedirect/Test.java
index c8c733b..eae3443 100644
--- a/langtools/test/jdk/javadoc/tool/outputRedirect/Test.java
+++ b/langtools/test/jdk/javadoc/tool/outputRedirect/Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @bug 4587487
  * @summary jdk.javadoc.internal.tool.Main.execute ignores PrintWriters
  * @author gafter
- * @modules jdk.javadoc
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @compile p/OutputRedirect.java
  * @run main p.OutputRedirect
  */
diff --git a/langtools/test/jdk/javadoc/tool/parser/7091528/T7091528.java b/langtools/test/jdk/javadoc/tool/parser/7091528/T7091528.java
index c29debd..39a726e 100644
--- a/langtools/test/jdk/javadoc/tool/parser/7091528/T7091528.java
+++ b/langtools/test/jdk/javadoc/tool/parser/7091528/T7091528.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug     7091528 8029145 8037484
  * @summary ensures javadoc parses unique source files and ignores all class files
- * @modules jdk.javadoc/jdk.javadoc.internal.doclets.standard
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
  * @compile p/C1.java p/q/C2.java
  * @run main T7091528
  */
diff --git a/langtools/test/jdk/jshell/ClassPathTest.java b/langtools/test/jdk/jshell/ClassPathTest.java
index 1672e8a..b9df311 100644
--- a/langtools/test/jdk/jshell/ClassPathTest.java
+++ b/langtools/test/jdk/jshell/ClassPathTest.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,6 +26,7 @@
  * @summary Tests for EvalState#addToClasspath
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ToolBox Compiler
  * @run testng ClassPathTest
diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java
index 07f7fc3..b2ed67b 100644
--- a/langtools/test/jdk/jshell/CommandCompletionTest.java
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java
@@ -27,6 +27,7 @@
  * @summary Test Command Completion
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @library /tools/lib
  * @build ReplToolTesting TestingInputStream Compiler ToolBox
diff --git a/langtools/test/jdk/jshell/CompletionSuggestionTest.java b/langtools/test/jdk/jshell/CompletionSuggestionTest.java
index 68c4418..bc642b8 100644
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.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,6 +27,7 @@
  * @summary Test Completion
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ToolBox Compiler
  * @run testng CompletionSuggestionTest
diff --git a/langtools/test/jdk/jshell/ComputeFQNsTest.java b/langtools/test/jdk/jshell/ComputeFQNsTest.java
index 0f87fc7..15cdb70 100644
--- a/langtools/test/jdk/jshell/ComputeFQNsTest.java
+++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java
@@ -27,6 +27,9 @@
  * @summary Test Get FQNs
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ToolBox Compiler
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @run testng ComputeFQNsTest
  */
 
diff --git a/langtools/test/jdk/jshell/ErrorTranslationTest.java b/langtools/test/jdk/jshell/ErrorTranslationTest.java
index 682fcaa..8b9bcec 100644
--- a/langtools/test/jdk/jshell/ErrorTranslationTest.java
+++ b/langtools/test/jdk/jshell/ErrorTranslationTest.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,6 +26,7 @@
  * @summary Tests for shell error translation
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ExpectedDiagnostic ToolBox Compiler
diff --git a/langtools/test/jdk/jshell/ImportTest.java b/langtools/test/jdk/jshell/ImportTest.java
index 21f919d..6956a37 100644
--- a/langtools/test/jdk/jshell/ImportTest.java
+++ b/langtools/test/jdk/jshell/ImportTest.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,6 +26,7 @@
  * @summary Test imports
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ToolBox ExpectedDiagnostic
  * @run testng ImportTest
diff --git a/langtools/test/jdk/jshell/InferTypeTest.java b/langtools/test/jdk/jshell/InferTypeTest.java
index ce1f729..4e26bf6 100644
--- a/langtools/test/jdk/jshell/InferTypeTest.java
+++ b/langtools/test/jdk/jshell/InferTypeTest.java
@@ -26,6 +26,9 @@
  * @bug 8131027
  * @summary Test Type Inference
  * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build KullaTesting TestingInputStream ToolBox Compiler
  * @run testng InferTypeTest
  */
diff --git a/langtools/test/jdk/jshell/StartOptionTest.java b/langtools/test/jdk/jshell/StartOptionTest.java
index 9acab38..490b0b8 100644
--- a/langtools/test/jdk/jshell/StartOptionTest.java
+++ b/langtools/test/jdk/jshell/StartOptionTest.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,6 +26,7 @@
  * @summary Testing start-up options.
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @library /tools/lib
  * @build Compiler ToolBox
diff --git a/langtools/test/jdk/jshell/T8146368/JShellToolTest8146368.java b/langtools/test/jdk/jshell/T8146368/JShellToolTest8146368.java
index fc5ba96..c04598b 100644
--- a/langtools/test/jdk/jshell/T8146368/JShellToolTest8146368.java
+++ b/langtools/test/jdk/jshell/T8146368/JShellToolTest8146368.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
diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java
index cc3aa02..b255c67 100644
--- a/langtools/test/jdk/jshell/ToolFormatTest.java
+++ b/langtools/test/jdk/jshell/ToolFormatTest.java
@@ -26,6 +26,10 @@
  * @bug 8148316 8148317
  * @summary Tests for output customization
  * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ *          jdk.jshell/jdk.internal.jshell.tool
  * @build KullaTesting TestingInputStream ToolBox Compiler
  * @run testng ToolFormatTest
  */
diff --git a/langtools/test/jdk/jshell/ToolReloadTest.java b/langtools/test/jdk/jshell/ToolReloadTest.java
index 4871fcc..7ad3716 100644
--- a/langtools/test/jdk/jshell/ToolReloadTest.java
+++ b/langtools/test/jdk/jshell/ToolReloadTest.java
@@ -28,6 +28,7 @@
  * @summary Tests for /reload in JShell tool
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  *          jdk.jshell/jdk.internal.jshell.tool
  * @library /tools/lib
  * @build KullaTesting TestingInputStream ToolBox Compiler
diff --git a/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java b/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
index 85317a8..4a8ccea 100644
--- a/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
+++ b/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,9 +25,10 @@
 
 import java.io.*;
 import java.net.URL;
-import java.util.List;
 
 import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.InvalidIndex;
+import com.sun.tools.classfile.ConstantPool.UnexpectedEntry;
 
 /**
  * A class providing utilities for writing tests that inspect class
@@ -160,6 +161,7 @@
                  classTypeAnnos, methodTypeAnnos, fieldTypeAnnos);
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             final String newline = System.lineSeparator();
@@ -310,6 +312,7 @@
             this.expectedCount = expectedCount;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ");
@@ -356,7 +359,7 @@
                                      Annotation anno) {
             try {
                 return cpool.getUTF8Info(anno.type_index).value.equals("L" + expectedName + ";");
-            } catch(Exception e) {
+            } catch (InvalidIndex | UnexpectedEntry e) {
                 return false;
             }
         }
@@ -403,6 +406,7 @@
             this.methodname = methodname;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ");
@@ -454,6 +458,7 @@
             this.index = index;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ");
@@ -463,7 +468,8 @@
             sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
             sb.append(" on method ");
             sb.append(methodname);
-            sb.append(" parameter " + index);
+            sb.append(" parameter ");
+            sb.append(index);
             return sb.toString();
         }
 
@@ -493,6 +499,7 @@
             this.fieldname = fieldname;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ").append(expectedCount)
@@ -564,6 +571,7 @@
             this.typePath = typePath;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ");
@@ -766,6 +774,7 @@
             this.methodname = methodname;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ");
@@ -839,8 +848,9 @@
              * parameters that have been provided.  The default values
              * will be used for those that have not.
              *
-             * @return The cretaed {@code ExpectedMethodTypeAnnotation}.
+             * @return The created {@code ExpectedMethodTypeAnnotation}.
              */
+            @Override
             public ExpectedMethodTypeAnnotation build() {
                 return new ExpectedMethodTypeAnnotation(methodname, expectedName,
                                                         visibility, expectedCount,
@@ -890,6 +900,7 @@
             this.fieldname = fieldname;
         }
 
+        @Override
         public String toString() {
             final StringBuilder sb = new StringBuilder();
             sb.append("Expected ").append(expectedCount)
@@ -957,8 +968,9 @@
              * parameters that have been provided.  The default values
              * will be used for those that have not.
              *
-             * @return The cretaed {@code ExpectedFieldTypeAnnotation}.
+             * @return The created {@code ExpectedFieldTypeAnnotation}.
              */
+            @Override
             public ExpectedFieldTypeAnnotation build() {
                 return new ExpectedFieldTypeAnnotation(fieldname, expectedName,
                                                        visibility, expectedCount,
@@ -1163,356 +1175,215 @@
                                          Class<?> host)
         throws IOException, ConstantPoolException {
         final URL url = host.getResource(name);
-        final InputStream in = url.openStream();
-        try {
+        try (InputStream in = url.openStream()) {
             return ClassFile.read(in);
-        } finally {
-            in.close();
         }
     }
 
-    private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher =
-        new Attribute.Visitor<Void, ExpectedTypeAnnotation>() {
+    private static class AbstractAttributeVisitor<T> implements Attribute.Visitor<Void, T> {
 
         @Override
-        public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
-                                          ExpectedTypeAnnotation expected) {
+        public Void visitBootstrapMethods(BootstrapMethods_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitDefault(DefaultAttribute attr,
-                                 ExpectedTypeAnnotation expected) {
+        public Void visitConcealedPackages(ConcealedPackages_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
-                                           ExpectedTypeAnnotation expected) {
+        public Void visitDefault(DefaultAttribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
-                                             ExpectedTypeAnnotation expected) {
+        public Void visitAnnotationDefault(AnnotationDefault_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitCode(Code_attribute attr,
-                              ExpectedTypeAnnotation expected) {
+        public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitCompilationID(CompilationID_attribute attr,
-                                       ExpectedTypeAnnotation expected) {
+        public Void visitCode(Code_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitConstantValue(ConstantValue_attribute attr,
-                                       ExpectedTypeAnnotation expected) {
+        public Void visitCompilationID(CompilationID_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitDeprecated(Deprecated_attribute attr,
-                                    ExpectedTypeAnnotation expected) {
+        public Void visitConstantValue(ConstantValue_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
-                                         ExpectedTypeAnnotation expected) {
+        public Void visitDeprecated(Deprecated_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitExceptions(Exceptions_attribute attr,
-                                    ExpectedTypeAnnotation expected) {
+        public Void visitEnclosingMethod(EnclosingMethod_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitInnerClasses(InnerClasses_attribute attr,
-                                      ExpectedTypeAnnotation expected) {
+        public Void visitExceptions(Exceptions_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitLineNumberTable(LineNumberTable_attribute attr,
-                                         ExpectedTypeAnnotation expected) {
+        public Void visitHashes(Hashes_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
-                                            ExpectedTypeAnnotation expected) {
+        public Void visitInnerClasses(InnerClasses_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
-                                                ExpectedTypeAnnotation expected) {
+        public Void visitLineNumberTable(LineNumberTable_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitMethodParameters(MethodParameters_attribute attr,
-                                          ExpectedTypeAnnotation expected) {
+        public Void visitLocalVariableTable(LocalVariableTable_attribute attr, T p) {
             return null;
         }
 
         @Override
-            public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
-                                                       ExpectedTypeAnnotation expected) {
+        public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
-                                                     ExpectedTypeAnnotation expected) {
+        public Void visitMainClass(MainClass_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
-                                                            ExpectedTypeAnnotation expected) {
+        public Void visitMethodParameters(MethodParameters_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
-                                                              ExpectedTypeAnnotation expected) {
+        public Void visitModule(Module_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitSignature(Signature_attribute attr,
-                                   ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
-                                              ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitSourceFile(SourceFile_attribute attr,
-                                    ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitSourceID(SourceID_attribute attr,
-                                  ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitStackMap(StackMap_attribute attr,
-                                  ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitStackMapTable(StackMapTable_attribute attr,
-                                       ExpectedTypeAnnotation expected) {
+        public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitSynthetic(Synthetic_attribute attr,
-                                   ExpectedTypeAnnotation expected) {
+        public Void visitSignature(Signature_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
-                                                       ExpectedTypeAnnotation expected) {
-            if (expected.matchVisibility(true)) {
-                for(TypeAnnotation anno : attr.annotations) {
-                    expected.matchAnnotation(anno);
+        public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitSourceFile(SourceFile_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitSourceID(SourceID_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitStackMap(StackMap_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitStackMapTable(StackMapTable_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitSynthetic(Synthetic_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitTargetPlatform(TargetPlatform_attribute attr, T p) {
+            return null;
+        }
+
+        @Override
+        public Void visitVersion(Version_attribute attr, T p) {
+            return null;
+        }
+
+    }
+
+    private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher
+            = new AbstractAttributeVisitor<ExpectedTypeAnnotation>() {
+
+                @Override
+                public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
+                        ExpectedTypeAnnotation expected) {
+                    if (expected.matchVisibility(true)) {
+                        for (TypeAnnotation anno : attr.annotations) {
+                            expected.matchAnnotation(anno);
+                        }
+                    }
+
+                    return null;
                 }
-            }
 
-            return null;
-        }
+                @Override
+                public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
+                        ExpectedTypeAnnotation expected) {
+                    if (expected.matchVisibility(false)) {
+                        for (TypeAnnotation anno : attr.annotations) {
+                            expected.matchAnnotation(anno);
+                        }
+                    }
 
-        @Override
-        public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
-                                                         ExpectedTypeAnnotation expected) {
-            if (expected.matchVisibility(false)) {
-                for(TypeAnnotation anno : attr.annotations) {
-                    expected.matchAnnotation(anno);
+                    return null;
                 }
-            }
-
-            return null;
-        }
-    };
+            };
 
     private static Attribute.Visitor<Void, ExpectedAnnotation> annoMatcher(ConstantPool cpool) {
-        return new Attribute.Visitor<Void, ExpectedAnnotation>() {
-
-            @Override
-                public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
-                                                  ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitDefault(DefaultAttribute attr,
-                                         ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
-                                                   ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
-                                                     ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCode(Code_attribute attr,
-                                      ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCompilationID(CompilationID_attribute attr,
-                                               ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitConstantValue(ConstantValue_attribute attr,
-                                               ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitDeprecated(Deprecated_attribute attr,
-                                            ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
-                                                 ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitExceptions(Exceptions_attribute attr,
-                                            ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitInnerClasses(InnerClasses_attribute attr,
-                                              ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLineNumberTable(LineNumberTable_attribute attr,
-                                                 ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
-                                                    ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
-                                                        ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitMethodParameters(MethodParameters_attribute attr,
-                                                  ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
-                                                                    ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
-                                                                      ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
-                                                               ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
-                                                                 ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSignature(Signature_attribute attr,
-                                           ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
-                                                      ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceFile(SourceFile_attribute attr,
-                                            ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceID(SourceID_attribute attr,
-                                          ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitStackMap(StackMap_attribute attr,
-                                          ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitStackMapTable(StackMapTable_attribute attr,
-                                               ExpectedAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSynthetic(Synthetic_attribute attr,
-                                           ExpectedAnnotation expected) {
-                return null;
-            }
+        return new AbstractAttributeVisitor<ExpectedAnnotation>() {
 
             @Override
             public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
@@ -1541,163 +1412,7 @@
     }
 
     private static Attribute.Visitor<Void, ExpectedParameterAnnotation> paramMatcher(ConstantPool cpool) {
-        return new Attribute.Visitor<Void, ExpectedParameterAnnotation>() {
-
-            @Override
-                public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
-                                                  ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitDefault(DefaultAttribute attr,
-                                         ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
-                                                   ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
-                                                     ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCode(Code_attribute attr,
-                                      ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitCompilationID(CompilationID_attribute attr,
-                                               ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitConstantValue(ConstantValue_attribute attr,
-                                               ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitDeprecated(Deprecated_attribute attr,
-                                            ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
-                                                 ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitExceptions(Exceptions_attribute attr,
-                                            ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitInnerClasses(InnerClasses_attribute attr,
-                                              ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLineNumberTable(LineNumberTable_attribute attr,
-                                                 ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
-                                                    ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
-                                                        ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitMethodParameters(MethodParameters_attribute attr,
-                                                  ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-            public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
-                                                       ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-            public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
-                                                         ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
-                                                               ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
-                                                                 ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSignature(Signature_attribute attr,
-                                           ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
-                                                      ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceFile(SourceFile_attribute attr,
-                                            ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSourceID(SourceID_attribute attr,
-                                          ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitStackMap(StackMap_attribute attr,
-                                          ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitStackMapTable(StackMapTable_attribute attr,
-                                               ExpectedParameterAnnotation expected) {
-                return null;
-            }
-
-            @Override
-                public Void visitSynthetic(Synthetic_attribute attr,
-                                           ExpectedParameterAnnotation expected) {
-                return null;
-            }
+        return new AbstractAttributeVisitor<ExpectedParameterAnnotation>() {
 
             @Override
             public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
diff --git a/langtools/test/tools/all/RunCodingRules.java b/langtools/test/tools/all/RunCodingRules.java
index 643ae8e..9f52e81 100644
--- a/langtools/test/tools/all/RunCodingRules.java
+++ b/langtools/test/tools/all/RunCodingRules.java
@@ -95,7 +95,14 @@
 
             Path crulesTarget = targetDir.resolve("crules");
             Files.createDirectories(crulesTarget);
-            List<String> crulesOptions = Arrays.asList("-d", crulesTarget.toString());
+            List<String> crulesOptions = Arrays.asList(
+                    "-XaddExports:"
+                        + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                        + "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED,"
+                        + "jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED,"
+                        + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED,"
+                        + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                    "-d", crulesTarget.toString());
             javaCompiler.getTask(null, fm, noErrors, crulesOptions, null,
                     fm.getJavaFileObjectsFromFiles(crulesFiles)).call();
             Path registration = crulesTarget.resolve("META-INF/services/com.sun.source.util.Plugin");
@@ -113,8 +120,10 @@
             Path sourceTarget = targetDir.resolve("classes");
             Files.createDirectories(sourceTarget);
             String processorPath = crulesTarget.toString() + File.pathSeparator + crulesDir.toString();
-            List<String> options = Arrays.asList("-d", sourceTarget.toString(),
-                    "-processorpath", processorPath, "-Xplugin:coding_rules");
+            List<String> options = Arrays.asList(
+                    "-d", sourceTarget.toString(),
+                    "-processorpath", processorPath,
+                    "-Xplugin:coding_rules");
             javaCompiler.getTask(null, fm, noErrors, options, null,
                     fm.getJavaFileObjectsFromFiles(sources)).call();
         }
diff --git a/langtools/test/tools/doclint/tool/PathsTest.java b/langtools/test/tools/doclint/tool/PathsTest.java
index 1dd41cf..2eb3338 100644
--- a/langtools/test/tools/doclint/tool/PathsTest.java
+++ b/langtools/test/tools/doclint/tool/PathsTest.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main PathsTest
  */
@@ -70,7 +71,6 @@
         test("src/Test.java", "-classpath", "classes1" + PS + "classes2");
 
         File testJar = createJar();
-        String sysBootClassPath = System.getProperty("sun.boot.class.path");
         test("src/Test.java", "-bootclasspath",
                 testJar + PS + "classes1" + PS + "classes2");
 
@@ -87,7 +87,12 @@
         if (!pkgNotFound.matcher(out1).find())
             error("message not found: " + pkgNotFound);
 
-        String out2 = doclint("-Xmsgs", pathOpt, path, file);
+        String out2;
+        if (needTarget8(pathOpt)) {
+            out2 = doclint("-Xmsgs", "-source", "8", "-target", "8", pathOpt, path, file);
+        } else {
+            out2 = doclint("-Xmsgs", pathOpt, path, file);
+        }
         if (pkgNotFound.matcher(out2).find())
             error("unexpected message found: " + pkgNotFound);
         if (!badHtmlEntity.matcher(out1).find())
@@ -101,6 +106,15 @@
         }
     }
 
+    boolean needTarget8(String opt) {
+        switch (opt) {
+            case "-bootclasspath":
+                return true;
+            default:
+                return false;
+        }
+    }
+
     File createJar() throws IOException {
         File f = new File("test.jar");
         try (JavaFileManager fm = new JavacFileManager(new Context(), false, null)) {
diff --git a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java
index 52c5e59..57fab2f 100644
--- a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java
+++ b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main CheckEBCDICLocaleTest
  */
diff --git a/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java b/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java
index 7cf9f50..7ccce1c 100644
--- a/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java
+++ b/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile -encoding iso-8859-1 -XD-printsource T6302184.java
  * @run main HiddenOptionsShouldUseGivenEncodingTest
diff --git a/langtools/test/tools/javac/6330997/T6330997.java b/langtools/test/tools/javac/6330997/T6330997.java
index 36a0446..c5de10e 100644
--- a/langtools/test/tools/javac/6330997/T6330997.java
+++ b/langtools/test/tools/javac/6330997/T6330997.java
@@ -28,6 +28,7 @@
  * @author  Wei Tao
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  * @clean T1 T2
@@ -39,9 +40,13 @@
 import java.nio.*;
 import java.io.*;
 import java.nio.channels.*;
+
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.ClassFinder.BadClassFile;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.util.List;
 import javax.tools.ToolProvider;
 
 public class T6330997 {
@@ -51,14 +56,17 @@
         javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
         JavaCompiler compiler = JavaCompiler.instance(task.getContext());
+        Symtab syms = Symtab.instance(task.getContext());
+        Modules modules = Modules.instance(task.getContext());
+        modules.enter(List.nil(), null);
         try {
-            compiler.resolveIdent("T1").complete();
+            compiler.resolveIdent(syms.unnamedModule, "T1").complete();
         } catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException("Failed: unexpected exception while reading class T1");
         }
         try {
-            compiler.resolveIdent("T2").complete();
+            compiler.resolveIdent(syms.unnamedModule, "T2").complete();
         } catch (BadClassFile e) {
             System.err.println("Passed: expected completion failure " + e.getClass().getName());
             return;
diff --git a/langtools/test/tools/javac/6403424/T6403424.java b/langtools/test/tools/javac/6403424/T6403424.java
index 7ffce07..0345528 100644
--- a/langtools/test/tools/javac/6403424/T6403424.java
+++ b/langtools/test/tools/javac/6403424/T6403424.java
@@ -46,7 +46,8 @@
         // now compile B, which references A,
         // with TMP on classpath and tmp on bootclasspath
         File B_java = new File(testSrc, "B.java");
-        compile("-classpath",  TMP.getPath(),
+        compile("-source", "8", "-target", "8", // can't use -Xbootclasspath/p after 8
+                "-classpath",  TMP.getPath(),
                 "-Xbootclasspath/p:" + TMP.getPath().toLowerCase(),
                 "-d", ".",
                 B_java.getPath());
diff --git a/langtools/test/tools/javac/6508981/TestInferBinaryName.java b/langtools/test/tools/javac/6508981/TestInferBinaryName.java
index a573cf1..fd250ab 100644
--- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java
+++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox p.A
  * @run main TestInferBinaryName
  */
diff --git a/langtools/test/tools/javac/6589361/T6589361.java b/langtools/test/tools/javac/6589361/T6589361.java
index d44f498..4d405e4 100644
--- a/langtools/test/tools/javac/6589361/T6589361.java
+++ b/langtools/test/tools/javac/6589361/T6589361.java
@@ -28,8 +28,12 @@
                 // Note: Zip/Jar entry names use '/', not File.separator, but just to be sure,
                 // we normalize the filename as well.
                 if (file.getName().replace(File.separatorChar, '/').contains("java/lang/Object.class")) {
-                    String str = fm.inferBinaryName(StandardLocation.CLASS_PATH, file);
+                    String str = fm.inferBinaryName(StandardLocation.PLATFORM_CLASS_PATH, file);
                     if (!str.equals("java.lang.Object")) {
+                        System.err.println("file object: " + file);
+                        System.err.println("      class: " + file.getClass());
+                        System.err.println("       name: " + file.getName());
+                        System.err.println("binary name: " + str);
                         throw new AssertionError("Error in JavacFileManager.inferBinaryName method!");
                     }
                     else {
diff --git a/langtools/test/tools/javac/6627362/T6627362.java b/langtools/test/tools/javac/6627362/T6627362.java
index f6504eb..28d178d 100644
--- a/langtools/test/tools/javac/6627362/T6627362.java
+++ b/langtools/test/tools/javac/6627362/T6627362.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
@@ -27,6 +27,7 @@
  * @summary javac generates code that uses array.clone,
  *          which is not available on JavaCard
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
@@ -67,7 +68,7 @@
         // compile and disassemble E.java, using modified Object.java,
         // check for reference to System.arraycopy
         File x = new File(testSrc, "x");
-        String[] jcArgs = { "-d", ".",
+        String[] jcArgs = { "-d", ".", "-Xmodule:java.base",
                             new File(x, "E.java").getPath(),
                             new File(x, "Object.java").getPath()};
         compile(jcArgs);
diff --git a/langtools/test/tools/javac/6889255/T6889255.java b/langtools/test/tools/javac/6889255/T6889255.java
index 191c20c..6b63cc3 100644
--- a/langtools/test/tools/javac/6889255/T6889255.java
+++ b/langtools/test/tools/javac/6889255/T6889255.java
@@ -379,7 +379,7 @@
         String classname;
         while ((classname = work.poll()) != null) {
             System.err.println("Checking class " + classname);
-            ClassSymbol sym = syms.enterClass(names.table.fromString(classname));
+            ClassSymbol sym = syms.enterClass(syms.noModule, names.table.fromString(classname));
             sym.complete();
 
             if ((sym.flags() & Flags.INTERFACE) != 0 && !testInterfaces)
diff --git a/langtools/test/tools/javac/AnonymousSubclassTest.java b/langtools/test/tools/javac/AnonymousSubclassTest.java
index 8470a09..79818b6 100644
--- a/langtools/test/tools/javac/AnonymousSubclassTest.java
+++ b/langtools/test/tools/javac/AnonymousSubclassTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main AnonymousSubclassTest
  */
diff --git a/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java b/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java
index eea005e..d862163 100644
--- a/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java
+++ b/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ClassPathTest
  */
diff --git a/langtools/test/tools/javac/ConstFoldTest.java b/langtools/test/tools/javac/ConstFoldTest.java
index 40ab642..11513c5 100644
--- a/langtools/test/tools/javac/ConstFoldTest.java
+++ b/langtools/test/tools/javac/ConstFoldTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ConstFoldTest
  */
diff --git a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
index d21fb79..5b01a65 100644
--- a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
+++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
@@ -33,6 +33,7 @@
 // use /othervm to avoid locale issues
 
 import java.net.URI;
+import java.util.ResourceBundle;
 import java.util.regex.Matcher;
 import javax.tools.*;
 import com.sun.tools.javac.util.*;
@@ -373,7 +374,7 @@
         options.put("diagsIndentation", indentString);
         MyLog log = new MyLog(ctx);
         JavacMessages messages = JavacMessages.instance(ctx);
-        messages.add("tester");
+        messages.add(locale -> ResourceBundle.getBundle("tester", locale));
         JCDiagnostic.Factory diags = JCDiagnostic.Factory.instance(ctx);
         log.useSource(new MyFileObject("This is a source line"));
         JCDiagnostic d = diags.error(null, log.currentSource(),
diff --git a/langtools/test/tools/javac/ExtDirs/ExtDirTest.java b/langtools/test/tools/javac/ExtDirs/ExtDirTest.java
index 06d894f..4dec423 100644
--- a/langtools/test/tools/javac/ExtDirs/ExtDirTest.java
+++ b/langtools/test/tools/javac/ExtDirs/ExtDirTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ExtDirTest
  */
@@ -150,22 +151,27 @@
     void compileWithExtDirs() throws Exception {
         tb.new JavacTask()
                 .outdir(".")
-                .options("-extdirs", "ext1")
+                .options("-source", "8",
+                        "-extdirs", "ext1")
                 .sources(ExtDirTest_1Src)
                 .run()
                 .writeAll();
 
         tb.new JavacTask()
                 .outdir(".")
-                .options("-extdirs", "ext1" + File.pathSeparator + "ext2")
+                .options("-source", "8",
+                        "-extdirs", "ext1" + File.pathSeparator + "ext2")
                 .sources(ExtDirTest_2Src)
-                .run();
+                .run()
+                .writeAll();
 
         tb.new JavacTask()
                 .outdir(".")
-                .options("-extdirs", "ext3")
+                .options("-source", "8",
+                        "-extdirs", "ext3")
                 .sources(ExtDirTest_3Src)
-                .run();
+                .run()
+                .writeAll();
     }
 
 }
diff --git a/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java
index 21617c6..6e2c2f7 100644
--- a/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java
+++ b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main IncorrectInheritanceTest
  */
diff --git a/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java b/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
index 53c8136..f189fe3 100644
--- a/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
+++ b/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -34,15 +34,19 @@
     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 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; }
@@ -56,4 +60,6 @@
     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/MethodParametersTest.java b/langtools/test/tools/javac/MethodParametersTest.java
index e08d7b9..ba909b1 100644
--- a/langtools/test/tools/javac/MethodParametersTest.java
+++ b/langtools/test/tools/javac/MethodParametersTest.java
@@ -27,12 +27,15 @@
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.model
  *          jdk.compiler/com.sun.tools.javac.util
  */
 // key: opt.arg.parameters
 import com.sun.tools.classfile.*;
+import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.Main;
 import com.sun.tools.javac.util.Context;
@@ -138,10 +141,11 @@
         com.sun.tools.javac.code.ClassFinder cf =
             com.sun.tools.javac.code.ClassFinder.instance(context);
         Name name = Names.instance(context).fromString(Baz_name);
+        Symtab syms = Symtab.instance(context);
 
         // Now walk down the language model and check the name of the
         // parameter.
-        final Element baz = cf.loadClass(name);
+        final Element baz = cf.loadClass(syms.unnamedModule, name);
         for (Element e : baz.getEnclosedElements()) {
             if (e instanceof ExecutableElement) {
                 final ExecutableElement ee = (ExecutableElement) e;
diff --git a/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java b/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java
index dc38308..4d903fe 100644
--- a/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java
+++ b/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.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
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main MissingIncludeTest
  */
diff --git a/langtools/test/tools/javac/Object1.java b/langtools/test/tools/javac/Object1.java
deleted file mode 100644
index 70ae750..0000000
--- a/langtools/test/tools/javac/Object1.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 4091755
- * @summary java.lang.Object can't be redefined without crashing javac
- * @author gafter
- *
- * @compile/fail/ref=Object1.out -XDrawDiagnostics  Object1.java
- */
-
-package java.lang;
-class Object extends Throwable {
-    public final native Class getClass();
-    public native int hashCode();
-    public native boolean equals(Object obj);
-    protected native Object clone() throws CloneNotSupportedException;
-    public native String toString();
-    public final native void notify();
-    public final native void notifyAll();
-    public final native void wait(long timeout) throws InterruptedException;
-    public native final void wait(long timeout, int nanos) throws InterruptedException;
-    public native final void wait() throws InterruptedException;
-    protected void finalize() throws Throwable { }
-}
diff --git a/langtools/test/tools/javac/Object1.out b/langtools/test/tools/javac/Object1.out
deleted file mode 100644
index 67a342e..0000000
--- a/langtools/test/tools/javac/Object1.out
+++ /dev/null
@@ -1,2 +0,0 @@
-Object1.java:11:22: compiler.err.cyclic.inheritance: java.lang.Throwable
-1 error
diff --git a/langtools/test/tools/javac/Object2.java b/langtools/test/tools/javac/Object2.java
deleted file mode 100644
index 2186bac..0000000
--- a/langtools/test/tools/javac/Object2.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 4091755
- * @summary java.lang.Object can't be redefined without crashing javac
- * @author gafter
- *
- * @compile/fail/ref=Object2.out -XDrawDiagnostics  Object2.java
- */
-
-package java.lang;
-class Object implements Cloneable {
-    public final native Class getClass();
-    public native int hashCode();
-    public native boolean equals(Object obj);
-    public native Object clone() throws CloneNotSupportedException;
-    public native String toString();
-    public final native void notify();
-    public final native void notifyAll();
-    public final native void wait(long timeout) throws InterruptedException;
-    public native final void wait(long timeout, int nanos) throws InterruptedException;
-    public native final void wait() throws InterruptedException;
-    protected void finalize() throws Throwable { }
-}
diff --git a/langtools/test/tools/javac/Object2.out b/langtools/test/tools/javac/Object2.out
deleted file mode 100644
index b238fe4..0000000
--- a/langtools/test/tools/javac/Object2.out
+++ /dev/null
@@ -1,2 +0,0 @@
-Object2.java:11:25: compiler.err.cyclic.inheritance: java.lang.Cloneable
-1 error
diff --git a/langtools/test/tools/javac/Paths/AbsolutePathTest.java b/langtools/test/tools/javac/Paths/AbsolutePathTest.java
index 92ae325..c2e2931 100644
--- a/langtools/test/tools/javac/Paths/AbsolutePathTest.java
+++ b/langtools/test/tools/javac/Paths/AbsolutePathTest.java
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @ignore 8055768 ToolBox does not close opened files
  * @build ToolBox
  * @run main AbsolutePathTest
diff --git a/langtools/test/tools/javac/Paths/Diagnostics.sh b/langtools/test/tools/javac/Paths/Diagnostics.sh
index 954cd8a..01e08bf 100644
--- a/langtools/test/tools/javac/Paths/Diagnostics.sh
+++ b/langtools/test/tools/javac/Paths/Diagnostics.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# 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
@@ -47,9 +47,10 @@
     HorizontalRule
     echo "$@"
     output=`"$@" 2>&1`; rc="$?"
-    test -n "$output" && echo "$output"
+    output2=`echo "$output" | grep -v "bootstrap class path not set in conjunction with -source"`
+    test -n "$output2" && echo "$output"
     test $rc -eq 0 || Fail "Command \"$*\" failed with exitValue $rc";
-    case "$output" in *warning:*) gotwarning="yes";; *) gotwarning="no";; esac
+    case "$output2" in *warning:*) gotwarning="yes";; *) gotwarning="no";; esac
 
     if test "$gotwarning" = "yes" -a "$NO" = "no"; then
         Fail "Command \"$*\" printed an unexpected warning"
@@ -87,6 +88,13 @@
 Cleanup
 echo "public class Main{public static void main(String[]a){}}" > Main.java
 
+# We need to set -source 8 -target 8 for those cases where the option is
+# not legal in 9 and later. However, that triggers an additional warning
+# about not setting bootclasspath, which is filtered out in Warning.
+# The alternative would be to extract a minimal rt.jar from JDK and
+# specify that with -bootclasspath.
+SRCTRG8="-source 8 -target 8"
+
 #----------------------------------------------------------------
 # No warnings unless -Xlint:path is used
 #----------------------------------------------------------------
@@ -96,33 +104,33 @@
 #----------------------------------------------------------------
 # Warn for missing elts in user-specified paths
 #----------------------------------------------------------------
-Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path -cp ".${PS}classes"         Main.java
-Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-Xbootclasspath/p:classes" Main.java
-Warning "$javac" ${TESTTOOLVMOPTS} -Xlint      "-Xbootclasspath/a:classes" Main.java
+Warning "$javac" ${TESTTOOLVMOPTS}           -Xlint:path -cp ".${PS}classes"         Main.java
+Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-Xbootclasspath/p:classes" Main.java
+Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint      "-Xbootclasspath/a:classes" Main.java
 
-Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-endorseddirs" "classes"   Main.java
-Warning "$javac" ${TESTTOOLVMOPTS} -Xlint      "-extdirs"      "classes"   Main.java
-# Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-Xbootclasspath:classes${PS}${BCP}" Main.java
+Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-endorseddirs" "classes"   Main.java
+Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint      "-extdirs"      "classes"   Main.java
+#Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-Xbootclasspath:classes${PS}${BCP}" Main.java
 
 #----------------------------------------------------------------
 # No warning for missing elts in "system" paths
 #----------------------------------------------------------------
 # No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Djava.endorsed.dirs=classes" Main.java
 # No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Djava.ext.dirs=classes"      Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Xbootclasspath/p:classes"    Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Xbootclasspath/a:classes"    Main.java
+# No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Xbootclasspath/p:classes"    Main.java
+# No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Xbootclasspath/a:classes"    Main.java
 # No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-J-Xbootclasspath:classes${PS}${BCP}" Main.java
 
 #----------------------------------------------------------------
 # No warning if class path element exists
 #----------------------------------------------------------------
 Sys mkdir classes
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path -cp ".${PS}classes"         Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-endorseddirs"   "classes" Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-extdirs"        "classes" Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-Xbootclasspath/p:classes" Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-Xbootclasspath/a:classes" Main.java
-# No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint:path "-Xbootclasspath:classes${PS}${BCP}" Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS}           -Xlint:path -cp ".${PS}classes"         Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-endorseddirs"   "classes" Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-extdirs"        "classes" Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-Xbootclasspath/p:classes" Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-Xbootclasspath/a:classes" Main.java
+#No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint:path "-Xbootclasspath:classes${PS}${BCP}" Main.java
 
 Sys "$jar" cf classes.jar Main.class
 Sys cp classes.jar classes.war
@@ -161,17 +169,17 @@
 #----------------------------------------------------------------
 # Non-existent recursive Class-Path reference gives warning
 #----------------------------------------------------------------
-No Warning "$javac" ${TESTTOOLVMOPTS}             -classpath   classesRefRef.jar Main.java
-   Warning "$javac" ${TESTTOOLVMOPTS} -Xlint      -classpath   classesRefRef.jar Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint -Xbootclasspath/p:classesRefRef.jar Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS}                        -classpath   classesRefRef.jar Main.java
+   Warning "$javac" ${TESTTOOLVMOPTS}            -Xlint      -classpath   classesRefRef.jar Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -Xbootclasspath/p:classesRefRef.jar Main.java
 
 BadJarFile classesRef.jar
 
 #----------------------------------------------------------------
 # Non-jar file recursive Class-Path reference gives error
 #----------------------------------------------------------------
-   Error "$javac" ${TESTTOOLVMOPTS}      -classpath   classesRefRef.jar Main.java
-No Error "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/a:classesRefRef.jar Main.java
+   Error "$javac" ${TESTTOOLVMOPTS}            -classpath        classesRefRef.jar Main.java
+No Error "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xbootclasspath/a:classesRefRef.jar Main.java
 
 MkManifestWithClassPath classes
 Sys "$jar" cmf MANIFEST.MF classesRef.jar Main.class
@@ -179,23 +187,23 @@
 #----------------------------------------------------------------
 # Jar file recursive Class-Path reference is OK
 #----------------------------------------------------------------
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint      -classpath   classesRefRef.jar Main.java
-No Warning "$javac" ${TESTTOOLVMOPTS} -Xlint -Xbootclasspath/p:classesRefRef.jar Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS}            -Xlint      -classpath   classesRefRef.jar Main.java
+No Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -Xbootclasspath/p:classesRefRef.jar Main.java
 
 #----------------------------------------------------------------
 # Class-Path attribute followed in extdirs or endorseddirs
 #----------------------------------------------------------------
 Sys mkdir jars
 Sys cp classesRefRef.jar jars/.
-   Warning "$javac" ${TESTTOOLVMOPTS} -Xlint -extdirs      jars Main.java
-   Warning "$javac" ${TESTTOOLVMOPTS} -Xlint -endorseddirs jars Main.java
+   Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -extdirs      jars Main.java
+   Warning "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -endorseddirs jars Main.java
 
 #----------------------------------------------------------------
 # Bad Jar file in extdirs and endorseddirs should not be ignored
 #----------------------------------------------------------------
 BadJarFile jars/classesRef.jar
-  Error "$javac" ${TESTTOOLVMOPTS} -Xlint -extdirs      jars Main.java
-  Error "$javac" ${TESTTOOLVMOPTS} -Xlint -endorseddirs jars Main.java
+   Error "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -extdirs      jars Main.java
+   Error "$javac" ${TESTTOOLVMOPTS} ${SRCTRG8} -Xlint -endorseddirs jars Main.java
 
 Cleanup
 
diff --git a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java
index 70738d3..d85cafa 100644
--- a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java
+++ b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ProtectedInnerClassesTest
  */
diff --git a/langtools/test/tools/javac/T4093617/T4093617.java b/langtools/test/tools/javac/T4093617/T4093617.java
index 0628d3b..5162097 100644
--- a/langtools/test/tools/javac/T4093617/T4093617.java
+++ b/langtools/test/tools/javac/T4093617/T4093617.java
@@ -1,13 +1,31 @@
 /*
- * @test  /nodynamiccopyright/
+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
  * @bug     4093617
  * @summary Object has no superclass
  * @author  Peter von der Ah\u00e9
- * @compile/fail/ref=T4093617.out -XDrawDiagnostics T4093617.java
+ * @compile/module=java.base/fail/ref=T4093617.out -XDrawDiagnostics Object.java
  */
 
-package java.lang;
-
-class Object {
-    Object() { super(); }
-}
diff --git a/langtools/test/tools/javac/T4093617/T4093617.out b/langtools/test/tools/javac/T4093617/T4093617.out
index 0e654c8..1e7eba1 100644
--- a/langtools/test/tools/javac/T4093617/T4093617.out
+++ b/langtools/test/tools/javac/T4093617/T4093617.out
@@ -1,2 +1,2 @@
-T4093617.java:12:16: compiler.err.no.superclass: java.lang.Object
+Object.java:9:16: compiler.err.no.superclass: java.lang.Object
 1 error
diff --git a/langtools/test/tools/javac/T4093617/java.base/Object.java b/langtools/test/tools/javac/T4093617/java.base/Object.java
new file mode 100644
index 0000000..ab5142d
--- /dev/null
+++ b/langtools/test/tools/javac/T4093617/java.base/Object.java
@@ -0,0 +1,10 @@
+/*
+ * /nodynamiccopyright/
+ * See ../T4093617.java
+ */
+
+package java.lang;
+
+class Object {
+    Object() { super(); }
+}
diff --git a/langtools/test/tools/javac/T4965689/ClassLiteralWastesByteTest.java b/langtools/test/tools/javac/T4965689/ClassLiteralWastesByteTest.java
index 1add166..b38fe65 100644
--- a/langtools/test/tools/javac/T4965689/ClassLiteralWastesByteTest.java
+++ b/langtools/test/tools/javac/T4965689/ClassLiteralWastesByteTest.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
@@ -26,6 +26,7 @@
  * @bug 4965689
  * @summary class literal code wastes a byte
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/T5053846/MethodRefDupInConstantPoolTest.java b/langtools/test/tools/javac/T5053846/MethodRefDupInConstantPoolTest.java
index 281eea0..256161d 100644
--- a/langtools/test/tools/javac/T5053846/MethodRefDupInConstantPoolTest.java
+++ b/langtools/test/tools/javac/T5053846/MethodRefDupInConstantPoolTest.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
@@ -27,6 +27,7 @@
  * @summary javac: MethodRef entries are duplicated in the constant pool
  * @summary javac, compiler regression iterable + captured type
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/T5090006/AssertionFailureTest.java b/langtools/test/tools/javac/T5090006/AssertionFailureTest.java
index f9bdce0..f22afc4 100644
--- a/langtools/test/tools/javac/T5090006/AssertionFailureTest.java
+++ b/langtools/test/tools/javac/T5090006/AssertionFailureTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main AssertionFailureTest
  */
diff --git a/langtools/test/tools/javac/T6181889/EmptyFinallyTest.java b/langtools/test/tools/javac/T6181889/EmptyFinallyTest.java
index 4ea5406..f369cb4 100644
--- a/langtools/test/tools/javac/T6181889/EmptyFinallyTest.java
+++ b/langtools/test/tools/javac/T6181889/EmptyFinallyTest.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
@@ -26,6 +26,7 @@
  * @bug 6181889
  * @summary Empty try/finally results in bytecodes being generated
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/T6358024.java b/langtools/test/tools/javac/T6358024.java
index 51ffef9..abc61bd 100644
--- a/langtools/test/tools/javac/T6358024.java
+++ b/langtools/test/tools/javac/T6358024.java
@@ -38,9 +38,7 @@
 import javax.tools.*;
 import com.sun.source.util.*;
 import com.sun.tools.javac.api.*;
-import com.sun.tools.javac.file.*;
 import com.sun.tools.javac.file.JavacFileManager;
-import com.sun.tools.javac.main.*;
 import com.sun.tools.javac.util.*;
 
 
@@ -71,6 +69,10 @@
 
         JavacTool tool = JavacTool.create();
         List<String> flags = new ArrayList<String>();
+        flags.add("-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED");
         for (Option opt: opts) {
             flags.add(opt.name);
             for (Object arg : opt.args)
diff --git a/langtools/test/tools/javac/T6358166.java b/langtools/test/tools/javac/T6358166.java
index e6a73d6..bea8971 100644
--- a/langtools/test/tools/javac/T6358166.java
+++ b/langtools/test/tools/javac/T6358166.java
@@ -56,9 +56,15 @@
         JavacFileManager fm = new JavacFileManager(new Context(), false, null);
         JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java");
 
-        test(fm, f, "-verbose", "-d", ".");
+        String addExports = "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED";
 
-        test(fm, f, "-verbose", "-d", ".", "-XprintRounds", "-processorpath", ".", "-processor", self);
+        test(fm, f, addExports, "-verbose", "-d", ".");
+
+        test(fm, f, addExports, "-verbose", "-d", ".", "-XprintRounds", "-processorpath", ".", "-processor", self);
     }
 
     static void test(JavacFileManager fm, JavaFileObject f, String... args) throws Throwable {
diff --git a/langtools/test/tools/javac/T6403466.java b/langtools/test/tools/javac/T6403466.java
index fa49eca..1d441f2 100644
--- a/langtools/test/tools/javac/T6403466.java
+++ b/langtools/test/tools/javac/T6403466.java
@@ -57,10 +57,14 @@
             Iterable<? extends JavaFileObject> files =
                 fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java")));
 
-            Iterable<String> options = Arrays.asList("-processorpath", testClassDir,
-                                                     "-processor", self,
-                                                     "-s", ".",
-                                                     "-d", ".");
+            Iterable<String> options = Arrays.asList(
+                "-XaddExports:"
+                    + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                "-processorpath", testClassDir,
+                "-processor", self,
+                "-s", ".",
+                "-d", ".");
             JavacTask task = tool.getTask(out, fm, null, options, null, files);
 
             VerifyingTaskListener vtl = new VerifyingTaskListener(new File(testSrcDir, self + ".out"));
diff --git a/langtools/test/tools/javac/T6405099.java b/langtools/test/tools/javac/T6405099.java
index 3e8c934..5bbe9bf 100644
--- a/langtools/test/tools/javac/T6405099.java
+++ b/langtools/test/tools/javac/T6405099.java
@@ -49,16 +49,19 @@
 
     static void test(File dir) {
         String[] args = {
-            "-extdirs", dir.getPath(), "-d", ".",
+            "-source", "8", "-target", "8", // -extdirs not allowed after -target 8
+            "-extdirs", dir.getPath(),
+            "-d", ".",
             new File(System.getProperty("test.src", "."), "T6405099.java").getPath()
         };
 
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
         int rc = com.sun.tools.javac.Main.compile(args, pw);
+        pw.close();
+        System.out.println(sw);
+
         if (rc != 0)
             throw new Error("compilation failed");
-
-        System.out.println(sw);
     }
 }
diff --git a/langtools/test/tools/javac/T6406771.java b/langtools/test/tools/javac/T6406771.java
index d327b0c..bb375eb 100644
--- a/langtools/test/tools/javac/T6406771.java
+++ b/langtools/test/tools/javac/T6406771.java
@@ -8,25 +8,29 @@
  */
 
 // WARNING: White-space and layout is important in this file, especially tab characters.
+// Editing the imports and other leading text may affect the golden text in the tests field.
+// Also beware of scripts that auto-expand tabs to spaces.
 
 import java.io.*;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.*;
 import javax.annotation.processing.*;
 import javax.lang.model.*;
 import javax.lang.model.element.*;
 import javax.tools.*;
-import com.sun.tools.javac.api.*;
+
 import com.sun.source.tree.*;
 import com.sun.source.util.*;
+import com.sun.tools.javac.api.*;
 import com.sun.tools.javac.tree.JCTree;
 
-
 @SupportedAnnotationTypes("*")
 public class T6406771 extends AbstractProcessor {
     String[] tests = {
-        "line:27",
-        "line:28",
-        "line:29", "line:29",
+        "line:31",
+        "line:32",
+        "line:33", "line:33",
 //       1         2         3         4         5         6
 //3456789012345678901234567890123456789012345678901234567890
       "col:7", "col:16", "col:26",                 // this line uses spaces
@@ -41,13 +45,21 @@
         String testSrc = System.getProperty("test.src");
         String testClasses = System.getProperty("test.classes");
 
-        JavacTool tool = JavacTool.create();
+        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
             JavaFileObject f = fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, self+".java"))).iterator().next();
 
-            List<String> opts = Arrays.asList("-d", ".", "-processorpath", testClasses, "-processor", self, "-proc:only");
+            List<String> opts = Arrays.asList(
+                "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+                "-XDaccessInternalAPI",
+                "-d", ".",
+                "-processorpath", testClasses,
+                "-processor", self,
+                "-proc:only");
 
-            JavacTask task = tool.getTask(null, fm, null, opts, null, Arrays.asList(f));
+            JavacTask task = (JavacTask)tool.getTask(null, fm, null, opts, null, Arrays.asList(f));
 
             if (!task.call())
                 throw new AssertionError("failed");
diff --git a/langtools/test/tools/javac/T6435291/T6435291.java b/langtools/test/tools/javac/T6435291/T6435291.java
index ace80aa..6e3d0d5 100644
--- a/langtools/test/tools/javac/T6435291/T6435291.java
+++ b/langtools/test/tools/javac/T6435291/T6435291.java
@@ -28,6 +28,7 @@
  * @author  Wei Tao
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  * @build T
@@ -36,16 +37,22 @@
 
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.ClassFinder.BadClassFile;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.util.List;
 import javax.tools.ToolProvider;
 
 public class T6435291 {
     public static void main(String... args) {
         javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
+        Symtab syms = Symtab.instance(task.getContext());
+        //initialize unnamed module:
+        Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
         JavaCompiler compiler = JavaCompiler.instance(task.getContext());
         try {
-            compiler.resolveIdent("T").complete();
+            compiler.resolveIdent(syms.unnamedModule, "T").complete();
         } catch (BadClassFile e) {
             System.err.println("Passed: expected completion failure " + e.getClass().getName());
             return;
diff --git a/langtools/test/tools/javac/T6558476.java b/langtools/test/tools/javac/T6558476.java
index 7cd492e..2e525e5 100644
--- a/langtools/test/tools/javac/T6558476.java
+++ b/langtools/test/tools/javac/T6558476.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main/othervm -Xmx512m -Xms512m  T6558476
  */
diff --git a/langtools/test/tools/javac/T6725036.java b/langtools/test/tools/javac/T6725036.java
index 8eb72a8..63516d2 100644
--- a/langtools/test/tools/javac/T6725036.java
+++ b/langtools/test/tools/javac/T6725036.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main T6725036
  */
diff --git a/langtools/test/tools/javac/T6942649.java b/langtools/test/tools/javac/T6942649.java
index 49502ae..8cdea11 100644
--- a/langtools/test/tools/javac/T6942649.java
+++ b/langtools/test/tools/javac/T6942649.java
@@ -36,11 +36,11 @@
     }
 
     void run() throws Exception {
-        test("-XDshowClass", "com.sun.tools.javac.Main");
-        test("-XDshowClass=com.sun.tools.javac.util.Log", "com.sun.tools.javac.util.Log");
+        test("-XDshowClass", "com.sun.tools.javac.Main", false);
+        test("-XDshowClass=com.sun.tools.javac.util.Log", "com.sun.tools.javac.util.Log", false);
     }
 
-    void test(String opt, String clazz) throws Exception {
+    void test(String opt, String clazz, boolean checkLocation) throws Exception {
         System.err.println("test " + opt);
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
@@ -48,11 +48,18 @@
         pw.close();
         String out = sw.toString();
         System.err.println("javac rc=" + rc + "\n" + out);
+
         if (!out.contains(clazz))
             throw new Exception("class name not found in output");
-        int lastDot = clazz.lastIndexOf(".");
-        if (!out.contains(clazz.substring(lastDot + 1) + ".class"))
-            throw new Exception("location of class not found in output");
+
+        // (JDK 9) We can no longer guarantee to be able to show a URL for the
+        // location of the class, especially when the class is in the system image
+        if (checkLocation) {
+            int lastDot = clazz.lastIndexOf(".");
+            if (!out.contains(clazz.substring(lastDot + 1) + ".class"))
+                throw new Exception("location of class not found in output");
+        }
+
         if (!out.contains("MD5 checksum: "))
             throw new Exception("checksum not found in output");
     }
diff --git a/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java b/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java
index c9306ca..f4a37d6 100644
--- a/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java
+++ b/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.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
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main DebugPointerAtBadPositionTest
  */
diff --git a/langtools/test/tools/javac/T6972327.java b/langtools/test/tools/javac/T6972327.java
index e22f2fc..7fd2a2c 100644
--- a/langtools/test/tools/javac/T6972327.java
+++ b/langtools/test/tools/javac/T6972327.java
@@ -31,8 +31,6 @@
 import com.sun.source.tree.*;
 import com.sun.source.util.Trees;
 import com.sun.tools.javac.api.*;
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.tree.JCTree.*;
 import java.net.URI;
 import java.util.Arrays;
 import javax.tools.*;
@@ -40,14 +38,13 @@
 public class T6972327 {
 
     public static void main(String[] args) throws Exception {
-        final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         assert tool != null;
 
         String code = "\n@interface Test {}";
 
         JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null,
-            Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code)));
+            Arrays.asList("-Xjcov"), null, Arrays.asList(new MyFileObject(code)));
         CompilationUnitTree cut = ct.parse().iterator().next();
         ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
         Trees t = Trees.instance(ct);
diff --git a/langtools/test/tools/javac/T6985181.java b/langtools/test/tools/javac/T6985181.java
index f86136a..5f4c4db 100644
--- a/langtools/test/tools/javac/T6985181.java
+++ b/langtools/test/tools/javac/T6985181.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
@@ -26,6 +26,7 @@
  * @bug 6985181
  * @summary Annotations lost from classfile
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javac/T6993301.java b/langtools/test/tools/javac/T6993301.java
index ebb0474..00d8dda 100644
--- a/langtools/test/tools/javac/T6993301.java
+++ b/langtools/test/tools/javac/T6993301.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 6993301
  * @summary catch parameters do not have correct kind (i.e. ElementKind.EXCEPTION_PARAMETER)
+ * @modules jdk.compiler/com.sun.tools.javac.api
  */
 
 import com.sun.source.tree.CompilationUnitTree;
@@ -44,9 +45,7 @@
 import javax.tools.ToolProvider;
 
 /**
- *
  * @author Jan Lahoda
- * @modules jdk.compiler/com.sun.tools.javac.api
  */
 public class T6993301 {
     public static void main(String... args) throws Exception {
@@ -66,15 +65,13 @@
     }
 
     public void testExceptionParameterCorrectKind() throws IOException {
-        final String bootPath = System.getProperty("sun.boot.class.path");
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         assert tool != null;
 
         String code = "package test; public class Test { { try { } catch (NullPointerException ex) {} } }";
 
         final JavacTaskImpl ct = (JavacTaskImpl)tool.getTask(null, null, null,
-                Arrays.asList("-bootclasspath",  bootPath),
-                null, Arrays.asList(new MyFileObject(code)));
+                null, null, Arrays.asList(new MyFileObject(code)));
         CompilationUnitTree cut = ct.parse().iterator().next();
 
         ct.analyze();
diff --git a/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java b/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java
index e243b7a..5495733 100644
--- a/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java
+++ b/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main InlinedFinallyConfuseDebuggersTest
  */
diff --git a/langtools/test/tools/javac/T7040592/T7040592.java b/langtools/test/tools/javac/T7040592/T7040592.java
index e4c180a..7fa5adf 100644
--- a/langtools/test/tools/javac/T7040592/T7040592.java
+++ b/langtools/test/tools/javac/T7040592/T7040592.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,6 +26,7 @@
  * @bug 7040592
  * @summary Verify that null can be assigned freely to array types without a checkcast
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java
index fb5fa80..a6a4cde 100644
--- a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java
+++ b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.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
@@ -40,12 +40,15 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
 import javax.tools.ToolProvider;
+
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Descriptor;
@@ -53,16 +56,21 @@
 import com.sun.tools.classfile.Field;
 
 import static javax.tools.JavaFileObject.Kind.CLASS;
+
 import static com.sun.tools.classfile.AccessFlags.ACC_ENUM;
 import static com.sun.tools.classfile.AccessFlags.ACC_FINAL;
 import static com.sun.tools.classfile.AccessFlags.ACC_STATIC;
 
 public class DetectMutableStaticFields {
 
-    private static final String keyResource =
-            "com/sun/tools/javac/tree/JCTree.class";
+    private final String[] modules = {
+        "java.compiler",
+        "jdk.compiler",
+        "jdk.javadoc",
+        "jdk.jdeps"
+    };
 
-    private String[] packagesToSeekFor = new String[] {
+    private final String[] packagesToSeekFor = new String[] {
         "javax.tools",
         "javax.lang.model",
         "com.sun.javadoc",
@@ -73,61 +81,50 @@
         "com.sun.tools.javadoc",
         "com.sun.tools.javah",
         "com.sun.tools.javap",
+        "jdk.javadoc"
     };
 
     private static final Map<String, List<String>> classFieldsToIgnoreMap = new HashMap<>();
-
-    static {
-        classFieldsToIgnoreMap.
-                put("javax/tools/ToolProvider",
-                    Arrays.asList("instance"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javah/JavahTask",
-                    Arrays.asList("versionRB"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/classfile/Dependencies$DefaultFilter",
-                    Arrays.asList("instance"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javap/JavapTask",
-                    Arrays.asList("versionRB"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/doclets/formats/html/HtmlDoclet",
-                    Arrays.asList("docletToStart"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/util/JCDiagnostic",
-                    Arrays.asList("fragmentFormatter"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/util/JavacMessages",
-                    Arrays.asList("defaultBundle", "defaultMessages"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/file/ZipFileIndexCache",
-                    Arrays.asList("sharedInstance"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/file/JRTIndex",
-                    Arrays.asList("sharedInstance"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/main/JavaCompiler",
-                    Arrays.asList("versionRB"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/code/Type",
-                    Arrays.asList("moreInfo"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/util/SharedNameTable",
-                    Arrays.asList("freelist"));
-        classFieldsToIgnoreMap.
-                put("com/sun/tools/javac/util/Log",
-                    Arrays.asList("useRawMessages"));
+    private static void ignore(String className, String... fields) {
+        classFieldsToIgnoreMap.put(className, Arrays.asList(fields));
     }
 
-    private List<String> errors = new ArrayList<>();
+    static {
+        ignore("javax/tools/ToolProvider", "instance");
+        ignore("com/sun/tools/javah/JavahTask", "versionRB");
+        ignore("com/sun/tools/classfile/Dependencies$DefaultFilter", "instance");
+        ignore("com/sun/tools/javap/JavapTask", "versionRB");
+        ignore("com/sun/tools/doclets/formats/html/HtmlDoclet", "docletToStart");
+        ignore("com/sun/tools/javac/util/JCDiagnostic", "fragmentFormatter");
+        ignore("com/sun/tools/javac/util/JavacMessages", "defaultBundle", "defaultMessages");
+        ignore("com/sun/tools/javac/file/JRTIndex", "sharedInstance");
+        ignore("com/sun/tools/javac/main/JavaCompiler", "versionRB");
+        ignore("com/sun/tools/javac/code/Type", "moreInfo");
+        ignore("com/sun/tools/javac/util/SharedNameTable", "freelist");
+        ignore("com/sun/tools/javac/util/Log", "useRawMessages");
+
+        // The following static fields are used for caches of information obtained
+        // by reflective lookup, to avoid explicit references that are not available
+        // when running javac on JDK 8.
+        ignore("com/sun/tools/javac/util/ModuleHelper",
+                "addExportsMethod", "getModuleMethod", "getUnnamedModuleMethod");
+        ignore("com/sun/tools/javac/util/ModuleWrappers$ConfigurationHelper",
+                "resolveRequiresAndUsesMethod", "configurationClass");
+        ignore("com/sun/tools/javac/util/ModuleWrappers$LayerHelper",
+                "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod", "layerClass");
+        ignore("com/sun/tools/javac/util/ModuleWrappers$ModuleFinderHelper",
+                "emptyMethod", "moduleFinderInterface", "ofMethod");
+
+
+    }
+
+    private final List<String> errors = new ArrayList<>();
 
     public static void main(String[] args) {
         try {
             new DetectMutableStaticFields().run();
         } catch (Exception ex) {
-            throw new AssertionError(
-                    "Exception during test execution with cause ",
-                    ex.getCause());
+            throw new AssertionError("Exception during test execution: " + ex, ex);
         }
     }
 
@@ -138,12 +135,12 @@
             InvalidDescriptor,
             URISyntaxException {
 
-        URI resource = findResource(keyResource);
-        if (resource == null) {
-            throw new AssertionError("Resource " + keyResource +
-                "not found in the class path");
+        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
+            for (String module: modules) {
+                analyzeModule(fm, module);
+            }
         }
-        analyzeResource(resource);
 
         if (errors.size() > 0) {
             for (String error: errors) {
@@ -154,19 +151,6 @@
         }
     }
 
-    URI findResource(String className) throws URISyntaxException {
-        URI uri = getClass().getClassLoader().getResource(className).toURI();
-        if (uri.getScheme().equals("jar")) {
-            String ssp = uri.getRawSchemeSpecificPart();
-            int sep = ssp.lastIndexOf("!");
-            uri = new URI(ssp.substring(0, sep));
-        } else if (uri.getScheme().equals("file")) {
-            uri = new URI(uri.getPath().substring(0,
-                    uri.getPath().length() - keyResource.length()));
-        }
-        return uri;
-    }
-
     boolean shouldAnalyzePackage(String packageName) {
         for (String aPackage: packagesToSeekFor) {
             if (packageName.contains(aPackage)) {
@@ -176,25 +160,22 @@
         return false;
     }
 
-    void analyzeResource(URI resource)
+    void analyzeModule(StandardJavaFileManager fm, String moduleName)
         throws
             IOException,
             ConstantPoolException,
             InvalidDescriptor {
-        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
-            JavaFileManager.Location location =
-                    StandardLocation.locationFor(resource.getPath());
-            fm.setLocation(location, com.sun.tools.javac.util.List.of(
-                    new File(resource.getPath())));
+        JavaFileManager.Location location =
+                fm.getModuleLocation(StandardLocation.SYSTEM_MODULES, moduleName);
+        if (location == null)
+            throw new AssertionError("can't find module " + moduleName);
 
-            for (JavaFileObject file : fm.list(location, "", EnumSet.of(CLASS), true)) {
-                String className = fm.inferBinaryName(location, file);
-                int index = className.lastIndexOf('.');
-                String pckName = index == -1 ? "" : className.substring(0, index);
-                if (shouldAnalyzePackage(pckName)) {
-                    analyzeClassFile(ClassFile.read(file.openInputStream()));
-                }
+        for (JavaFileObject file : fm.list(location, "", EnumSet.of(CLASS), true)) {
+            String className = fm.inferBinaryName(location, file);
+            int index = className.lastIndexOf('.');
+            String pckName = index == -1 ? "" : className.substring(0, index);
+            if (shouldAnalyzePackage(pckName)) {
+                analyzeClassFile(ClassFile.read(file.openInputStream()));
             }
         }
     }
diff --git a/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java b/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java
index 83fa742..6aab478 100644
--- a/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java
+++ b/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main CheckRejectProfileBCPOptionsIfUsedTogetherTest
  */
diff --git a/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java b/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java
index 2f5fa54..8229594 100644
--- a/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java
+++ b/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main CompilerCrashWhenMixingBinariesAndSourcesTest
  */
diff --git a/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java b/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java
index 8b5a181..a33beb0 100644
--- a/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java
+++ b/langtools/test/tools/javac/T8010737/ParameterNamesAreNotCopiedToAnonymousInitTest.java
@@ -142,8 +142,16 @@
                     fm.getJavaFileObjectsFromFiles(
                     Arrays.asList(new File(System.getProperty("test.src"),
                     this.getClass().getName() + ".java")));
-            JavacTask task = (JavacTask) c.getTask(null, fm, null,
-                    Arrays.asList("-d", System.getProperty("user.dir")), null, fos);
+            java.util.List<String> options = Arrays.asList(
+                "-XaddExports:"
+                    + "jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                "-d", System.getProperty("user.dir")
+            );
+            JavacTask task = (JavacTask) c.getTask(null, fm, null, options, null, fos);
 
             BasicJavacTask impl = (BasicJavacTask)task;
             Context context = impl.getContext();
diff --git a/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java b/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java
index 8f796fc..5613e1e 100644
--- a/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java
+++ b/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main CompileErrorWithIteratorTest
  */
diff --git a/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java b/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java
index 2d99fdc..323b5c7 100644
--- a/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java
+++ b/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.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
@@ -26,11 +26,12 @@
  * @bug 8019486 8026861 8027142
  * @summary javac, generates erroneous LVT for a test case with lambda code
  * @library /tools/lib
- * @modules jdk.jdeps/com.sun.tools.classfile
- *          jdk.compiler/com.sun.tools.javac.api
+ * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main WrongLNTForLambdaTest
  */
diff --git a/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java
index 66a7442..c5173da 100644
--- a/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java
+++ b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main IncorrectSignatureDeterminationForInnerClassesTest
  */
diff --git a/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java
index b51d276..26790e4 100644
--- a/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java
+++ b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.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
@@ -26,11 +26,12 @@
  * @bug 8024039
  * @summary javac, previous solution for JDK-8022186 was incorrect
  * @library /tools/lib
- * @modules jdk.jdeps/com.sun.tools.classfile
- *          jdk.compiler/com.sun.tools.javac.api
+ * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main NoDeadCodeGenerationOnTrySmtTest
  */
diff --git a/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java
index c4355fc..8a15634 100644
--- a/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java
+++ b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ExceptionInferenceFromClassFileTest
  */
diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out
index 26e5399..df6e2bf 100644
--- a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out
+++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out
@@ -1,5 +1,5 @@
 TwrForVariable3.java:15:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable))
 TwrForVariable3.java:18:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable))
-TwrForVariable3.java:21:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null)
+TwrForVariable3.java:21:18: compiler.err.doesnt.exist: java
 TwrForVariable3.java:24:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null)
 4 errors
diff --git a/langtools/test/tools/javac/VersionOpt.java b/langtools/test/tools/javac/VersionOpt.java
index 8c5d77d..0d92962 100644
--- a/langtools/test/tools/javac/VersionOpt.java
+++ b/langtools/test/tools/javac/VersionOpt.java
@@ -44,30 +44,18 @@
         // Test functions by comparing the version string from javac against
         // a "golden" version generated automatically from the underlying JVM.
         // As such, it is only effective in testing the "standard" compiler,
-        // and not any development version being tested via -Xbootclasspath.
+        // and not any development version being tested via -Xpatch.
         // Check the version of the compiler being used, and let the test pass
         // automatically if is is a development version.
         Class<?> javacClass = com.sun.tools.javac.Main.class;
-        URL javacURL = getClass().getClassLoader().getResource(javacClass.getName().replace(".", "/") + ".class");
-        if (!javacURL.getProtocol().equals("jar") || !javacURL.getFile().contains("!")) {
-            System.err.println("javac not found in tools.jar: " + javacURL);
-            System.err.println("rest of test skipped");
-            return;
-        }
-        String javacHome = javacURL.getFile().substring(0, javacURL.getFile().indexOf("!"));
-
-        File javaHome = new File(System.getProperty("java.home"));
-        if (javaHome.getName().equals("jre"))
-            javaHome = javaHome.getParentFile();
-        File toolsJar = new File(new File(javaHome, "lib"), "tools.jar");
-
-        if (!javacHome.equalsIgnoreCase(toolsJar.toURI().toString())) {
-            System.err.println("javac not found in tools.jar: " + javacHome);
+        URL location = javacClass.getProtectionDomain().getCodeSource().getLocation();
+        if (!location.toString().equals("jrt:/jdk.compiler")) {
+            System.err.println("javac not found in system image: " + location);
             System.err.println("rest of test skipped");
             return;
         }
 
-        System.out.println("javac found in " + toolsJar);
+        System.out.println("javac found in " + location);
 
         String javaVersion = System.getProperty("java.version");
         String javaRuntimeVersion = System.getProperty("java.runtime.version");
diff --git a/langtools/test/tools/javac/annotations/SyntheticParameters.java b/langtools/test/tools/javac/annotations/SyntheticParameters.java
index dddca30..9670f76 100644
--- a/langtools/test/tools/javac/annotations/SyntheticParameters.java
+++ b/langtools/test/tools/javac/annotations/SyntheticParameters.java
@@ -27,6 +27,7 @@
  * @summary Test generation of annotations on inner class parameters.
  * @library /lib/annotations/
  * @modules jdk.jdeps/com.sun.tools.classfile
+ * @build annotations.classfile.ClassfileInspector SyntheticParameters
  * @run main SyntheticParameters
  */
 
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java
index 5ab5a76..6ab597d 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java
@@ -22,8 +22,8 @@
  */
 
 import java.io.*;
-import java.util.Set;
 import java.util.HashSet;
+import java.util.Set;
 
 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
@@ -118,7 +118,7 @@
 
         try {
             File f = writeTestFile();
-            com.sun.tools.javac.Main.compile(new String[] {"-proc:only", "-processor", "TypeProcOnly", f.getAbsolutePath()});
+            com.sun.tools.javac.Main.compile(new String[] {"-XDaccessInternalAPI", "-proc:only", "-processor", "TypeProcOnly", f.getAbsolutePath()});
         } finally {
             System.setOut(prevOut);
         }
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
index d2117a6..aa8f3a8 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile -g NestedLambdasCastedTest.java
  * @run main NestedLambdasCastedTest
diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java
index 00025e3..31535a7 100644
--- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java
@@ -52,7 +52,7 @@
  *          jdk.compiler/com.sun.tools.javac.processing
  *          jdk.compiler/com.sun.tools.javac.util
  * @compile PackageProcessor.java
- * @compile -cp . -processor PackageProcessor mypackage/Anno.java mypackage/MyClass.java mypackage/package-info.java
+ * @compile -XDaccessInternalAPI -cp . -processor PackageProcessor mypackage/Anno.java mypackage/MyClass.java mypackage/package-info.java
  */
 
 @SupportedAnnotationTypes("*")
diff --git a/langtools/test/tools/javac/api/6400303/T6400303.java b/langtools/test/tools/javac/api/6400303/T6400303.java
index f964f52..8763bcc 100644
--- a/langtools/test/tools/javac/api/6400303/T6400303.java
+++ b/langtools/test/tools/javac/api/6400303/T6400303.java
@@ -28,6 +28,7 @@
  * @author  Peter von der Ah\u00e9
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  * @compile Test1.java
@@ -39,15 +40,21 @@
 
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.util.List;
 
 public class T6400303 {
     public static void main(String... args) {
         javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
+        Symtab syms = Symtab.instance(task.getContext());
+        //initialize unnamed module:
+        Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
         JavaCompiler compiler = JavaCompiler.instance(task.getContext());
         try {
-            compiler.resolveIdent("Test$1").complete();
+            compiler.resolveIdent(syms.unnamedModule, "Test$1").complete();
         } catch (CompletionFailure ex) {
             System.err.println("Got expected completion failure: " + ex.getLocalizedMessage());
             return;
diff --git a/langtools/test/tools/javac/api/6412656/T6412656.java b/langtools/test/tools/javac/api/6412656/T6412656.java
index 6b45510..0924d5d 100644
--- a/langtools/test/tools/javac/api/6412656/T6412656.java
+++ b/langtools/test/tools/javac/api/6412656/T6412656.java
@@ -34,11 +34,9 @@
  */
 
 import java.io.IOException;
-import java.util.Set;
-import java.util.Collections;
+import java.util.*;
 import javax.lang.model.element.TypeElement;
 import javax.annotation.processing.*;
-import com.sun.tools.javac.processing.AnnotationProcessingError;
 
 
 public class T6412656 extends ToolTester {
@@ -67,6 +65,7 @@
         MyProc(T6412656 test) {
             this.test = test;
         }
+
         public boolean process(Set<? extends TypeElement> annotations,
                                RoundEnvironment roundEnv) {
             test.count++;
diff --git a/langtools/test/tools/javac/api/6418694/T6418694.java b/langtools/test/tools/javac/api/6418694/T6418694.java
index 964acc1..8eb2375 100644
--- a/langtools/test/tools/javac/api/6418694/T6418694.java
+++ b/langtools/test/tools/javac/api/6418694/T6418694.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
@@ -45,6 +45,7 @@
             case SOURCE_PATH:
             case CLASS_OUTPUT:
             case PLATFORM_CLASS_PATH:
+            case SYSTEM_MODULES:
                 if (!fm.hasLocation(loc))
                     throw new AssertionError("Missing location " + loc);
                 break;
diff --git a/langtools/test/tools/javac/api/6440528/T6440528.java b/langtools/test/tools/javac/api/6440528/T6440528.java
index c67dd29..ef94ccb 100644
--- a/langtools/test/tools/javac/api/6440528/T6440528.java
+++ b/langtools/test/tools/javac/api/6440528/T6440528.java
@@ -28,7 +28,7 @@
  * @author  Peter von der Ah\u00e9
  * @library ../lib
  * @modules java.compiler
- *          jdk.compiler
+ *          jdk.compiler/com.sun.tools.javac.file
  * @build ToolTester
  * @compile T6440528.java
  * @run main T6440528
diff --git a/langtools/test/tools/javac/api/6557752/T6557752.java b/langtools/test/tools/javac/api/6557752/T6557752.java
index 1db1c60..2c7adb3 100644
--- a/langtools/test/tools/javac/api/6557752/T6557752.java
+++ b/langtools/test/tools/javac/api/6557752/T6557752.java
@@ -38,7 +38,6 @@
 import com.sun.source.util.TreePath;
 import com.sun.source.util.TreePathScanner;
 import com.sun.source.util.Trees;
-import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.util.List;
 import java.io.IOException;
 import java.net.URI;
diff --git a/langtools/test/tools/javac/api/6852595/T6852595.java b/langtools/test/tools/javac/api/6852595/T6852595.java
index 82f4816..85b4b0c 100644
--- a/langtools/test/tools/javac/api/6852595/T6852595.java
+++ b/langtools/test/tools/javac/api/6852595/T6852595.java
@@ -42,7 +42,6 @@
 import com.sun.source.tree.*;
 import com.sun.source.util.TreePath;
 import com.sun.source.util.Trees;
-import com.sun.tools.javac.api.JavacTrees;
 import com.sun.tools.javac.tree.JCTree.*;
 
 import static javax.tools.JavaFileObject.Kind;
diff --git a/langtools/test/tools/javac/api/T6358786.java b/langtools/test/tools/javac/api/T6358786.java
index 32ea1a7..811a74c 100644
--- a/langtools/test/tools/javac/api/T6358786.java
+++ b/langtools/test/tools/javac/api/T6358786.java
@@ -30,15 +30,15 @@
  * @run main T6358786 T6358786.java
  */
 
-import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.file.JavacFileManager;
-import java.util.Arrays;
-
-import javax.lang.model.util.Elements;
 import java.io.*;
-import javax.lang.model.element.TypeElement;
+import java.util.*;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.util.Elements;
 import javax.tools.*;
 
+import com.sun.tools.javac.api.JavacTaskImpl;
+
 /**
  * Tests that doccomments are available from the Tree API.
  */
@@ -48,9 +48,12 @@
         try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
             String srcdir = System.getProperty("test.src");
             File file = new File(srcdir, args[0]);
-            JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, fm.getJavaFileObjectsFromFiles(Arrays.asList(file)));
+            List<String> options = Arrays.asList(
+                "-XaddExports:jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"
+            );
+            JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, fm, null, options, null, fm.getJavaFileObjectsFromFiles(Arrays.asList(file)));
             Elements elements = task.getElements();
-            for (TypeElement clazz : task.enter(task.parse())) {
+            for (Element clazz : task.enter(task.parse())) {
                 String doc = elements.getDocComment(clazz);
                 if (doc == null)
                     throw new AssertionError(clazz.getSimpleName() + ": no doc comment");
diff --git a/langtools/test/tools/javac/api/T6397104.java b/langtools/test/tools/javac/api/T6397104.java
index 9795d06..d2f6fb4 100644
--- a/langtools/test/tools/javac/api/T6397104.java
+++ b/langtools/test/tools/javac/api/T6397104.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
@@ -61,15 +61,22 @@
         if (!fileObjectFile.equals(expectedFile))
             throw new AssertionError("Expected " + expectedFile +
                                      ", got " + fileObjectFile);
-        System.out.format("OK: (%s, %s) => %s%n", siblingFile, relName, fileObjectFile);
+        System.err.format("OK: (%s, %s) => %s%n", siblingFile, relName, fileObjectFile);
     }
 
     void test(boolean hasLocation, File siblingFile, String relName, String expectedPath)
         throws Exception
     {
+        System.err.format("test: hasLocation:%s, siblingFile:%s, relName:%s, expectedPath:%s%n",
+                hasLocation, siblingFile, relName, expectedPath);
         try (StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
             if (hasLocation) {
                 for (Location location : StandardLocation.values()) {
+                    System.err.format("  location:%s, moduleLocn:%b%n",
+                        location, location.isModuleLocation());
+                    if (location.isModuleLocation()) {
+                        continue;
+                    }
                     fm.setLocation(location, Arrays.asList(new File(".")));
                     test(fm, location, siblingFile, relName, expectedPath);
                 }
diff --git a/langtools/test/tools/javac/api/T6412669.java b/langtools/test/tools/javac/api/T6412669.java
index 2cd9c84..5d1ce55 100644
--- a/langtools/test/tools/javac/api/T6412669.java
+++ b/langtools/test/tools/javac/api/T6412669.java
@@ -51,7 +51,11 @@
             fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(testClasses));
             Iterable<? extends JavaFileObject> files =
                 fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, T6412669.class.getName()+".java")));
-            String[] opts = { "-proc:only", "-processor", T6412669.class.getName()};
+            String[] opts = {
+                "-proc:only",
+                "-processor", T6412669.class.getName(),
+                "-XaddExports:jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"
+            };
             StringWriter sw = new StringWriter();
             JavacTask task = tool.getTask(sw, fm, null, Arrays.asList(opts), null, files);
             boolean ok = task.call();
diff --git a/langtools/test/tools/javac/api/TestClientCodeWrapper.java b/langtools/test/tools/javac/api/TestClientCodeWrapper.java
index 263ac6a..cd86281 100644
--- a/langtools/test/tools/javac/api/TestClientCodeWrapper.java
+++ b/langtools/test/tools/javac/api/TestClientCodeWrapper.java
@@ -39,9 +39,10 @@
 import javax.lang.model.*;
 import javax.lang.model.element.*;
 import javax.tools.*;
+import javax.tools.JavaFileObject.Kind;
+
 import com.sun.source.util.*;
 import com.sun.tools.javac.api.*;
-import javax.tools.JavaFileObject.Kind;
 
 public class TestClientCodeWrapper extends JavacTestingAbstractProcessor {
     public static void main(String... args) throws Exception {
@@ -60,7 +61,8 @@
         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
             defaultFileManager = fm;
 
-            for (Method m: getMethodsExcept(JavaFileManager.class, "close", "getJavaFileForInput")) {
+            for (Method m: getMethodsExcept(JavaFileManager.class,
+                        "close", "getJavaFileForInput", "getModuleLocation", "getServiceLoader")) {
                 test(m);
             }
 
@@ -131,6 +133,7 @@
         PrintWriter pw = new PrintWriter(sw);
 
         List<String> javacOptions = Arrays.asList(
+                "-XaddExports:jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
                 "-extdirs", extDirs.getPath(), // for use by filemanager handleOption
                 "-processor", TestClientCodeWrapper.class.getName()
                 );
@@ -320,6 +323,12 @@
         }
 
         @Override
+        public <S> ServiceLoader getServiceLoader(Location location, Class<S> service) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "getServiceLoader");
+            return super.getServiceLoader(location, service);
+        }
+
+        @Override
         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
             throwUserExceptionIfNeeded(fileManagerMethod, "list");
             return wrap(super.list(location, packageName, kinds, recurse));
@@ -391,8 +400,32 @@
             return super.isSupportedOption(option);
         }
 
+        @Override
+        public Location getModuleLocation(Location location, String moduleName) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "getModuleLocation");
+            return super.getModuleLocation(location, moduleName);
+        }
+
+        @Override
+        public Location getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "getModuleLocation");
+            return super.getModuleLocation(location, fo, pkgName);
+        }
+
+        @Override
+        public String inferModuleName(Location location) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "inferModuleName");
+            return super.inferModuleName(location);
+        }
+
+        @Override
+        public Iterable<Set<Location>> listModuleLocations(Location location) throws IOException {
+            throwUserExceptionIfNeeded(fileManagerMethod, "listModuleLocations");
+            return super.listModuleLocations(location);
+        }
+
         public FileObject wrap(FileObject fo) {
-            if (fileObjectMethod == null)
+            if (fileObjectMethod == null || fo == null)
                 return fo;
             return new UserFileObject(fileObjectMethod, (JavaFileObject)fo);
         }
@@ -405,7 +438,7 @@
         }
 
         public JavaFileObject wrap(JavaFileObject fo) {
-            if (fileObjectMethod == null)
+            if (fileObjectMethod == null || fo == null)
                 return fo;
             return new UserFileObject(fileObjectMethod, fo);
         }
diff --git a/langtools/test/tools/javac/api/TestGetElementReference.java b/langtools/test/tools/javac/api/TestGetElementReference.java
index 62de3df..52ee979 100644
--- a/langtools/test/tools/javac/api/TestGetElementReference.java
+++ b/langtools/test/tools/javac/api/TestGetElementReference.java
@@ -36,7 +36,9 @@
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.lang.model.element.Element;
@@ -50,10 +52,21 @@
 public class TestGetElementReference {
 
     public static void main(String... args) throws IOException {
-        File source = new File(System.getProperty("test.src", "."), "TestGetElementReferenceData.java").getAbsoluteFile();
+        analyze("TestGetElementReferenceData.java");
+        analyze("mod/module-info.java", "mod/api/pkg/Api.java");
+    }
+
+    private static void analyze(String... fileNames) throws IOException {
         try (StandardJavaFileManager fm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) {
+            List<JavaFileObject> files = new ArrayList<>();
+            for (String fileName : fileNames) {
+                File source = new File(System.getProperty("test.src", "."), fileName.replace('/', File.separatorChar)).getAbsoluteFile();
+                for (JavaFileObject f : fm.getJavaFileObjects(source)) {
+                    files.add(f);
+                }
+            }
             DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
-            JavacTask ct = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, diagnostics, Arrays.asList("-Xjcov"), null, fm.getJavaFileObjects(source));
+            JavacTask ct = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, diagnostics, Arrays.asList("-Xjcov"), null, files);
             Trees trees = Trees.instance(ct);
             CompilationUnitTree cut = ct.parse().iterator().next();
 
@@ -70,12 +83,16 @@
 
             while (m.find()) {
                 TreePath tp = pathFor(trees, cut, m.start() - 1);
-                Element found = trees.getElement(tp);
                 String expected = m.group(1);
+                if (expected.startsWith("getParentPath:")) {
+                    tp = tp.getParentPath();
+                    expected = expected.substring("getParentPath:".length());
+                }
+                Element found = trees.getElement(tp);
                 String actual = found != null ? found.getKind() + ":" + symbolToString(found) : "<null>";
 
                 if (!expected.equals(actual)) {
-                    throw new IllegalStateException("expected=" + expected + "; actual=" + actual);
+                    throw new IllegalStateException("expected=" + expected + "; actual=" + actual + "; tree: " + tp.getLeaf());
                 }
             }
         }
diff --git a/langtools/test/tools/javac/api/TestJavacTask.java b/langtools/test/tools/javac/api/TestJavacTask.java
index 4691cbb..c17f7d0 100644
--- a/langtools/test/tools/javac/api/TestJavacTask.java
+++ b/langtools/test/tools/javac/api/TestJavacTask.java
@@ -31,10 +31,11 @@
  */
 
 import com.sun.tools.javac.api.JavacTaskImpl;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
-import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.Element;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
@@ -53,7 +54,7 @@
         String srcdir = System.getProperty("test.src");
         File file = new File(srcdir, args[0]);
         JavacTaskImpl task = getTask(file);
-        for (TypeElement clazz : task.enter(task.parse()))
+        for (Element clazz : task.enter(task.parse()))
             System.out.println(clazz.getSimpleName());
     }
 
diff --git a/langtools/test/tools/javac/api/TestJavacTaskScanner.java b/langtools/test/tools/javac/api/TestJavacTaskScanner.java
index ab58769..e2c1385 100644
--- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java
+++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java
@@ -39,15 +39,18 @@
 import com.sun.tools.javac.parser.*;
 import com.sun.tools.javac.parser.Tokens.Token;
 import com.sun.tools.javac.util.*;
+
 import java.io.*;
 import java.net.*;
 import java.nio.*;
 import java.nio.charset.Charset;
 import java.util.Arrays;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.Types;
 import javax.tools.*;
@@ -70,7 +73,12 @@
         final Iterable<? extends JavaFileObject> compilationUnits =
             fm.getJavaFileObjects(new File[] {file});
         StandardJavaFileManager fm = getLocalFileManager(tool, null, null);
-        task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, compilationUnits);
+        java.util.List<String> options = Arrays.asList("-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED");
+        task = (JavacTaskImpl)tool.getTask(null, fm, null, options, null, compilationUnits);
         task.getContext().put(ScannerFactory.scannerFactoryKey,
                 new MyScanner.Factory(task.getContext(), this));
         elements = task.getElements();
@@ -79,7 +87,7 @@
 
     public void run() {
         Iterable<? extends TypeElement> toplevels;
-        toplevels = task.enter(task.parse());
+        toplevels = ElementFilter.typesIn(task.enter(task.parse()));
         for (TypeElement clazz : toplevels) {
             System.out.format("Testing %s:%n%n", clazz.getSimpleName());
             testParseType(clazz);
diff --git a/langtools/test/tools/javac/api/TestResolveError.java b/langtools/test/tools/javac/api/TestResolveError.java
index e121e72..7258fca 100644
--- a/langtools/test/tools/javac/api/TestResolveError.java
+++ b/langtools/test/tools/javac/api/TestResolveError.java
@@ -37,6 +37,7 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.Types;
 import javax.tools.*;
@@ -69,7 +70,7 @@
         types = task.getTypes();
 
         Iterable<? extends TypeElement> toplevels;
-        toplevels = task.enter(task.parse());
+        toplevels = ElementFilter.typesIn(task.enter(task.parse()));
 
         for (TypeElement clazz : toplevels) {
             System.out.format("Testing %s:%n%n", clazz.getSimpleName());
diff --git a/langtools/test/tools/javac/api/TestResolveIdent.java b/langtools/test/tools/javac/api/TestResolveIdent.java
index 6c1c7c6..165a0cd 100644
--- a/langtools/test/tools/javac/api/TestResolveIdent.java
+++ b/langtools/test/tools/javac/api/TestResolveIdent.java
@@ -28,17 +28,18 @@
  * @author  Peter von der Ah\u00e9
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  * @run main TestResolveIdent
  */
 
 import com.sun.tools.javac.api.JavacTaskImpl;
-import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.main.JavaCompiler;
-import java.io.File;
+import com.sun.tools.javac.util.List;
 import java.io.IOException;
-import javax.lang.model.element.TypeElement;
 import javax.tools.ToolProvider;
 
 public class TestResolveIdent {
@@ -52,7 +53,10 @@
         javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
         JavaCompiler compiler = JavaCompiler.instance(task.getContext());
-        System.out.println(compiler.resolveIdent(getDeprecatedClass().getCanonicalName()));
+        Symtab syms = Symtab.instance(task.getContext());
+        Modules modules = Modules.instance(task.getContext());
+        modules.enter(List.nil(), null);
+        System.out.println(compiler.resolveIdent(syms.unnamedModule, getDeprecatedClass().getCanonicalName()));
     }
 
 }
diff --git a/langtools/test/tools/javac/api/TestSearchPaths.java b/langtools/test/tools/javac/api/TestSearchPaths.java
index 4452979..0c91bba 100644
--- a/langtools/test/tools/javac/api/TestSearchPaths.java
+++ b/langtools/test/tools/javac/api/TestSearchPaths.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
@@ -96,7 +96,8 @@
 
             // future-proof: guard against new StandardLocations being added
             if (!tested.equals(EnumSet.allOf(StandardLocation.class))) {
-                error("not all standard locations have been tested");
+                // FIXME: need to update for JDK 9 locations
+                // error("not all standard locations have been tested");
                 out.println("not yet tested: " + EnumSet.complementOf(tested));
             }
 
@@ -213,6 +214,7 @@
         setLocation(CLASS_PATH); // empty
         setLocation(SOURCE_PATH); // empty
 
+        // Use -source 8 -target 8 to enable use of platform class path options
         // FIXME: temporarily exclude cases referring to default bootclasspath
         // for (int i = 1; i <= 10; i++) {
         int[] cases = new int[] { 1, 2, 4, 5, 6, 7 };
@@ -231,7 +233,9 @@
 
             switch (i) {
                 case 1:
-                    options = getOptions("-d", classes.getPath(), "-Xbootclasspath/p:" + testClasses);
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-Xbootclasspath/p:" + testClasses);
                     mode = Mode.STARTS_WITH;
                     match = Arrays.asList(testClasses);
                     break;
@@ -240,9 +244,10 @@
                     // the default values for -extdirs and -endorseddirs come after the bootclasspath;
                     // so to check -Xbootclasspath/a: we specify empty values for those options.
                     options = getOptions("-d", classes.getPath(),
-                            "-Xbootclasspath/a:" + testClasses,
-                            "-extdirs", "",
-                            "-endorseddirs", "");
+                        "-source", "8", "-target", "8",
+                        "-Xbootclasspath/a:" + testClasses,
+                        "-extdirs", "",
+                        "-endorseddirs", "");
                     mode = Mode.ENDS_WITH;
                     match = Arrays.asList(testClasses);
                     break;
@@ -258,7 +263,9 @@
                     fileManager.setLocation(PLATFORM_CLASS_PATH, null);
                     jar = new File(testJars, "j" + i + ".jar");
                     writeJar(jar, testClasses, "C" + i + ".class");
-                    options = getOptions("-d", classes.getPath(), "-endorseddirs", testJars.getPath());
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-endorseddirs", testJars.getPath());
                     mode = Mode.CONTAINS;
                     match = Arrays.asList(jar);
                     break;
@@ -267,7 +274,9 @@
                     fileManager.setLocation(PLATFORM_CLASS_PATH, null);
                     jar = new File(testJars, "j" + i + ".jar");
                     writeJar(jar, testClasses, "C" + i + ".class");
-                    options = getOptions("-d", classes.getPath(), "-Djava.endorsed.dirs=" + testJars.getPath());
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-Djava.endorsed.dirs=" + testJars.getPath());
                     mode = Mode.CONTAINS;
                     match = Arrays.asList(jar);
                     break;
@@ -276,7 +285,9 @@
                     fileManager.setLocation(PLATFORM_CLASS_PATH, null);
                     jar = new File(testJars, "j" + i + ".jar");
                     writeJar(jar, testClasses, "C" + i + ".class");
-                    options = getOptions("-d", classes.getPath(), "-extdirs", testJars.getPath());
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-extdirs", testJars.getPath());
                     mode = Mode.CONTAINS;
                     match = Arrays.asList(jar);
                     break;
@@ -285,7 +296,9 @@
                     fileManager.setLocation(PLATFORM_CLASS_PATH, null);
                     jar = new File(testJars, "j" + i + ".jar");
                     writeJar(jar, testClasses, "C" + i + ".class");
-                    options = getOptions("-d", classes.getPath(), "-Djava.ext.dirs=" + testJars.getPath());
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-Djava.ext.dirs=" + testJars.getPath());
                     mode = Mode.CONTAINS;
                     match = Arrays.asList(jar);
                     break;
@@ -299,7 +312,9 @@
                     break;
 
                 default:
-                    options = getOptions("-d", classes.getPath(), "-bootclasspath", defaultPathString);
+                    options = getOptions("-d", classes.getPath(),
+                        "-source", "8", "-target", "8",
+                        "-bootclasspath", defaultPathString);
                     mode = Mode.EQUALS;
                     match = defaultPath;
                     reference = "";
diff --git a/langtools/test/tools/javac/api/TestTrees.java b/langtools/test/tools/javac/api/TestTrees.java
index 567bf51..3b730c2 100644
--- a/langtools/test/tools/javac/api/TestTrees.java
+++ b/langtools/test/tools/javac/api/TestTrees.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
@@ -25,14 +25,9 @@
  * @test
  * @bug 6346249 6392177 6411385
  * @summary new Trees API
- * @modules jdk.compiler/com.sun.tools.javac.api
- *          jdk.compiler/com.sun.tools.javac.code
- *          jdk.compiler/com.sun.tools.javac.file
- *          jdk.compiler/com.sun.tools.javac.tree
+ * @modules jdk.compiler/com.sun.tools.javac.tree
  */
 
-import com.sun.source.tree.*;
-import com.sun.source.util.*;
 import java.io.*;
 import java.lang.annotation.*;
 import java.util.*;
@@ -41,14 +36,15 @@
 import javax.lang.model.element.*;
 import javax.lang.model.type.*;
 import javax.tools.*;
-import com.sun.tools.javac.api.JavacTool;
+
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.TreeInfo;
 
 @Anno
 @SupportedAnnotationTypes("*")
 public class TestTrees extends AbstractProcessor {
-
     @Anno
     void annoMethod() { }
 
@@ -70,7 +66,7 @@
 
     void run() throws IOException {
 
-        JavacTool tool = JavacTool.create();
+        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
 
         DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
                 public void report(Diagnostic d) {
@@ -82,20 +78,30 @@
             Iterable<? extends JavaFileObject> files =
                 fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java")));
 
-            Iterable<String> opts = Arrays.asList("-d", ".", "-XDcompilePolicy=simple");
+            Iterable<String> opts = Arrays.asList(
+                "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+                "-d", ".",
+                "-XDcompilePolicy=simple");
 
             System.err.println("simple compilation, no processing");
-            JavacTask task = tool.getTask(out, fm, dl, opts, null, files);
+            JavacTask task = (JavacTask) tool.getTask(out, fm, dl, opts, null, files);
             task.setTaskListener(new MyTaskListener(task));
             if (!task.call())
                 throw new AssertionError("compilation failed");
 
-            opts =  Arrays.asList("-d", ".", "-processorpath", testClassDir, "-processor", self,
+            opts =  Arrays.asList(
+                "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+                "-XDaccessInternalAPI",
+                "-d", ".",
+                "-processorpath", testClassDir,
+                "-processor", self,
                 "-XDcompilePolicy=simple");
 
             System.err.println();
             System.err.println("compilation with processing");
-            task = tool.getTask(out, fm, dl,opts, null, files);
+            task = (JavacTask) tool.getTask(out, fm, dl,opts, null, files);
             if (!task.call())
                 throw new AssertionError("compilation failed");
 
diff --git a/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java b/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java
index 71bcec1..aa940ea 100644
--- a/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java
+++ b/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main HelloWorldTest
  */
diff --git a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java
index 3c00f8c..3d2936e 100644
--- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java
+++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ToolProviderTest1
  */
diff --git a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java
index 200d6cb..176612e 100644
--- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java
+++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ToolProviderTest2
  */
diff --git a/langtools/test/tools/javac/api/mod/api/pkg/Api.java b/langtools/test/tools/javac/api/mod/api/pkg/Api.java
new file mode 100644
index 0000000..3aaed29
--- /dev/null
+++ b/langtools/test/tools/javac/api/mod/api/pkg/Api.java
@@ -0,0 +1,27 @@
+/*
+ * 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 api.pkg;
+public class Api implements Runnable {
+     public void run() {}
+}
diff --git a/langtools/test/tools/javac/api/mod/module-info.java b/langtools/test/tools/javac/api/mod/module-info.java
new file mode 100644
index 0000000..5b88a32
--- /dev/null
+++ b/langtools/test/tools/javac/api/mod/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module mod {/*getElement:MODULE:mod*/
+    requires java.base/*getElement:MODULE:java.base*/;
+    exports api/*getElement:PACKAGE:api*/.pkg/*getElement:PACKAGE:api.pkg*/ to java.desktop/*getElement:MODULE:java.desktop*/;
+    uses java/*getElement:PACKAGE:java*/.lang/*getElement:PACKAGE:java.lang*/.Runnable/*getElement:INTERFACE:java.lang.Runnable*/;
+    provides java/*getElement:PACKAGE:java*/.lang/*getElement:PACKAGE:java.lang*/.Runnable/*getElement:INTERFACE:java.lang.Runnable*/
+    with     api/*getElement:PACKAGE:api*/.pkg/*getElement:PACKAGE:api.pkg*/.Api/*getElement:CLASS:api.pkg.Api*/;
+}/*getElement:getParentPath:MODULE:mod*/
diff --git a/langtools/test/tools/javac/api/taskListeners/CompileEvent.java b/langtools/test/tools/javac/api/taskListeners/CompileEvent.java
index 08546af..0da7848 100644
--- a/langtools/test/tools/javac/api/taskListeners/CompileEvent.java
+++ b/langtools/test/tools/javac/api/taskListeners/CompileEvent.java
@@ -68,7 +68,7 @@
         //when starting compiler using Main.compile
         out = new StringWriter();
         int mainResult = Main.compile(new String[] {
-            "-Xplugin:compile-event", "-processorpath", testClasses, test.getAbsolutePath()
+            "-XDaccessInternalAPI", "-Xplugin:compile-event", "-processorpath", testClasses, test.getAbsolutePath()
         }, new PrintWriter(out, true));
         if (mainResult != 0)
             throw new AssertionError("Compilation failed unexpectedly, exit code: " + mainResult);
@@ -81,7 +81,7 @@
             //test events fired to listeners registered from plugins
             //when starting compiler using JavaCompiler.getTask(...).call
             List<String> options =
-                    Arrays.asList("-Xplugin:compile-event", "-processorpath", testClasses);
+                    Arrays.asList("-XDaccessInternalAPI", "-Xplugin:compile-event", "-processorpath", testClasses);
             out = new StringWriter();
             boolean compResult = comp.getTask(out, null, null, options, null, testFileObjects).call();
             if (!compResult)
diff --git a/langtools/test/tools/javac/boxing/IncrementBoxedAndAccess.java b/langtools/test/tools/javac/boxing/IncrementBoxedAndAccess.java
index f6fd6b9..0066d19 100644
--- a/langtools/test/tools/javac/boxing/IncrementBoxedAndAccess.java
+++ b/langtools/test/tools/javac/boxing/IncrementBoxedAndAccess.java
@@ -25,6 +25,9 @@
  * @test
  * @bug 8143388
  * @summary Verify that boxed postfix operator works properly when referring to super class' field.
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  */
 
diff --git a/langtools/test/tools/javac/cast/intersection/model/Model01.java b/langtools/test/tools/javac/cast/intersection/model/Model01.java
index 63b8fc4..9998483 100644
--- a/langtools/test/tools/javac/cast/intersection/model/Model01.java
+++ b/langtools/test/tools/javac/cast/intersection/model/Model01.java
@@ -29,7 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.code
  *          jdk.compiler/com.sun.tools.javac.tree
  * @build JavacTestingAbstractProcessor ModelChecker
- * @compile -processor ModelChecker Model01.java
+ * @compile -XDaccessInternalAPI -processor ModelChecker Model01.java
  */
 
 import javax.lang.model.element.ElementKind;
diff --git a/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java
index 2c9a4eb..3aaa965 100644
--- a/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java
+++ b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -45,7 +45,6 @@
 
 @SupportedAnnotationTypes("Check")
 public class ModelChecker extends JavacTestingAbstractProcessor {
-
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (roundEnv.processingOver())
diff --git a/langtools/test/tools/javac/classfiles/InnerClasses/T8068517.java b/langtools/test/tools/javac/classfiles/InnerClasses/T8068517.java
index 9508b13..ce55cbe 100644
--- a/langtools/test/tools/javac/classfiles/InnerClasses/T8068517.java
+++ b/langtools/test/tools/javac/classfiles/InnerClasses/T8068517.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,16 +21,17 @@
  * questions.
  */
 
-/** @test
- *  @bug 8034854
- *  @summary Verify that nested enums have correct abstract flag in the InnerClasses attribute.
- *  @library /tools/lib
- *  @modules jdk.compiler/com.sun.tools.javac.api
- *           jdk.compiler/com.sun.tools.javac.file
- *           jdk.compiler/com.sun.tools.javac.main
- *           jdk.compiler/com.sun.tools.javac.util
- *  @build ToolBox T8068517
- *  @run main T8068517
+/* @test
+ * @bug 8034854
+ * @summary Verify that nested enums have correct abstract flag in the InnerClasses attribute.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox T8068517
+ * @run main T8068517
  */
 
 import com.sun.tools.javac.util.Assert;
diff --git a/langtools/test/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java b/langtools/test/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java
index a06fa40..c3b5f4c 100644
--- a/langtools/test/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build AnnotationDefaultTest TestBase TestResult InMemoryFileManager ToolBox AnnotationDefaultVerifier
  * @run main AnnotationDefaultTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java b/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java
index 84a465c..04df246 100644
--- a/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build EnclosingMethodTest TestBase TestResult InMemoryFileManager ToolBox
  * @run main EnclosingMethodTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTest.java b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTest.java
index 9fbd7af..eb871a7 100644
--- a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox TestBase InMemoryFileManager LineNumberTestBase Container TestCase
  * @run main LineNumberTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java
index bc42ace..7023b03 100644
--- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager
  * @compile -g LocalVariableTableTest.java
  * @run main LocalVariableTableTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java
index f43c3f3..8753f68 100644
--- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager
  * @compile -g LocalVariableTypeTableTest.java
  * @run main LocalVariableTypeTableTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleFlagTest.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleFlagTest.java
new file mode 100644
index 0000000..e77fe97
--- /dev/null
+++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleFlagTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080878
+ * @summary Checking ACC_MODULE flag is generated for module-info.
+ * @library /tools/lib
+ * @modules 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
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox
+ * @run main ModuleFlagTest
+ */
+
+import com.sun.tools.classfile.AccessFlags;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ModuleFlagTest {
+    public static void main(String[] args) throws IOException, ConstantPoolException {
+        Path outdir = Paths.get(".");
+        ToolBox tb = new ToolBox();
+        final Path moduleInfo = Paths.get("module-info.java");
+        tb.writeFile(moduleInfo, "module test_module{}");
+        tb.new JavacTask()
+                .outdir(outdir)
+                .files(moduleInfo)
+                .run();
+
+        AccessFlags accessFlags = ClassFile.read(outdir.resolve("module-info.class"))
+                .access_flags;
+        if (!accessFlags.is(AccessFlags.ACC_MODULE)) {
+            throw new RuntimeException("Classfile doesn't have module access flag");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java
new file mode 100644
index 0000000..c28ffc7
--- /dev/null
+++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Module attribute tests
+ * @bug 8080878
+ * @modules 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
+ *          jdk.jdeps/com.sun.tools.javap
+ * @library /tools/lib ../lib /tools/javac/lib
+ * @build ToolBox TestBase TestResult ModuleTestBase
+ * @run main ModuleTest
+ */
+
+import java.nio.file.Path;
+
+public class ModuleTest extends ModuleTestBase {
+
+    public static void main(String[] args) throws Exception {
+        new ModuleTest().run();
+    }
+
+    @Test
+    public void testEmptyModule(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testExports(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .exports("pack")
+                .write(base);
+        tb.writeJavaFiles(base, "package pack; public class C extends java.util.ArrayList{}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testSeveralExports(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .exports("pack")
+                .exports("pack2")
+                .exports("pack3")
+                .write(base);
+        tb.writeJavaFiles(base,
+                "package pack; public class A {}",
+                "package pack2; public class B {}",
+                "package pack3; public class C {}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testQualifiedExports(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);
+    }
+
+    @Test
+    public void testSeveralQualifiedExports(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .exportsTo("pack", "jdk.compiler, java.xml")
+                .exportsTo("pack2", "java.xml")
+                .exportsTo("pack3", "jdk.compiler")
+                .write(base);
+        tb.writeJavaFiles(base,
+                "package pack; public class A {}",
+                "package pack2; public class B {}",
+                "package pack3; public class C {}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testRequires(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .requires("jdk.compiler")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testRequiresPublic(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .requiresPublic("java.xml")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testSeveralRequires(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .requiresPublic("java.xml")
+                .requires("java.compiler")
+                .requires("jdk.compiler")
+                .requiresPublic("jdk.scripting.nashorn")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testProvides(Path base) throws Exception {
+        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{}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testSeveralProvides(Path base) throws Exception {
+        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")
+                .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);" +
+                        "}}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testUses(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .uses("java.util.List")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testSeveralUses(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .uses("java.util.List")
+                .uses("java.util.Collection")
+                .requires("java.logging")
+                .uses("java.util.logging.Logger")
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testComplex(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .exports("pack1")
+                .exportsTo("packTo1", "java.xml")
+                .requires("jdk.compiler")
+                .requiresPublic("java.xml")
+                .provides("java.util.List", "pack1.C")
+                .uses("java.util.List")
+                .uses("java.nio.file.Path")
+                .provides("java.util.List", "pack2.D")
+                .requiresPublic("java.desktop")
+                .requires("java.compiler")
+                .exportsTo("packTo2", "java.compiler")
+                .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,
+                "package packTo1; public class T1 {}",
+                "package packTo2; public class T2 {}");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+}
diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java
new file mode 100644
index 0000000..4722922
--- /dev/null
+++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java
@@ -0,0 +1,223 @@
+/*
+ * 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 com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Module_attribute;
+import com.sun.tools.javac.util.Pair;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+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.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class ModuleTestBase {
+    protected final ToolBox tb = new ToolBox();
+    private final TestResult tr = new TestResult();
+
+
+    protected void run() throws Exception {
+        boolean noTests = true;
+        for (Method method : this.getClass().getMethods()) {
+            if (method.isAnnotationPresent(Test.class)) {
+                noTests = false;
+                try {
+                    tr.addTestCase(method.getName());
+                    method.invoke(this, Paths.get(method.getName()));
+                } catch (Throwable th) {
+                    tr.addFailure(th);
+                }
+            }
+        }
+        if (noTests) throw new AssertionError("Tests are not found.");
+        tr.checkStatus();
+    }
+
+    protected void testModuleAttribute(Path modulePath, ModuleDescriptor moduleDescriptor) throws Exception {
+        ClassFile classFile = ClassFile.read(modulePath.resolve("module-info.class"));
+        Module_attribute moduleAttribute = (Module_attribute) classFile.getAttribute("Module");
+        ConstantPool constantPool = classFile.constant_pool;
+
+        testRequires(moduleDescriptor, moduleAttribute, constantPool);
+        testExports(moduleDescriptor, moduleAttribute, constantPool);
+        testProvides(moduleDescriptor, moduleAttribute, constantPool);
+        testUses(moduleDescriptor, moduleAttribute, constantPool);
+    }
+
+    private void testRequires(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException {
+        tr.checkEquals(module.requires_count, moduleDescriptor.requires.size(), "Wrong amount of requires.");
+
+        List<Pair<String, Integer>> actualRequires = new ArrayList<>();
+        for (Module_attribute.RequiresEntry require : module.requires) {
+            actualRequires.add(Pair.of(
+                    require.getRequires(constantPool), require.requires_flags));
+        }
+        tr.checkContains(actualRequires, moduleDescriptor.requires, "Lists of requires don't match");
+    }
+
+    private void testExports(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry {
+        tr.checkEquals(module.exports_count, moduleDescriptor.exports.size(), "Wrong amount of exports.");
+        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);
+                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));
+                }
+                tr.checkContains(actualTo, expectedTo, "Lists of \"exports to\" don't match.");
+            }
+        }
+    }
+
+    private void testUses(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException {
+        tr.checkEquals(module.uses_count, moduleDescriptor.uses.size(), "Wrong amount of uses.");
+        List<String> actualUses = new ArrayList<>();
+        for (int usesIdx : module.uses_index) {
+            String uses = constantPool.getClassInfo(usesIdx).getBaseName().replace('/', '.');
+            actualUses.add(uses);
+        }
+        tr.checkContains(actualUses, moduleDescriptor.uses, "Lists of uses don't match");
+    }
+
+    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<>();
+        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));
+        }
+        tr.checkContains(actualProvides, moduleDescriptor.provides, "Lists of provides don't match");
+    }
+
+    protected void compile(Path base) throws IOException {
+        tb.new JavacTask()
+                .files(findJavaFiles(base))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    private static Path[] findJavaFiles(Path src) throws IOException {
+        return Files.find(src, Integer.MAX_VALUE, (path, attr) -> path.toString().endsWith(".java"))
+                .toArray(Path[]::new);
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Test {
+    }
+
+    class ModuleDescriptor {
+
+        private final String name;
+        //pair is name of module and flag(public,mandated,synthetic)
+        private final List<Pair<String, Integer>> requires = new ArrayList<>();
+
+        {
+            requires.add(new Pair<>("java.base", Module_attribute.ACC_MANDATED));
+        }
+
+        private final Map<String, List<String>> exports = new HashMap<>();
+
+        //List of service and implementation
+        private final List<Pair<String, String>> provides = new ArrayList<>();
+        private final List<String> uses = new ArrayList<>();
+
+        private static final String LINE_END = ";\n";
+
+        StringBuilder content = new StringBuilder("module ");
+
+        public ModuleDescriptor(String moduleName) {
+            this.name = moduleName;
+            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);
+            }
+            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);
+            }
+            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);
+            }
+            return this;
+        }
+
+        public ModuleDescriptor exportsTo(String exports, String to) {
+            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);
+            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);
+            return this;
+        }
+
+        public ModuleDescriptor uses(String... uses) {
+            Collections.addAll(this.uses, uses);
+            for (String use : uses) {
+                content.append("    uses ").append(use).append(LINE_END);
+            }
+            return this;
+        }
+
+        public ModuleDescriptor write(Path path) throws IOException {
+            String src = content.append('}').toString();
+
+            tb.createDirectories(path);
+            tb.writeJavaFiles(path, src);
+            return this;
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java
index ce1ab91..94aab12 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ConstructorTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build ConstructorTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver ConstructorTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.java
index 81d9c0f..7993c97 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/EnumTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build EnumTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver EnumTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.java
index c434e09..9a3fbf0 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ExceptionTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build ExceptionTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver ExceptionTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java
index 2098015..8d35f76 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/FieldTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build FieldTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver FieldTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java
index 49a9362..85630990 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/InnerClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build InnerClassTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver InnerClassTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java
index 10f4cd4..00f9bf9 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodParameterTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build MethodParameterTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver MethodParameterTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.java
index 557ce68..73d79c3 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/MethodTypeBoundTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build MethodTypeBoundTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver MethodTypeBoundTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java b/langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java
index b60244d..ab156b5 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Signature/ReturnTypeTest.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build ReturnTypeTest Driver ExpectedSignature ExpectedSignatureContainer
  * @run main Driver ReturnTypeTest
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java
index d426e22..aa86594 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main AnonymousClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java
index 52a6e5d..251da93 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main InnerClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java
index 7f58d38..be20d48 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main LocalClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java
index 109b528..c46ca5f 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main MixTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/ModuleInfoTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/ModuleInfoTest.java
new file mode 100644
index 0000000..45610fc
--- /dev/null
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/ModuleInfoTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary sourcefile attribute test for module-info.
+ * @bug 8080878
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
+ * @run main ModuleInfoTest
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ModuleInfoTest extends SourceFileTestBase {
+    public static void main(String[] args) throws Exception {
+        Path outdir = Paths.get(".");
+        ToolBox tb = new ToolBox();
+        final Path moduleInfo = Paths.get("module-info.java");
+        tb.writeFile(moduleInfo, "module m1{}");
+        tb.new JavacTask()
+                .files(moduleInfo)
+                .outdir(outdir)
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        new ModuleInfoTest().test(outdir.resolve("module-info.class"), "module-info.java");
+    }
+}
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java
index 8cd1ea9..3a2b389 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @compile -g:none NoSourceFileAttribute.java
  * @run main NoSourceFileAttribute
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java
index 944a2d8..f6ff405 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,6 +25,7 @@
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.SourceFile_attribute;
 
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -60,6 +61,16 @@
     }
 
     /**
+     * Checks expected fileName for the specified class in the SourceFile attribute.
+     *
+     * @param classToTest path of class to check its SourceFile attribute
+     * @param fileName    expected name of the file from which the test file is compiled.
+     */
+    protected void test(Path classToTest, String fileName) throws Exception {
+        assertAttributePresent(ClassFile.read(classToTest), fileName);
+    }
+
+    /**
      * Compiles sourceCode and for each specified class name checks the SourceFile attribute.
      * The file name is extracted from source code.
      *
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java
index e23e928..8c278b7 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main SyntheticClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java b/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java
index ecc584e..1c092e2 100644
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager
  * @run main TopLevelClassesOneFileTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java
index 6087a44..52d9145 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build AccessToPrivateInnerClassMembersTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.java
index 2810ed0..6cdd788 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.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
@@ -29,6 +29,7 @@
  * @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
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build AccessToPrivateSiblingsTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AssertFieldTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AssertFieldTest.java
index beea5d0..0c7f921 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/AssertFieldTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/AssertFieldTest.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
@@ -29,6 +29,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build AssertFieldTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodForGenericMethodTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodForGenericMethodTest.java
index 5a1ce63..dabecee 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodForGenericMethodTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodForGenericMethodTest.java
@@ -29,6 +29,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build BridgeMethodForGenericMethodTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java
index 0b11b97..d78873f 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build BridgeMethodsForLambdaTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/EnumTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/EnumTest.java
index d5a3f26..d89090b 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/EnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/EnumTest.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
@@ -29,6 +29,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build EnumTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/PackageInfoTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/PackageInfoTest.java
index a7b09dc..45b8307 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/PackageInfoTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/PackageInfoTest.java
@@ -29,6 +29,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/Synthetic/ThisFieldTest.java b/langtools/test/tools/javac/classfiles/attributes/Synthetic/ThisFieldTest.java
index 16bfb6a..863c3d1 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Synthetic/ThisFieldTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Synthetic/ThisFieldTest.java
@@ -28,6 +28,7 @@
  * @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
  * @library /tools/lib /tools/javac/lib ../lib
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @build ThisFieldTest SyntheticTestDriver ExpectedClass ExpectedClasses
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java
index 67f7392..2ed305a 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java
index e264c7f..df26473 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java
index ebeb044..53e25dd 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java
index 83f37ba..8bed834 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java
index 63a4323..341ee29 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java
index bb06f38..fb1a603 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java
index 88f069a..b8224b8 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java
index 055cd42..356ec85f 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java
index 7398805..a297dc8 100644
--- a/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java
@@ -28,6 +28,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib /tools/javac/lib ../lib
  * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
  * @build TestCase ClassType TestAnnotationInfo
diff --git a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java
index 5d541c0..b688f3b 100644
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build  ToolBox TestBase TestResult InMemoryFileManager
  * @run main DeprecatedPackageTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java
index e3d6210..e71fc4c 100644
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox TestBase TestResult InMemoryFileManager
  * @run main DeprecatedTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java
index 7be9a5b..5a8d9ea 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerAnnotationsInInnerAnnotationTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java
index 70f33ab..798ea68 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerAnnotationsInInnerClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java
index 4bf1b24..78dbf32 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerAnnotationsInInnerEnumTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java
index 44f009d..6333fbd 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerAnnotationsInInnerInterfaceTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java
index 11f1e7d..f6958b9 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesHierarchyTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java
index 507b575..962c695 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInAnonymousClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java
index 59fca6e..2147572 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInInnerAnnotationTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java
index ed5e298..5e97e7d 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInInnerClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java
index 3007ce7..192f5a0 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInInnerEnumTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java
index cbbebc7..6a89bb5 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInInnerInterfaceTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java
index 7b394d9..f377644 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
  * @run main InnerClassesInLocalClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java
index e4da27d..c95266d 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerClassesIndexTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java
index edfada6..d0cb3dd 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerClassesTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java
index b1fa079..3359823 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerEnumInInnerAnnotationTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java
index c0acbc6..f64590c 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerEnumInInnerEnumTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java
index 98f4e60..aa9137f 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerEnumInInnerInterfaceTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java
index 7386bdb..38618c6 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerEnumsInInnerClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java
index 47cd504..0cd7211 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerInterfacesInInnerAnnotationTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java
index 0a1a3cc..3bfe8e5 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerInterfacesInInnerClassTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java
index 6dfb17d..c53223b 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerInterfacesInInnerEnumTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java
index d9c7d49..91025bd 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
  * @run main InnerInterfacesInInnerInterfaceTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java
index 78b08f8..1ea21f1 100644
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.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
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @build TestBase InMemoryFileManager ToolBox
  * @run main NoInnerClassesTest
  */
diff --git a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java
index 4779ab0..7160879 100644
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java
@@ -78,7 +78,7 @@
         return checkEquals(actual, true, message);
     }
 
-    public boolean checkContains(Set<?> found, Set<?> expected, String message) {
+    public boolean checkContains(Collection<?> found, Collection<?> expected, String message) {
         Set<?> copy = new HashSet<>(expected);
         copy.removeAll(found);
         if (!found.containsAll(expected)) {
diff --git a/langtools/test/tools/javac/code/ArrayClone.java b/langtools/test/tools/javac/code/ArrayClone.java
index 8a36a1d..1a229a9 100644
--- a/langtools/test/tools/javac/code/ArrayClone.java
+++ b/langtools/test/tools/javac/code/ArrayClone.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,6 +27,7 @@
  * @summary Clone() on arrays compiled incorrectly
  * @author gafter jjg
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javac/defaultMethods/AssertionsTest.java b/langtools/test/tools/javac/defaultMethods/AssertionsTest.java
index 2761ba0..ef7b8f4 100644
--- a/langtools/test/tools/javac/defaultMethods/AssertionsTest.java
+++ b/langtools/test/tools/javac/defaultMethods/AssertionsTest.java
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox Assertions AssertionsTest
  * @run main AssertionsTest -da
  * @run main AssertionsTest -ea:test.Assertions Inner
diff --git a/langtools/test/tools/javac/defaultMethods/BadClassfile.java b/langtools/test/tools/javac/defaultMethods/BadClassfile.java
index 663f21f..0f5e9df 100644
--- a/langtools/test/tools/javac/defaultMethods/BadClassfile.java
+++ b/langtools/test/tools/javac/defaultMethods/BadClassfile.java
@@ -29,6 +29,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
  *          jdk.compiler/com.sun.tools.javac.jvm
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
@@ -40,9 +41,12 @@
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.ClassFinder.BadClassFile;
 import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.jvm.Target;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.List;
 import java.io.File;
 import java.util.Arrays;
 import java.util.Objects;
@@ -68,9 +72,13 @@
 
         JavaCompiler c = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl) c.getTask(null, null, null, Arrays.asList("-classpath", System.getProperty("test.classes", ".")), null, null);
+        Symtab syms = Symtab.instance(task.getContext());
+
+        //initialize unnamed module:
+        Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
 
         try {
-            Symbol clazz = com.sun.tools.javac.main.JavaCompiler.instance(task.getContext()).resolveIdent(classname);
+            Symbol clazz = com.sun.tools.javac.main.JavaCompiler.instance(task.getContext()).resolveIdent(syms.unnamedModule, classname);
 
             clazz.complete();
         } catch (BadClassFile f) {
diff --git a/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java
index 1dd810d..fd1f7e6 100644
--- a/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java
+++ b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main DefaultMethodsNotVisibleForSourceLessThan8Test
  */
diff --git a/langtools/test/tools/javac/diags/CheckExamples.java b/langtools/test/tools/javac/diags/CheckExamples.java
index d45675a..3ecf594 100644
--- a/langtools/test/tools/javac/diags/CheckExamples.java
+++ b/langtools/test/tools/javac/diags/CheckExamples.java
@@ -38,6 +38,8 @@
  */
 
 import java.io.*;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.nio.file.*;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.*;
@@ -108,8 +110,9 @@
             }
         }
 
+        Module jdk_compiler = Layer.boot().findModule("jdk.compiler").get();
         ResourceBundle b =
-            ResourceBundle.getBundle("com.sun.tools.javac.resources.compiler");
+            ResourceBundle.getBundle("com.sun.tools.javac.resources.compiler", jdk_compiler);
         Set<String> resourceKeys = new TreeSet<String>(b.keySet());
 
         for (String dk: declaredKeys) {
diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java
index 9c1c038..18951f8 100644
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java
@@ -30,6 +30,8 @@
  */
 
 import java.io.*;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.*;
 import javax.tools.*;
 import com.sun.tools.classfile.*;
@@ -267,6 +269,9 @@
     }
     // where
     private Set<String> noResourceRequired = new HashSet<String>(Arrays.asList(
+            // module names
+            "jdk.compiler",
+            "jdk.javadoc",
             // system properties
             "application.home", // in Paths.java
             "env.class.path",
@@ -277,7 +282,8 @@
             "ct.sym",
             "rt.jar",
             "jfxrt.jar",
-            "bootmodules.jimage",
+            "module-info.class",
+            "jrt-fs.jar",
             // -XD option names
             "process.packages",
             "ignore.symbol.file",
@@ -289,7 +295,8 @@
             "count.",
             "illegal.",
             "javac.",
-            "verbose."
+            "verbose.",
+            "locn."
     ));
 
     /**
@@ -375,10 +382,11 @@
      * Get the set of keys from the javac resource bundles.
      */
     Set<String> getResourceKeys() {
+        Module jdk_compiler = Layer.boot().findModule("jdk.compiler").get();
         Set<String> results = new TreeSet<String>();
         for (String name : new String[]{"javac", "compiler"}) {
             ResourceBundle b =
-                    ResourceBundle.getBundle("com.sun.tools.javac.resources." + name);
+                    ResourceBundle.getBundle("com.sun.tools.javac.resources." + name, jdk_compiler);
             results.addAll(b.keySet());
         }
         return results;
diff --git a/langtools/test/tools/javac/diags/DocCommentProcessor.java b/langtools/test/tools/javac/diags/DocCommentProcessor.java
index bb41985..c42e886 100644
--- a/langtools/test/tools/javac/diags/DocCommentProcessor.java
+++ b/langtools/test/tools/javac/diags/DocCommentProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -37,7 +37,6 @@
 import com.sun.source.util.TreePath;
 import com.sun.source.util.TreePathScanner;
 import com.sun.source.util.TreeScanner;
-import com.sun.tools.javac.tree.DocPretty;
 import java.io.PrintWriter;
 import javax.tools.Diagnostic;
 
diff --git a/langtools/test/tools/javac/diags/Example.java b/langtools/test/tools/javac/diags/Example.java
index f4522cd..e7e2556 100644
--- a/langtools/test/tools/javac/diags/Example.java
+++ b/langtools/test/tools/javac/diags/Example.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, 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
@@ -205,7 +205,16 @@
             opts.addAll(options);
 
         if (procFiles.size() > 0) {
-            List<String> pOpts = Arrays.asList("-d", classesDir.getPath());
+            List<String> pOpts = new ArrayList<>(Arrays.asList("-d", classesDir.getPath()));
+
+            // hack to automatically add exports; a better solution would be to grep the
+            // source for import statements or a magic comment
+            for (File pf: procFiles) {
+                if (pf.getName().equals("CreateBadClassFile.java")) {
+                    pOpts.add("-XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED");
+                }
+            }
+
             new Jsr199Compiler(verbose).run(null, null, false, pOpts, procFiles);
             opts.add("-classpath"); // avoid using -processorpath for now
             opts.add(classesDir.getPath());
@@ -331,7 +340,7 @@
                 else if (first.equals("backdoor"))
                     return new BackdoorCompiler(verbose);
                 else if (first.equals("exec"))
-                    return new ExecCompiler(verbose);
+                    return new ExecCompiler(verbose, rest);
                 else
                     throw new IllegalArgumentException(first);
             }
@@ -515,8 +524,11 @@
      * Run the test in a separate process.
      */
     static class ExecCompiler extends Compiler {
-        ExecCompiler(boolean verbose) {
+        List<String> vmOpts;
+
+        ExecCompiler(boolean verbose, String... args) {
             super(verbose);
+            vmOpts = Arrays.asList(args);
         }
 
         @Override
@@ -525,7 +537,7 @@
                 throw new IllegalArgumentException();
 
             if (verbose)
-                System.err.println("run_exec: " + opts + " " + files);
+                System.err.println("run_exec: " + vmOpts + " " + opts + " " + files);
 
             List<String> args = new ArrayList<String>();
 
@@ -541,6 +553,7 @@
                 args.add(toolsJar.getPath());
             }
 
+            args.addAll(vmOpts);
             addOpts(args, "test.vm.opts");
             addOpts(args, "test.java.opts");
             args.add(com.sun.tools.javac.Main.class.getName());
diff --git a/langtools/test/tools/javac/diags/FileManager.java b/langtools/test/tools/javac/diags/FileManager.java
index 2019eef..e4fec27 100644
--- a/langtools/test/tools/javac/diags/FileManager.java
+++ b/langtools/test/tools/javac/diags/FileManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -31,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.regex.Pattern;
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
@@ -67,7 +68,7 @@
 
     @Override
     protected JavaFileObject wrap(JavaFileObject fo) {
-        return new WrappedFileObject(fo);
+        return (fo == null) ? null : new WrappedFileObject(fo);
     }
 
     @Override
@@ -116,7 +117,7 @@
 
     class WrappedFileObject implements JavaFileObject {
         WrappedFileObject(JavaFileObject fileObject) {
-            delegate = fileObject;
+            delegate = Objects.requireNonNull(fileObject);
         }
 
         public Kind getKind() {
diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt
index 806d471..b90c1e6 100644
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt
@@ -109,3 +109,67 @@
 compiler.err.cant.inherit.from.anon                     # error for subclass of anonymous class
 compiler.misc.bad.class.file                            # class file is malformed
 compiler.misc.bad.const.pool.entry                      # constant pool entry has wrong type
+
+# The following are new module-related messages, that need new examples to be created
+compiler.err.addmods.all.module.path.invalid
+compiler.err.cant.find.module
+compiler.err.cyclic.requires
+compiler.err.duplicate.exports
+compiler.err.duplicate.module
+compiler.err.duplicate.module.on.path
+compiler.err.duplicate.provides
+compiler.err.duplicate.requires
+compiler.err.duplicate.uses
+compiler.err.expected.module
+compiler.err.illegal.argument.for.option
+compiler.err.invalid.module.specifier
+compiler.err.locn.bad.module-info
+compiler.err.locn.cant.get.module.name.for.jar
+compiler.err.locn.cant.read.directory
+compiler.err.locn.cant.read.file
+compiler.err.locn.invalid.arg.for.xpatch
+compiler.err.locn.module-info.not.allowed.on.patch.path
+compiler.err.module-info.with.xmodule.classpath
+compiler.err.module-info.with.xmodule.sourcepath
+compiler.err.module.decl.sb.in.module-info.java
+compiler.err.module.name.mismatch
+compiler.err.module.not.found
+compiler.err.module.not.found.in.module.source.path
+compiler.err.modules.not.supported.in.source
+compiler.err.modulesourcepath.must.be.specified.with.dash.m.option
+compiler.err.multi-module.outdir.cannot.be.exploded.module
+compiler.err.no.output.dir
+compiler.err.not.def.access.package.cant.access
+compiler.err.output.dir.must.be.specified.with.dash.m.option
+compiler.err.package.clash.from.requires
+compiler.err.package.empty.or.not.found
+compiler.err.package.in.other.module
+compiler.err.processorpath.no.processormodulepath
+compiler.err.service.definition.is.inner
+compiler.err.service.implementation.doesnt.have.a.no.args.constructor
+compiler.err.service.implementation.is.abstract
+compiler.err.service.implementation.is.inner
+compiler.err.service.implementation.no.args.constructor.not.public
+compiler.err.service.implementation.not.in.right.module
+compiler.err.too.many.modules
+compiler.err.unexpected.after.module
+compiler.err.unnamed.pkg.not.allowed.named.modules
+compiler.err.xaddexports.malformed.entry
+compiler.err.xaddexports.too.many
+compiler.err.xaddreads.malformed.entry
+compiler.err.xaddreads.too.many
+compiler.err.xmodule.no.module.sourcepath
+compiler.misc.bad.module-info.name
+compiler.misc.cant.resolve.modules
+compiler.misc.file.does.not.contain.module
+compiler.misc.kindname.module
+compiler.misc.locn.module_path
+compiler.misc.locn.module_source_path
+compiler.misc.locn.system_modules
+compiler.misc.locn.upgrade_module_path
+compiler.misc.unnamed.module
+compiler.warn.dir.path.element.not.directory
+compiler.warn.locn.unknown.file.on.module.path
+compiler.warn.outdir.is.in.exploded.module
+compiler.warn.service.provided.but.not.exported.or.used
+
diff --git a/langtools/test/tools/javac/diags/examples/DirPathElementNotFound.java b/langtools/test/tools/javac/diags/examples/DirPathElementNotFound.java
index dc25d01..4c8a385 100644
--- a/langtools/test/tools/javac/diags/examples/DirPathElementNotFound.java
+++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotFound.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -22,7 +22,8 @@
  */
 
 // key: compiler.warn.dir.path.element.not.found
-// options: -Xlint:path -extdirs DoesNotExist
+// key: compiler.warn.source.no.bootclasspath
+// options: -Xlint:path -source 8 -target 8 -extdirs DoesNotExist
 // run: simple
 
 class DirPathElementNotFound { }
diff --git a/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/InvalidDefaultInterface.java b/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/InvalidDefaultInterface.java
index a8b1d44..e433305 100644
--- a/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/InvalidDefaultInterface.java
+++ b/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/InvalidDefaultInterface.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
 // key: compiler.misc.bad.class.file.header
 // key: compiler.err.cant.access
 // options: -processor CreateBadClassFile
+// run: exec -XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
 
 /* The annotation processor will create an invalid classfile with version 51.0
  * and a non-abstract method in an interface. Loading the classfile will produce
diff --git a/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/processors/CreateBadClassFile.java b/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/processors/CreateBadClassFile.java
index 1f37bfa..202f6fe 100644
--- a/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/processors/CreateBadClassFile.java
+++ b/langtools/test/tools/javac/diags/examples/InvalidDefaultInterface/processors/CreateBadClassFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -21,10 +21,6 @@
  * questions.
  */
 
-import com.sun.tools.classfile.*;
-import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
-import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
-import com.sun.tools.classfile.ConstantPool.CPInfo;
 import java.io.*;
 import java.util.*;
 import javax.annotation.processing.*;
@@ -32,6 +28,11 @@
 import javax.lang.model.element.*;
 import javax.tools.*;
 
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+
 /* Create an invalid classfile with version 51.0 and a non-abstract method in an interface.*/
 @SupportedAnnotationTypes("*")
 public class CreateBadClassFile extends AbstractProcessor {
diff --git a/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/InvalidStaticInterface.java b/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/InvalidStaticInterface.java
index 3d5ff00..751409a 100644
--- a/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/InvalidStaticInterface.java
+++ b/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/InvalidStaticInterface.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
 // key: compiler.misc.bad.class.file.header
 // key: compiler.err.cant.access
 // options: -processor CreateBadClassFile
+// run: exec -XaddExports:jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
 
 /* The annotation processor will create an invalid classfile with version 51.0
  * and a static method in an interface. Loading the classfile will produce
diff --git a/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/processors/CreateBadClassFile.java b/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/processors/CreateBadClassFile.java
index acd362c..3d96756 100644
--- a/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/processors/CreateBadClassFile.java
+++ b/langtools/test/tools/javac/diags/examples/InvalidStaticInterface/processors/CreateBadClassFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -21,10 +21,6 @@
  * questions.
  */
 
-import com.sun.tools.classfile.*;
-import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
-import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
-import com.sun.tools.classfile.ConstantPool.CPInfo;
 import java.io.*;
 import java.util.*;
 import javax.annotation.processing.*;
@@ -32,6 +28,11 @@
 import javax.lang.model.element.*;
 import javax.tools.*;
 
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+
 /* Create an invalid classfile with version 51.0 and a static method in an interface.*/
 @SupportedAnnotationTypes("*")
 public class CreateBadClassFile extends AbstractProcessor {
diff --git a/langtools/test/tools/javac/diags/examples/NoJavaLang.java b/langtools/test/tools/javac/diags/examples/NoJavaLang.java
index e0fe497..5025874 100644
--- a/langtools/test/tools/javac/diags/examples/NoJavaLang.java
+++ b/langtools/test/tools/javac/diags/examples/NoJavaLang.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -22,7 +22,7 @@
  */
 
 // key: compiler.misc.fatal.err.no.java.lang
-// options: -Xbootclasspath:
+// options: -source 8 -target 8 -Xbootclasspath:
 // run: backdoor
 
 class NoJavaLang { }
diff --git a/langtools/test/tools/javac/diags/examples/NoSuperclass.java b/langtools/test/tools/javac/diags/examples/NoSuperclass.java
index ad6f3de..9e86e18 100644
--- a/langtools/test/tools/javac/diags/examples/NoSuperclass.java
+++ b/langtools/test/tools/javac/diags/examples/NoSuperclass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -22,6 +22,7 @@
  */
 
 // key: compiler.err.no.superclass
+// options: -Xmodule:java.base
 
 package java.lang;
 
diff --git a/langtools/test/tools/javac/doctree/ReferenceTest.java b/langtools/test/tools/javac/doctree/ReferenceTest.java
index 7261e60..128d3e1 100644
--- a/langtools/test/tools/javac/doctree/ReferenceTest.java
+++ b/langtools/test/tools/javac/doctree/ReferenceTest.java
@@ -57,6 +57,7 @@
 /**
  * {@link java.lang        Package}
  * {@link java.lang.ERROR  Bad}
+ * {@link java.lang#ERROR  Bad}
  *
  * {@link java.lang.String Class}
  * {@link           String Class}
@@ -81,6 +82,7 @@
  *
  * @see java.lang        Package
  * @see java.lang.ERROR  Bad
+ * @see java.lang#ERROR  Bad
  *
  * @see java.lang.String Class
  * @see           String Class
diff --git a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java
index c879f7e..ebb9ceb 100644
--- a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java
+++ b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.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
@@ -29,11 +29,13 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main NoJavaLangTest
  */
 
-// Original test: test/tools/javac/fatalErrors/NoJavaLang.sh
+import java.nio.file.*;
+
 public class NoJavaLangTest {
 
     private static final String noJavaLangSrc =
@@ -49,22 +51,60 @@
         "Fatal Error: Unable to find package java.lang in classpath or bootclasspath";
 
     public static void main(String[] args) throws Exception {
-        ToolBox tb = new ToolBox();
+        new NoJavaLangTest().run();
+    }
 
+    final ToolBox tb = new ToolBox();
+
+    void run() throws Exception {
+        testStandard();
+        testBootClassPath();
+        testModulePath();
+    }
+
+    // sanity check, with java.lang available
+    void testStandard() {
         tb.new JavacTask()
                 .sources(noJavaLangSrc)
                 .run();
+    }
+
+
+    // test with bootclasspath, for as long as its around
+    void testBootClassPath() {
+        String[] bcpOpts = { "-Xlint:-options", "-source", "8", "-bootclasspath", "." };
+        test(bcpOpts, compilerErrorMessage);
+    }
+
+    // test with module path
+    void testModulePath() throws Exception {
+        // need to ensure there is an empty java.base to avoid different error message
+        Files.createDirectories(Paths.get("modules/java.base"));
+        tb.new JavacTask()
+                .sources("module java.base { }")
+                .outdir("modules/java.base")
+                .run();
+
+        // ideally we'd have a better message for this case
+        String[] mpOpts = { "-system", "none", "-modulepath", "modules" };
+        test(mpOpts, compilerErrorMessage);
+    }
+
+    private void test(String[] options, String expect) {
+        System.err.println("Testing " + java.util.Arrays.toString(options));
 
         String out = tb.new JavacTask()
-                .options("-bootclasspath", ".")
+                .options(options)
                 .sources(noJavaLangSrc)
                 .run(ToolBox.Expect.FAIL, 3)
                 .writeAll()
                 .getOutput(ToolBox.OutputKind.DIRECT);
 
-        if (!out.trim().equals(compilerErrorMessage)) {
+        if (!out.trim().equals(expect)) {
             throw new AssertionError("javac generated error output is not correct");
         }
+
+        System.err.println("OK");
     }
 
 }
diff --git a/langtools/test/tools/javac/file/ExplodedImage.java b/langtools/test/tools/javac/file/ExplodedImage.java
index 2f89c63..b859ab8 100644
--- a/langtools/test/tools/javac/file/ExplodedImage.java
+++ b/langtools/test/tools/javac/file/ExplodedImage.java
@@ -53,21 +53,25 @@
  *          jdk.compiler/com.sun.tools.javac.code
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox ExplodedImage
- * @run main ExplodedImage
+ * @run main/othervm ExplodedImage modules/* testDirectoryStreamClosed
+ * @run main/othervm ExplodedImage modules/* testCanCompileAgainstExplodedImage
  */
 
 public class ExplodedImage {
     public static void main(String... args) throws IOException {
-        new ExplodedImage().run();
+        new ExplodedImage().run(args);
     }
 
-    void run() throws IOException {
-        for (String moduleLocations : new String[] {"modules/*"}) {
-            System.setProperty("java.home", originalJavaHome);
-            testDirectoryStreamClosed(moduleLocations);
-            System.setProperty("java.home", originalJavaHome);
-            testCanCompileAgainstExplodedImage(moduleLocations);
+    void run(String... args) throws IOException {
+        switch (args[0]) {
+            case "testDirectoryStreamClosed":
+                testDirectoryStreamClosed(args[1]);
+                break;
+            case "testCanCompileAgainstExplodedImage":
+                testCanCompileAgainstExplodedImage(args[1]);
+                break;
         }
     }
 
diff --git a/langtools/test/tools/javac/file/T7018098.java b/langtools/test/tools/javac/file/T7018098.java
index 1ab3a21..3283fa6 100644
--- a/langtools/test/tools/javac/file/T7018098.java
+++ b/langtools/test/tools/javac/file/T7018098.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
@@ -21,7 +21,7 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 7018098
  * @summary CacheFSInfo persists too long
@@ -60,6 +60,11 @@
         _assert(!testDir.exists());
 
         compile(
+            "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+            "-XDaccessInternalAPI",
             "-proc:only",
             "-processor", myName,
             "-Aexpect=false",
@@ -69,6 +74,11 @@
         _assert(testDir.exists());
 
         compile(
+            "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+            "-XDaccessInternalAPI",
             "-proc:only",
             "-processor", myName,
             "-Aexpect=true",
diff --git a/langtools/test/tools/javac/generics/diamond/neg/T8078473_2.java b/langtools/test/tools/javac/generics/diamond/neg/T8078473_2.java
index ceedc6f..6a8b99c 100644
--- a/langtools/test/tools/javac/generics/diamond/neg/T8078473_2.java
+++ b/langtools/test/tools/javac/generics/diamond/neg/T8078473_2.java
@@ -29,7 +29,7 @@
  * @compile -Werror T8078473_2.java -XDrawDiagnostics -XDfind=diamond
  */
 
-package java.util.stream;
+package p.q.r;
 
 class T8078473_2<P, Q> {
 
diff --git a/langtools/test/tools/javac/importscope/CompletionFailureDuringImport.java b/langtools/test/tools/javac/importscope/CompletionFailureDuringImport.java
index 4206485..f3197d9 100644
--- a/langtools/test/tools/javac/importscope/CompletionFailureDuringImport.java
+++ b/langtools/test/tools/javac/importscope/CompletionFailureDuringImport.java
@@ -26,6 +26,10 @@
  * @bug 8131915
  * @summary Verify that CompletionFailure thrown during listing of import content is handled properly.
  * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.nio.file.Files;
diff --git a/langtools/test/tools/javac/importscope/ImportDependenciesTest.java b/langtools/test/tools/javac/importscope/ImportDependenciesTest.java
index c83e3c5..2005405 100644
--- a/langtools/test/tools/javac/importscope/ImportDependenciesTest.java
+++ b/langtools/test/tools/javac/importscope/ImportDependenciesTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox ImportDependenciesTest
  * @run main ImportDependenciesTest
  */
diff --git a/langtools/test/tools/javac/importscope/ImportMembersTest.java b/langtools/test/tools/javac/importscope/ImportMembersTest.java
index 371b1d0..5b0bff2 100644
--- a/langtools/test/tools/javac/importscope/ImportMembersTest.java
+++ b/langtools/test/tools/javac/importscope/ImportMembersTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox ImportMembersTest
  * @run main ImportMembersTest
  */
diff --git a/langtools/test/tools/javac/importscope/NegativeCyclicDependencyTest.java b/langtools/test/tools/javac/importscope/NegativeCyclicDependencyTest.java
index 7c7059f..631ada2 100644
--- a/langtools/test/tools/javac/importscope/NegativeCyclicDependencyTest.java
+++ b/langtools/test/tools/javac/importscope/NegativeCyclicDependencyTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox NegativeCyclicDependencyTest
  * @run main NegativeCyclicDependencyTest
  */
diff --git a/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java b/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java
index 7ae9056..cf19996 100644
--- a/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java
+++ b/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main InnerClassFileTest
  */
diff --git a/langtools/test/tools/javac/javazip/JavaZipTest.java b/langtools/test/tools/javac/javazip/JavaZipTest.java
index f4e1eec..3df3ba5 100644
--- a/langtools/test/tools/javac/javazip/JavaZipTest.java
+++ b/langtools/test/tools/javac/javazip/JavaZipTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main JavaZipTest
  */
diff --git a/langtools/test/tools/javac/lambda/AvoidInfiniteReattribution.java b/langtools/test/tools/javac/lambda/AvoidInfiniteReattribution.java
index ed17821..570a642 100644
--- a/langtools/test/tools/javac/lambda/AvoidInfiniteReattribution.java
+++ b/langtools/test/tools/javac/lambda/AvoidInfiniteReattribution.java
@@ -25,7 +25,11 @@
  * @test
  * @bug 8077605
  * @summary Check that when an exception occurs during Attr.visitLambda, an attempt to attribute
-            the lambda again is avoided rather than falling into an infinite recursion.
+ *          the lambda again is avoided rather than falling into an infinite recursion.
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.comp
+ *          jdk.compiler/com.sun.tools.javac.tree
+ *          jdk.compiler/com.sun.tools.javac.util
  */
 
 import java.io.IOException;
diff --git a/langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.java b/langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.java
index c37dd9c..a88b05b 100644
--- a/langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.java
+++ b/langtools/test/tools/javac/lambda/LambdaInnerTypeVarReflect.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
@@ -27,6 +27,7 @@
  * @summary A lambda containing an inner class referencing an external type var
  * @author  Robert Field
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  * @run main LambdaInnerTypeVarReflect
  */
 
diff --git a/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java b/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java
index eb6ee35..484e00a 100644
--- a/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java
+++ b/langtools/test/tools/javac/lambda/T8129740/SourceToSourceTranslationTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile -XD-printsource SourceForTranslation.java
  * @run main SourceToSourceTranslationTest
diff --git a/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java b/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java
index b707ec2..27501da 100644
--- a/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java
+++ b/langtools/test/tools/javac/lambda/TestBootstrapMethodsCount.java
@@ -29,6 +29,7 @@
  * @modules jdk.jdeps/com.sun.tools.classfile
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.jvm
  *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  */
diff --git a/langtools/test/tools/javac/lambda/bridge/TestMetafactoryBridges.java b/langtools/test/tools/javac/lambda/bridge/TestMetafactoryBridges.java
index a11254c..db611f4 100644
--- a/langtools/test/tools/javac/lambda/bridge/TestMetafactoryBridges.java
+++ b/langtools/test/tools/javac/lambda/bridge/TestMetafactoryBridges.java
@@ -31,7 +31,6 @@
 
 import com.sun.source.util.JavacTask;
 import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper;
-import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.util.JCDiagnostic;
 
 import java.io.File;
diff --git a/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties b/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties
index 9e96df0..70090af 100644
--- a/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties
+++ b/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties
@@ -1,7 +1,8 @@
 # This file identifies root(s) of the test-ng hierarchy.
 
-
-
 TestNG.dirs = .
 
 lib.dirs = /lib/combo
+
+modules = \
+        jdk.compiler/com.sun.tools.javac.util
diff --git a/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java b/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java
index c42b35f..e373a21 100644
--- a/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java
+++ b/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main TestNonSerializableLambdaNameStability
  */
diff --git a/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java b/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java
index b3cecce..db98919 100644
--- a/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java
+++ b/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main TestSerializedLambdaNameStability
  */
diff --git a/langtools/test/tools/javac/lambdaShapes/TEST.properties b/langtools/test/tools/javac/lambdaShapes/TEST.properties
index 51a8537..8a7db8d 100644
--- a/langtools/test/tools/javac/lambdaShapes/TEST.properties
+++ b/langtools/test/tools/javac/lambdaShapes/TEST.properties
@@ -1,2 +1,5 @@
 TestNG.dirs = tools/javac/lambdaShapes
 
+modules = \
+        jdk.compiler/com.sun.tools.javac.util
+
diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java
index c4304e4..982800c 100644
--- a/langtools/test/tools/javac/lib/DPrinter.java
+++ b/langtools/test/tools/javac/lib/DPrinter.java
@@ -1292,6 +1292,10 @@
             return visitType(type, null);
         }
 
+        public Void visitModuleType(ModuleType type, Void ignore) {
+            return visitType(type, null);
+        }
+
         public Void visitPackageType(PackageType type, Void ignore) {
             return visitType(type, null);
         }
diff --git a/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java b/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
index 1249fa9..f253356 100644
--- a/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
+++ b/langtools/test/tools/javac/lib/JavacTestingAbstractProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -21,6 +21,8 @@
  * questions.
  */
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.*;
 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
@@ -97,6 +99,20 @@
         options   = processingEnv.getOptions();
     }
 
+    protected void addExports(String moduleName, String... packageNames) {
+        for (String packageName : packageNames) {
+            try {
+                Layer layer = Layer.boot();
+                Optional<Module> m = layer.findModule(moduleName);
+                if (!m.isPresent())
+                    throw new Error("module not found: " + moduleName);
+                m.get().addExports(packageName, getClass().getModule());
+            } catch (Exception e) {
+                throw new Error("failed to add exports for " + moduleName + "/" + packageName);
+            }
+        }
+    }
+
     /*
      * The set of visitors below will directly extend the most recent
      * corresponding platform visitor type.
diff --git a/langtools/test/tools/javac/lib/combo/ReusableContext.java b/langtools/test/tools/javac/lib/combo/ReusableContext.java
index f679965..7cf4c75 100644
--- a/langtools/test/tools/javac/lib/combo/ReusableContext.java
+++ b/langtools/test/tools/javac/lib/combo/ReusableContext.java
@@ -112,7 +112,7 @@
         public Void visitClass(ClassTree node, Symtab syms) {
             Symbol sym = ((JCClassDecl)node).sym;
             if (sym != null) {
-                syms.classes.remove(sym.flatName());
+                syms.removeClass(sym.packge().modle, sym.flatName());
                 Type sup = supertype(sym);
                 if (isCoreClass(sym) ||
                         (sup != null && isCoreClass(sup.tsym) && sup.tsym.kind != Kinds.Kind.TYP)) {
diff --git a/langtools/test/tools/javac/limits/NumArgsTest.java b/langtools/test/tools/javac/limits/NumArgsTest.java
index 751df98..079f2a1 100644
--- a/langtools/test/tools/javac/limits/NumArgsTest.java
+++ b/langtools/test/tools/javac/limits/NumArgsTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,7 +21,6 @@
  * questions.
  */
 
-import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.api.*;
 import com.sun.tools.javac.file.*;
 import java.io.*;
diff --git a/langtools/test/tools/javac/links/LinksTest.java b/langtools/test/tools/javac/links/LinksTest.java
index 35fdccc..f2f215d 100644
--- a/langtools/test/tools/javac/links/LinksTest.java
+++ b/langtools/test/tools/javac/links/LinksTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main LinksTest
  */
diff --git a/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java
new file mode 100644
index 0000000..40a76d4
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 8145016
+ * @summary Javac doesn't report errors on service implementation which cannot be initialized
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AbstractOrInnerClassServiceImplTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class AbstractOrInnerClassServiceImplTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        AbstractOrInnerClassServiceImplTest t = new AbstractOrInnerClassServiceImplTest();
+        t.runTests();
+    }
+
+    @Test
+    void testAbstractServiceImpl(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.Service with p2.Impl; }",
+                "package p1; public interface Service { }",
+                "package p2; public interface Impl extends p1.Service { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:39: compiler.err.service.implementation.is.abstract: p2.Impl"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testInnerClassServiceImpl(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.Service with p2.Outer.Inner; }",
+                "package p1; public interface Service { }",
+                "package p2; public class Outer { public class Inner implements p1.Service {} }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:45: compiler.err.service.implementation.is.inner: p2.Outer.Inner"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testInnerInterfaceServiceImpl(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.Service with p2.Outer.Inner; }",
+                "package p1; public interface Service { }",
+                "package p2; public class Outer { public interface Inner extends p1.Service {} }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:45: compiler.err.service.implementation.is.abstract: p2.Outer.Inner"))
+            throw new Exception("expected output not found");
+    }
+}
diff --git a/langtools/test/tools/javac/modules/AddLimitMods.java b/langtools/test/tools/javac/modules/AddLimitMods.java
new file mode 100644
index 0000000..4c3e358
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AddLimitMods.java
@@ -0,0 +1,533 @@
+/*
+ * 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 Test -addmods and -limitmods; also test the "enabled" modules.
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.code
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.compiler/com.sun.tools.javac.model
+ *      jdk.compiler/com.sun.tools.javac.processing
+ *      jdk.compiler/com.sun.tools.javac.util
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AddLimitMods
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.TypeElement;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
+
+public class AddLimitMods extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        AddLimitMods t = new AddLimitMods();
+        t.runTests();
+    }
+
+    @Test
+    void testManual(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { requires m2; requires m3; }");
+
+        Path m2 = moduleSrc.resolve("m2");
+
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m3; exports m2; }",
+                          "package m2; public class M2 {}");
+
+        Path m3 = moduleSrc.resolve("m3");
+
+        tb.writeJavaFiles(m3,
+                          "module m3 { exports m3; }",
+                          "package m3; public class M3 {}");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(m3))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(m2))
+                .run()
+                .writeAll();
+
+        //real test
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "java.base")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "java.base",
+                         "-addmods", "m2")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "java.base",
+                         "-addmods", "m2,m3")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "m2")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "m3")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-XDshouldStopPolicyIfNoError=FLOW",
+                         "-limitmods", "m3",
+                         "-addmods", "m2")
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testAllModulePath(Path base) throws Exception {
+        if (Files.isDirectory(base))
+            tb.cleanDirectory(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports api; }",
+                          "package api; public class Api { }");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+
+        Path cpSrc = base.resolve("cp-src");
+        tb.writeJavaFiles(cpSrc, "package test; public class Test { api.Api api; }");
+
+        Path cpOut = base.resolve("cp-out");
+
+        Files.createDirectories(cpOut);
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString())
+                .outdir(cpOut)
+                .files(findJavaFiles(cpSrc))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-addmods", "ALL-MODULE-PATH")
+                .outdir(cpOut)
+                .files(findJavaFiles(cpSrc))
+                .run()
+                .writeAll();
+
+        List<String> actual;
+        List<String> expected = Arrays.asList(
+                "- compiler.err.addmods.all.module.path.invalid",
+                "1 error");
+
+        actual = tb.new JavacTask()
+                   .options("-modulesourcepath", moduleSrc.toString(),
+                            "-XDrawDiagnostics",
+                            "-addmods", "ALL-MODULE-PATH")
+                   .outdir(modulePath)
+                   .files(findJavaFiles(moduleSrc))
+                   .run(ToolBox.Expect.FAIL)
+                   .writeAll()
+                   .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        if (!Objects.equals(actual, expected)) {
+            throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected);
+        }
+
+        actual = tb.new JavacTask()
+                   .options("-Xmodule:java.base",
+                            "-XDrawDiagnostics",
+                            "-addmods", "ALL-MODULE-PATH")
+                   .outdir(cpOut)
+                   .files(findJavaFiles(cpSrc))
+                   .run(ToolBox.Expect.FAIL)
+                   .writeAll()
+                   .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        if (!Objects.equals(actual, expected)) {
+            throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected);
+        }
+
+        actual = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                   .options("-source", "8", "-target", "8",
+                            "-XDrawDiagnostics",
+                            "-addmods", "ALL-MODULE-PATH")
+                   .outdir(cpOut)
+                   .files(findJavaFiles(cpSrc))
+                   .run(ToolBox.Expect.FAIL)
+                   .writeAll()
+                   .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        if (!actual.contains("javac: option -addmods not allowed with target 1.8")) {
+            throw new IllegalStateException("incorrect errors; actual=" + actual);
+        }
+
+        tb.writeJavaFiles(cpSrc, "module m1 {}");
+
+        actual = tb.new JavacTask()
+                   .options("-XDrawDiagnostics",
+                            "-addmods", "ALL-MODULE-PATH")
+                   .outdir(cpOut)
+                   .files(findJavaFiles(cpSrc))
+                   .run(ToolBox.Expect.FAIL)
+                   .writeAll()
+                   .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        if (!Objects.equals(actual, expected)) {
+            throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected);
+        }
+    }
+
+    @Test
+    void testRuntime2Compile(Path base) throws Exception {
+        Path classpathSrc = base.resolve("classpath-src");
+        Path classpathOut = base.resolve("classpath-out");
+
+        tb.writeJavaFiles(classpathSrc,
+                          generateCheckAccessibleClass("cp.CP"));
+
+        Files.createDirectories(classpathOut);
+
+        tb.new JavacTask()
+                .outdir(classpathOut)
+                .files(findJavaFiles(classpathSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        Path automaticSrc = base.resolve("automatic-src");
+        Path automaticOut = base.resolve("automatic-out");
+
+        tb.writeJavaFiles(automaticSrc,
+                          generateCheckAccessibleClass("automatic.Automatic"));
+
+        Files.createDirectories(automaticOut);
+
+        tb.new JavacTask()
+                .outdir(automaticOut)
+                .files(findJavaFiles(automaticSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path automaticJar = modulePath.resolve("automatic.jar");
+
+        tb.new JarTask(automaticJar)
+          .baseDir(automaticOut)
+          .files("automatic/Automatic.class")
+          .run();
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports api; }",
+                          "package api; public class Api { public void test() { } }");
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        int index = 0;
+
+        for (String moduleInfo : MODULE_INFO_VARIANTS) {
+            for (String[] options : OPTIONS_VARIANTS) {
+                index++;
+
+                System.err.println("running check: " + moduleInfo + "; " + Arrays.asList(options));
+
+                Path m2Runtime = base.resolve(index + "-runtime").resolve("m2");
+                Path out = base.resolve(index + "-runtime").resolve("out").resolve("m2");
+
+                Files.createDirectories(out);
+
+                StringBuilder testClassNamed = new StringBuilder();
+
+                testClassNamed.append("package test;\n" +
+                                      "public class Test {\n" +
+                                      "    public static void main(String... args) throws Exception {\n");
+
+                for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
+                    testClassNamed.append("        System.err.println(\"visible:" + e.getKey() + ":\" + java.lang.reflect.Layer.boot().findModule(\"" + e.getKey() + "\").isPresent());\n");
+                }
+
+                testClassNamed.append("        Class<?> cp = Class.forName(Test.class.getClassLoader().getUnnamedModule(), \"cp.CP\");\n");
+                testClassNamed.append("        cp.getDeclaredMethod(\"runMe\").invoke(null);\n");
+
+                testClassNamed.append("        Class<?> automatic = Class.forName(java.lang.reflect.Layer.boot().findModule(\"automatic\").get(), \"automatic.Automatic\");\n");
+                testClassNamed.append("        automatic.getDeclaredMethod(\"runMe\").invoke(null);\n");
+
+                testClassNamed.append("    }\n" +
+                                      "}");
+
+                tb.writeJavaFiles(m2Runtime, moduleInfo, testClassNamed.toString());
+
+                tb.new JavacTask()
+                   .options("-modulepath", modulePath.toString())
+                   .outdir(out)
+                   .files(findJavaFiles(m2Runtime))
+                   .run()
+                   .writeAll();
+
+                boolean success;
+                String output;
+
+                try {
+                    output = tb.new JavaTask()
+                       .vmOptions(augmentOptions(options,
+                                                 Collections.emptyList(),
+                                                 "-modulepath", modulePath.toString() + File.pathSeparator + out.getParent().toString(),
+                                                 "-classpath", classpathOut.toString(),
+                                                 "-XaddReads:m2=ALL-UNNAMED,m2=automatic",
+                                                 "-m", "m2/test.Test"))
+                       .run()
+                       .writeAll()
+                       .getOutput(ToolBox.OutputKind.STDERR);
+
+                    success = true;
+                } catch (ToolBox.TaskError err) {
+                    success = false;
+                    output = "";
+                }
+
+                Path m2 = base.resolve(String.valueOf(index)).resolve("m2");
+
+                tb.writeJavaFiles(m2,
+                                  moduleInfo,
+                                  "package test;\n" +
+                                  "public class Test {}\n");
+
+                List<String> auxOptions = success ? Arrays.asList(
+                    "-processorpath", System.getProperty("test.class.path"),
+                    "-processor", CheckVisibleModule.class.getName(),
+                    "-Aoutput=" + output,
+                    "-XDaccessInternalAPI=true"
+                ) : Collections.emptyList();
+                tb.new JavacTask()
+                   .options(augmentOptions(options,
+                                           auxOptions,
+                                           "-modulepath", modulePath.toString(),
+                                           "-classpath", classpathOut.toString(),
+                                           "-XDshouldStopPolicyIfNoError=FLOW"))
+                   .outdir(modulePath)
+                   .files(findJavaFiles(m2))
+                   .run(success ? ToolBox.Expect.SUCCESS : ToolBox.Expect.FAIL)
+                   .writeAll();
+            }
+        }
+    }
+
+    private String generateCheckAccessibleClass(String fqn) {
+        String packageName = fqn.substring(0, fqn.lastIndexOf('.'));
+        String simpleName = fqn.substring(fqn.lastIndexOf('.') + 1);
+        StringBuilder checkClassesAccessible = new StringBuilder();
+        checkClassesAccessible.append("package " + packageName + ";" +
+                                      "public class " + simpleName + " {" +
+                                      "    public static void runMe() throws Exception {");
+        for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
+            checkClassesAccessible.append("try {");
+            checkClassesAccessible.append("Class.forName(\"" + e.getValue() + "\").newInstance();");
+            checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":true\");");
+            checkClassesAccessible.append("} catch (Exception ex) {");
+            checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":false\");");
+            checkClassesAccessible.append("}");
+        }
+
+        checkClassesAccessible.append("    }\n" +
+                                      "}");
+
+        return checkClassesAccessible.toString();
+    }
+
+    private static final Map<String, String> MODULES_TO_CHECK_TO_SAMPLE_CLASS = new LinkedHashMap<>();
+
+    static {
+        MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m1", "api.Api");
+        MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m2", "test.Test");
+        MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.base", "java.lang.Object");
+        MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.compiler", "javax.tools.ToolProvider");
+        MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("jdk.compiler", "com.sun.tools.javac.Main");
+    };
+
+    @SupportedAnnotationTypes("*")
+    @SupportedOptions("output")
+    public static final class CheckVisibleModule extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            String expected = processingEnv.getOptions().get("output");
+            Set<String> expectedElements = new HashSet<>(Arrays.asList(expected.split(System.getProperty("line.separator"))));
+            Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
+            Symtab syms = Symtab.instance(context);
+
+            for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) {
+                String module = e.getKey();
+                ModuleElement mod = processingEnv.getElementUtils().getModuleElement(module);
+                String visible = "visible:" + module + ":" + (mod != null);
+
+                if (!expectedElements.contains(visible)) {
+                    throw new AssertionError("actual: " + visible + "; expected: " + expected);
+                }
+
+                JavacElements javacElements = JavacElements.instance(context);
+                ClassSymbol unnamedClass = javacElements.getTypeElement(syms.unnamedModule, e.getValue());
+                String unnamed = "cp.CP:" + module + ":" + (unnamedClass != null);
+
+                if (!expectedElements.contains(unnamed)) {
+                    throw new AssertionError("actual: " + unnamed + "; expected: " + expected);
+                }
+
+                ModuleElement automaticMod = processingEnv.getElementUtils().getModuleElement("automatic");
+                ClassSymbol automaticClass = javacElements.getTypeElement(automaticMod, e.getValue());
+                String automatic = "automatic.Automatic:" + module + ":" + (automaticClass != null);
+
+                if (!expectedElements.contains(automatic)) {
+                    throw new AssertionError("actual: " + automatic + "; expected: " + expected);
+                }
+            }
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    public String[] augmentOptions(String[] options, List<String> auxOptions, String... baseOptions) {
+        List<String> all = new ArrayList<>();
+
+        all.addAll(Arrays.asList(options));
+        all.addAll(Arrays.asList(baseOptions));
+        all.addAll(auxOptions);
+
+        return all.toArray(new String[0]);
+    }
+
+    private static final String[] MODULE_INFO_VARIANTS = {
+        "module m2 { exports test; }",
+        "module m2 { requires m1; exports test; }",
+        "module m2 { requires jdk.compiler; exports test; }",
+    };
+
+    private static final String[][] OPTIONS_VARIANTS = {
+        {"-addmods", "automatic"},
+        {"-addmods", "m1,automatic"},
+        {"-addmods", "jdk.compiler,automatic"},
+        {"-addmods", "m1,jdk.compiler,automatic"},
+        {"-addmods", "ALL-SYSTEM,automatic"},
+        {"-limitmods", "java.base", "-addmods", "automatic"},
+        {"-limitmods", "java.base", "-addmods", "ALL-SYSTEM,automatic"},
+        {"-limitmods", "m2", "-addmods", "automatic"},
+        {"-limitmods", "jdk.compiler", "-addmods", "automatic"},
+    };
+}
diff --git a/langtools/test/tools/javac/modules/AddReadsTest.java b/langtools/test/tools/javac/modules/AddReadsTest.java
new file mode 100644
index 0000000..a3a0f95
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AddReadsTest.java
@@ -0,0 +1,305 @@
+/*
+ * 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 Test the -XaddReads option
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AddReadsTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+
+public class AddReadsTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new AddReadsTest().runTests();
+    }
+
+    @Test
+    void testAddReads(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports api; }",
+                          "package api; public class Api { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package test; public class Test extends api.Api { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api"))
+            throw new Exception("expected output not found");
+
+        //test add dependencies:
+        tb.new JavacTask()
+                .options("-XaddReads:m2=m1",
+                         "-modulesourcepath", src.toString(),
+                         "-processor", VerifyRequires.class.getName())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        String decompiled = tb.new JavapTask()
+                .options("-verbose", classes.resolve("m2").resolve("module-info.class").toString())
+                .run()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (decompiled.contains("m1")) {
+            throw new Exception("Incorrectly refers to m1 module.");
+        }
+
+        //cyclic dependencies OK when created through addReads:
+        tb.new JavacTask()
+                .options("-XaddReads:m2=m1,m1=m2",
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { requires m1; }");
+
+        tb.new JavacTask()
+                .options("-XaddReads:m1=m2",
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class VerifyRequires extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            ModuleElement m2Module = processingEnv.getElementUtils().getModuleElement("m2");
+            if (m2Module == null) {
+                throw new AssertionError("Cannot find the m2 module!");
+            }
+            boolean foundM1 = false;
+            for (RequiresDirective rd : ElementFilter.requiresIn(m2Module.getDirectives())) {
+                foundM1 |= rd.getDependency().getSimpleName().contentEquals("m1");
+            }
+            if (!foundM1) {
+                throw new AssertionError("Cannot find the dependency on m1 module!");
+            }
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    @Test
+    void testAddReadsUnnamedModule(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { api.Api api; }");
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString(),
+                   "-XaddReads:m1=ALL-UNNAMED",
+                   "-XDrawDiagnostics")
+          .outdir(classes)
+          .files(findJavaFiles(moduleSrc))
+          .run()
+          .writeAll();
+    }
+
+    @Test
+    void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package api; public class Api { public static void test() { } }",
+                          "package impl; public class Impl { { api.Api.test(); } }");
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString(),
+                   "-modulesourcepath", moduleSrc.toString(),
+                   "-XaddReads:m1=ALL-UNNAMED",
+                   "-XDrawDiagnostics")
+          .outdir(classes)
+          .files(m1.resolve("impl").resolve("Impl.java"))
+          .run()
+          .writeAll();
+    }
+
+    @Test
+    void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src,
+                          "package impl; public class Impl { api.Api a; }");
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString(),
+                   "-XaddReads:java.base=ALL-UNNAMED",
+                   "-Xmodule:java.base")
+          .outdir(classes)
+          .files(src.resolve("impl").resolve("Impl.java"))
+          .run()
+          .writeAll();
+    }
+
+    @Test
+    void testAddReadsToJavaBase(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src,
+                          "package impl; public class Impl { javax.swing.JButton b; }");
+
+        tb.new JavacTask()
+          .options("-XaddReads:java.base=java.desktop",
+                   "-Xmodule:java.base")
+          .outdir(classes)
+          .files(findJavaFiles(src))
+          .run()
+          .writeAll();
+    }
+
+    private Path prepareTestJar(Path base) throws Exception {
+        Path legacySrc = base.resolve("legacy-src");
+        tb.writeJavaFiles(legacySrc,
+                          "package api; public abstract class Api {}");
+        Path legacyClasses = base.resolve("legacy-classes");
+        Files.createDirectories(legacyClasses);
+
+        String log = tb.new JavacTask()
+                .options()
+                .outdir(legacyClasses)
+                .files(findJavaFiles(legacySrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Path lib = base.resolve("lib");
+
+        Files.createDirectories(lib);
+
+        Path jar = lib.resolve("test-api-1.0.jar");
+
+        tb.new JarTask(jar)
+          .baseDir(legacyClasses)
+          .files("api/Api.class")
+          .run();
+
+        return jar;
+    }
+
+    @Test
+    void testX(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { provides java.lang.Runnable with impl.Impl; }",
+                          "package impl; public class Impl implements Runnable { public void run() { } }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        Path unnamedSrc = base.resolve("unnamed-src");
+        Path unnamedClasses = base.resolve("unnamed-classes");
+
+        Files.createDirectories(unnamedClasses);
+
+        tb.writeJavaFiles(unnamedSrc,
+                          "package impl; public class Impl { }");
+
+        tb.new JavacTask()
+          .options("-XaddReads:m1=ALL-UNNAMED",
+                   "-Xmodule:m1",
+                   "-modulepath", classes.toString())
+          .outdir(unnamedClasses)
+          .files(findJavaFiles(unnamedSrc))
+          .run()
+          .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/modules/AnnotationProcessing.java b/langtools/test/tools/javac/modules/AnnotationProcessing.java
new file mode 100644
index 0000000..49a15b7
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java
@@ -0,0 +1,318 @@
+/*
+ * 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 Verify that annotation processing works.
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AnnotationProcessing
+ */
+
+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 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.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.ModuleElement.ProvidesDirective;
+import javax.lang.model.element.ModuleElement.UsesDirective;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.ElementScanner9;
+
+public class AnnotationProcessing extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new AnnotationProcessing().runTests();
+    }
+
+    @Test
+    void testAPSingleModule(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { }");
+
+        String log = tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString(),
+                         "-processor", AP.class.getName(),
+                         "-AexpectedEnclosedElements=m1=>impl")
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new AssertionError("Unexpected output: " + log);
+    }
+
+    @Test
+    void testAPMultiModule(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+        Path m2 = moduleSrc.resolve("m2");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl1; public class Impl1 { }");
+
+        tb.writeJavaFiles(m2,
+                          "module m2 { }",
+                          "package impl2; public class Impl2 { }");
+
+        String log = tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString(),
+                         "-processor", AP.class.getName(),
+                         "-AexpectedEnclosedElements=m1=>impl1,m2=>impl2")
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new AssertionError("Unexpected output: " + log);
+    }
+
+    @SupportedAnnotationTypes("*")
+    @SupportedOptions("expectedEnclosedElements")
+    public static final class AP extends AbstractProcessor {
+
+        private Map<String, List<String>> module2ExpectedEnclosedElements;
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            if (module2ExpectedEnclosedElements == null) {
+                module2ExpectedEnclosedElements = new HashMap<>();
+
+                String expectedEnclosedElements =
+                        processingEnv.getOptions().get("expectedEnclosedElements");
+
+                for (String moduleDef : expectedEnclosedElements.split(",")) {
+                    String[] module2Packages = moduleDef.split("=>");
+
+                    module2ExpectedEnclosedElements.put(module2Packages[0],
+                                                        Arrays.asList(module2Packages[1].split(":")));
+                }
+            }
+
+            //verify ModuleType and ModuleSymbol behavior:
+            for (Element root : roundEnv.getRootElements()) {
+                ModuleElement module = processingEnv.getElementUtils().getModuleOf(root);
+
+                assertEquals(TypeKind.MODULE, module.asType().getKind());
+
+                boolean[] seenModule = new boolean[1];
+
+                module.accept(new ElementScanner9<Void, Void>() {
+                    @Override
+                    public Void visitModule(ModuleElement e, Void p) {
+                        seenModule[0] = true;
+                        return null;
+                    }
+                    @Override
+                    public Void scan(Element e, Void p) {
+                        throw new AssertionError("Shouldn't get here.");
+                    }
+                }, null);
+
+                assertEquals(true, seenModule[0]);
+
+                List<String> actualElements =
+                        module.getEnclosedElements()
+                              .stream()
+                              .map(s -> (PackageElement) s)
+                              .map(p -> p.getQualifiedName().toString())
+                              .collect(Collectors.toList());
+
+                assertEquals(module2ExpectedEnclosedElements.remove(module.getQualifiedName().toString()),
+                             actualElements);
+            }
+
+            if (roundEnv.processingOver()) {
+                assertEquals(true, module2ExpectedEnclosedElements.isEmpty());
+            }
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    @Test
+    void testVerifyUsesProvides(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports api; uses api.Api; provides api.Api with impl.Impl; }",
+                          "package api; public class Api { }",
+                          "package impl; public class Impl extends api.Api { }");
+
+        String log = tb.new JavacTask()
+                .options("-doe", "-processor", VerifyUsesProvidesAP.class.getName())
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new AssertionError("Unexpected output: " + log);
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class VerifyUsesProvidesAP extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            TypeElement api = processingEnv.getElementUtils().getTypeElement("api.Api");
+
+            assertNonNull("Cannot find api.Api", api);
+
+            ModuleElement modle = (ModuleElement) processingEnv.getElementUtils().getPackageOf(api).getEnclosingElement();
+
+            assertNonNull("modle is null", modle);
+
+            List<? extends UsesDirective> uses = ElementFilter.usesIn(modle.getDirectives());
+            assertEquals(1, uses.size());
+            assertEquals("api.Api", uses.iterator().next().getService().getQualifiedName().toString());
+
+            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());
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    @Test
+    void testPackageNoModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(src,
+                          "package api; public class Api { }");
+
+        String log = tb.new JavacTask()
+                .options("-processor", VerifyPackageNoModule.class.getName(),
+                         "-source", "8",
+                         "-Xlint:-options")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new AssertionError("Unexpected output: " + log);
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class VerifyPackageNoModule extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            TypeElement api = processingEnv.getElementUtils().getTypeElement("api.Api");
+
+            assertNonNull("Cannot find api.Api", api);
+
+            ModuleElement modle = (ModuleElement) processingEnv.getElementUtils().getPackageOf(api).getEnclosingElement();
+
+            assertNull("modle is not null", modle);
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    private static void assertNonNull(String msg, Object val) {
+        if (val == null) {
+            throw new AssertionError(msg);
+        }
+    }
+
+    private static void assertNull(String msg, Object val) {
+        if (val != null) {
+            throw new AssertionError(msg);
+        }
+    }
+
+    private static void assertEquals(Object expected, Object actual) {
+        if (!Objects.equals(expected, actual)) {
+            throw new AssertionError("expected: " + expected + "; actual=" + actual);
+        }
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java
new file mode 100644
index 0000000..7c9b957
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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 Verify that annotation processors inside modules works
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AnnotationProcessorsInModulesTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class AnnotationProcessorsInModulesTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new AnnotationProcessorsInModulesTest().runTests();
+    }
+
+    private static final String annotationProcessorModule1 =
+            "module anno_proc1 {\n" +
+            "    requires java.compiler;\n" +
+            "\n" +
+            "    provides javax.annotation.processing.Processor\n" +
+            "      with mypkg1.MyProcessor1;\n" +
+            "}";
+
+    private static final String annotationProcessorModule2 =
+            "module anno_proc2 {\n" +
+            "    requires java.compiler;\n" +
+            "\n" +
+            "    provides javax.annotation.processing.Processor\n" +
+            "      with mypkg2.MyProcessor2;\n" +
+            "}";
+
+    private static final String annotationProcessor1 =
+            "package mypkg1;\n" +
+            "\n" +
+            "import javax.annotation.processing.AbstractProcessor;\n" +
+            "import javax.annotation.processing.RoundEnvironment;\n" +
+            "import javax.annotation.processing.SupportedAnnotationTypes;\n" +
+            "import javax.lang.model.SourceVersion;\n" +
+            "import javax.lang.model.element.*;\n" +
+            "\n" +
+            "import java.util.*;\n" +
+            "\n" +
+            "@SupportedAnnotationTypes(\"*\")\n" +
+            "public final class MyProcessor1 extends AbstractProcessor {\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n" +
+            "        return false;\n" +
+            "    }\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public SourceVersion getSupportedSourceVersion() {\n" +
+            "        System.out.println(\"the annotation processor 1 is working!\");\n" +
+            "        return SourceVersion.latest();\n" +
+            "    }\n" +
+            "}";
+
+    private static final String annotationProcessor2 =
+            "package mypkg2;\n" +
+            "\n" +
+            "import javax.annotation.processing.AbstractProcessor;\n" +
+            "import javax.annotation.processing.RoundEnvironment;\n" +
+            "import javax.annotation.processing.SupportedAnnotationTypes;\n" +
+            "import javax.lang.model.SourceVersion;\n" +
+            "import javax.lang.model.element.*;\n" +
+            "\n" +
+            "import java.util.*;\n" +
+            "\n" +
+            "@SupportedAnnotationTypes(\"*\")\n" +
+            "public final class MyProcessor2 extends AbstractProcessor {\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n" +
+            "        return false;\n" +
+            "    }\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public SourceVersion getSupportedSourceVersion() {\n" +
+            "        System.out.println(\"the annotation processor 2 is working!\");\n" +
+            "        return SourceVersion.latest();\n" +
+            "    }\n" +
+            "}";
+
+    private static final String testClass = "class Test{}";
+
+    void initialization(Path base) throws Exception {
+        moduleSrc = base.resolve("anno_proc_src");
+        Path anno_proc1 = moduleSrc.resolve("anno_proc1");
+        Path anno_proc2 = moduleSrc.resolve("anno_proc2");
+
+        processorCompiledModules = base.resolve("mods");
+
+        Files.createDirectories(processorCompiledModules);
+
+        tb.writeJavaFiles(
+                anno_proc1,
+                annotationProcessorModule1,
+                annotationProcessor1);
+
+        tb.writeJavaFiles(
+                anno_proc2,
+                annotationProcessorModule2,
+                annotationProcessor2);
+
+        String log = tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(processorCompiledModules)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        classes = base.resolve("classes");
+        Files.createDirectories(classes);
+    }
+
+    Path processorCompiledModules;
+    Path moduleSrc;
+    Path classes;
+
+    @Test
+    void testUseOnlyOneProcessor(Path base) throws Exception {
+        initialization(base);
+        String log = tb.new JavacTask()
+                .options("-processormodulepath", processorCompiledModules.toString(),
+                        "-processor", "mypkg2.MyProcessor2")
+                .outdir(classes)
+                .sources(testClass)
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.STDOUT);
+        if (!log.trim().equals("the annotation processor 2 is working!")) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    void testAnnotationProcessorExecutionOrder(Path base) throws Exception {
+        initialization(base);
+        List<String> log = tb.new JavacTask()
+                .options("-processormodulepath", processorCompiledModules.toString(),
+                        "-processor", "mypkg1.MyProcessor1,mypkg2.MyProcessor2")
+                .outdir(classes)
+                .sources(testClass)
+                .run()
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.STDOUT);
+        if (!log.equals(Arrays.asList("the annotation processor 1 is working!",
+                                      "the annotation processor 2 is working!"))) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        log = tb.new JavacTask()
+                .options("-processormodulepath", processorCompiledModules.toString(),
+                        "-processor", "mypkg2.MyProcessor2,mypkg1.MyProcessor1")
+                .outdir(classes)
+                .sources(testClass)
+                .run()
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.STDOUT);
+        if (!log.equals(Arrays.asList("the annotation processor 2 is working!",
+                                      "the annotation processor 1 is working!"))) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception {
+        initialization(base);
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
+                         "-processor", "mypkg2.MyProcessor2,noPackage.noProcessor,mypkg1.MyProcessor1")
+                .outdir(classes)
+                .sources(testClass)
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.STDOUT, ToolBox.OutputKind.DIRECT).toString();
+        if (!log.trim().equals("[the annotation processor 2 is working!, - compiler.err.proc.processor.not.found: noPackage.noProcessor, 1 error]")) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    void testOptionsExclusion(Path base) throws Exception {
+        initialization(base);
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
+                        "-processorpath", processorCompiledModules.toString())
+                .outdir(classes)
+                .sources(testClass)
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        if (!log.equals(Arrays.asList("- compiler.err.processorpath.no.processormodulepath",
+                                      "1 error"))) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/AutomaticModules.java b/langtools/test/tools/javac/modules/AutomaticModules.java
new file mode 100644
index 0000000..1150e32
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AutomaticModules.java
@@ -0,0 +1,223 @@
+/*
+ * 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 Test automatic modules
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main AutomaticModules
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class AutomaticModules extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        AutomaticModules t = new AutomaticModules();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path legacySrc = base.resolve("legacy-src");
+        tb.writeJavaFiles(legacySrc,
+                          "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}");
+        Path legacyClasses = base.resolve("legacy-classes");
+        Files.createDirectories(legacyClasses);
+
+        String log = tb.new JavacTask()
+                .options()
+                .outdir(legacyClasses)
+                .files(findJavaFiles(legacySrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path jar = modulePath.resolve("test-api-1.0.jar");
+
+        tb.new JarTask(jar)
+          .baseDir(legacyClasses)
+          .files("api/Api.class")
+          .run();
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { requires test.api; }",
+                          "package impl; public class Impl { public void e(api.Api api) { api.actionPerformed(null); } }");
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString(), "-modulepath", modulePath.toString(), "-addmods", "java.desktop")
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testUnnamedModule(Path base) throws Exception {
+        Path legacySrc = base.resolve("legacy-src");
+        tb.writeJavaFiles(legacySrc,
+                          "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }",
+                          "package base; public interface Base { public void run(); }");
+        Path legacyClasses = base.resolve("legacy-classes");
+        Files.createDirectories(legacyClasses);
+
+        String log = tb.new JavacTask()
+                .options()
+                .outdir(legacyClasses)
+                .files(findJavaFiles(legacySrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path apiJar = modulePath.resolve("test-api-1.0.jar");
+
+        tb.new JarTask(apiJar)
+          .baseDir(legacyClasses)
+          .files("api/Api.class")
+          .run();
+
+        Path baseJar = base.resolve("base.jar");
+
+        tb.new JarTask(baseJar)
+          .baseDir(legacyClasses)
+          .files("base/Base.class")
+          .run();
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { requires test.api; }",
+                          "package impl; public class Impl { public void e(api.Api api) { api.run(\"\"); } }");
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString(), "-modulepath", modulePath.toString(), "-classpath", baseJar.toString())
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
+        Path automaticSrc = base.resolve("automaticSrc");
+        tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
+        Path automaticClasses = base.resolve("automaticClasses");
+        tb.createDirectories(automaticClasses);
+
+        String automaticLog = tb.new JavacTask()
+                                .outdir(automaticClasses)
+                                .files(findJavaFiles(automaticSrc))
+                                .run()
+                                .writeAll()
+                                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!automaticLog.isEmpty())
+            throw new Exception("expected output not found: " + automaticLog);
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path automaticJar = modulePath.resolve("automatic-1.0.jar");
+
+        tb.new JarTask(automaticJar)
+          .baseDir(automaticClasses)
+          .files("api/Api.class")
+          .run();
+
+        Path depSrc = base.resolve("depSrc");
+        Path depClasses = base.resolve("depClasses");
+
+        Files.createDirectories(depSrc);
+        Files.createDirectories(depClasses);
+
+        tb.writeJavaFiles(depSrc,
+                          "module m1 { requires public automatic; }",
+                          "package dep; public class Dep { api.Api api; }");
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString())
+                .outdir(depClasses)
+                .files(findJavaFiles(depSrc))
+                .run()
+                .writeAll();
+
+        Path moduleJar = modulePath.resolve("m1.jar");
+
+        tb.new JarTask(moduleJar)
+          .baseDir(depClasses)
+          .files("module-info.class", "dep/Dep.class")
+          .run();
+
+        Path testSrc = base.resolve("testSrc");
+        Path testClasses = base.resolve("testClasses");
+
+        Files.createDirectories(testSrc);
+        Files.createDirectories(testClasses);
+
+        tb.writeJavaFiles(testSrc,
+                          "module m2 { requires automatic; }",
+                          "package test; public class Test { }");
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString())
+                .outdir(testClasses)
+                .files(findJavaFiles(testSrc))
+                .run()
+                .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/modules/DoclintOtherModules.java b/langtools/test/tools/javac/modules/DoclintOtherModules.java
new file mode 100644
index 0000000..c4604d9
--- /dev/null
+++ b/langtools/test/tools/javac/modules/DoclintOtherModules.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Verify that DocLint does not cause unnecessary (and potentially dangerous) implicit compilation
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main DoclintOtherModules
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class DoclintOtherModules extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        DoclintOtherModules t = new DoclintOtherModules();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        Path m2 = src.resolve("m2");
+        tb.writeJavaFiles(m1,
+                          "module m1 {}",
+                          "package m1; /** @see m2.B */ @Deprecated public class A {}");
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m1; exports m2; }",
+                          "package m2; public class B extends Foo {} @Deprecated class Foo {}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString(), "-Xlint:deprecation", "-Xdoclint:-reference", "-Werror")
+                .outdir(classes)
+                .files(findJavaFiles(m1))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/DuplicateClassTest.java b/langtools/test/tools/javac/modules/DuplicateClassTest.java
new file mode 100644
index 0000000..09c0257
--- /dev/null
+++ b/langtools/test/tools/javac/modules/DuplicateClassTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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 Ensure that classes with the same FQNs are OK in unrelated modules.
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main DuplicateClassTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class DuplicateClassTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        DuplicateClassTest t = new DuplicateClassTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { }");
+        tb.writeJavaFiles(m2,
+                          "module m2 { }",
+                          "package impl; public class Impl { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-modulesourcepath", base.toString())
+                .outdir(classes)
+                .files(findJavaFiles(base))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found; output: " + log);
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java
new file mode 100644
index 0000000..1a14cdd
--- /dev/null
+++ b/langtools/test/tools/javac/modules/EdgeCases.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for multi-module mode compilation
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.code
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main EdgeCases
+ */
+
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.lang.model.element.Element;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+
+public class EdgeCases extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new EdgeCases().runTests();
+    }
+
+    @Test
+    void testAddExportUndefinedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XaddExports:undef/undef=ALL-UNNAMED", "-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("- compiler.err.cant.find.module: undef",
+                                              "Test.java:1:27: compiler.err.doesnt.exist: undef",
+                                              "2 errors");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testModuleSymbolOutterMostClass(Path base) throws Exception {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+            Path moduleSrc = base.resolve("module-src");
+            Path m1 = moduleSrc.resolve("m1");
+
+            tb.writeJavaFiles(m1, "module m1 { }");
+
+            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc));
+            JavacTask task = (JavacTask) compiler.getTask(null, fm, null, null, null, files);
+
+            task.analyze();
+
+            ModuleSymbol msym = (ModuleSymbol) task.getElements().getModuleElement("m1");
+
+            msym.outermostClass();
+        }
+    }
+
+    @Test
+    void testParseEnterAnalyze(Path base) throws Exception {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+            Path moduleSrc = base.resolve("module-src");
+            Path m1 = moduleSrc.resolve("m1");
+
+            tb.writeJavaFiles(m1, "module m1 { }",
+                                  "package p;",
+                                  "package p; class T { }");
+
+            Path classes = base.resolve("classes");
+            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc));
+            List<String> options = Arrays.asList("-d", classes.toString(), "-Xpkginfo:always");
+            JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, null, options, null, files);
+
+            Iterable<? extends CompilationUnitTree> parsed = task.parse();
+            Iterable<? extends Element> entered = task.enter(parsed);
+            Iterable<? extends Element> analyzed = task.analyze(entered);
+            Iterable<? extends JavaFileObject> generatedFiles = task.generate(analyzed);
+
+            Set<String> generated = new HashSet<>();
+
+            for (JavaFileObject jfo : generatedFiles) {
+                generated.add(jfo.getName());
+            }
+
+            Set<String> expected = new HashSet<>(
+                    Arrays.asList(Paths.get("testParseEnterAnalyze", "classes", "p", "package-info.class").toString(),
+                                  Paths.get("testParseEnterAnalyze", "classes", "module-info.class").toString(),
+                                  Paths.get("testParseEnterAnalyze", "classes", "p", "T.class").toString())
+            );
+
+            if (!Objects.equals(expected, generated))
+                throw new AssertionError("Incorrect generated files: " + generated);
+        }
+    }
+
+    @Test
+    void testModuleImplicitModuleBoundaries(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports api1; }",
+                          "package api1; public class Api1 { public void call() { } }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { requires m1; 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 m2; }",
+                          "package test; public class Test { { api2.Api2.get().call(); api2.Api2.get().toString(); } }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("Test.java:1:52: compiler.err.not.def.access.class.intf.cant.access: call(), api1.Api1") ||
+            !log.contains("Test.java:1:76: compiler.err.not.def.access.class.intf.cant.access: toString(), java.lang.Object"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testAssignClassToAutomaticModule(Path base) throws Exception {
+        //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not
+        //duplicated when being accessed through a classfile.
+        Path automaticSrc = base.resolve("automaticSrc");
+        tb.writeJavaFiles(automaticSrc, "package api1; public class Api1 {}");
+        Path automaticClasses = base.resolve("automaticClasses");
+        tb.createDirectories(automaticClasses);
+
+        String automaticLog = tb.new JavacTask()
+                                .outdir(automaticClasses)
+                                .files(findJavaFiles(automaticSrc))
+                                .run()
+                                .writeAll()
+                                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!automaticLog.isEmpty())
+            throw new Exception("expected output not found: " + automaticLog);
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path automaticJar = modulePath.resolve("m1-1.0.jar");
+
+        tb.new JarTask(automaticJar)
+          .baseDir(automaticClasses)
+          .files("api1/Api1.class")
+          .run();
+
+        Path src = base.resolve("src");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { requires m1; 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; }",
+                          "package test; public class Test { { api2.Api2.get(); api1.Api1 a1; } }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src_m2))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-modulepath", modulePath.toString(),
+                         "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src_m3))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testEmptyImplicitModuleInfo(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        Files.createDirectories(src_m1);
+        try (Writer w = Files.newBufferedWriter(src_m1.resolve("module-info.java"))) {}
+        tb.writeJavaFiles(src_m1,
+                          "package test; public class Test {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        tb.new JavacTask()
+                .options("-sourcepath", src_m1.toString(),
+                         "-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src_m1.resolve("test")))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+
+        tb.writeJavaFiles(src_m1,
+                          "module m1 {}");
+
+        tb.new JavacTask()
+                .options("-sourcepath", src_m1.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src_m1.resolve("test")))
+                .run()
+                .writeAll();
+
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/GraphsTest.java b/langtools/test/tools/javac/modules/GraphsTest.java
new file mode 100644
index 0000000..6903905
--- /dev/null
+++ b/langtools/test/tools/javac/modules/GraphsTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for module graph resolution issues
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main GraphsTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class GraphsTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        GraphsTest t = new GraphsTest();
+        t.runTests();
+    }
+
+    /**
+     * 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 L           |                  |
+     *                          |                    |------------------
+     *                          | requires public O  |
+     *                          |                    |
+     *                          +--------------------+
+     *
+     */
+    @Test
+    void diamond(Path base) throws Exception {
+
+        Path modules = Files.createDirectories(base.resolve("modules"));
+
+        new ModuleBuilder("J")
+                .exports("openJ")
+                .classes("package openJ; public class J { }")
+                .classes("package closedJ; public class J { }")
+                .build(base.resolve("jar"));
+
+        Path jarModules = Files.createDirectories(base.resolve("jarModules"));
+        Path jar = jarModules.resolve("J.jar");
+        tb.new JarTask(jar)
+                .baseDir(base.resolve("jar/J"))
+                .files(".")
+                .run()
+                .writeAll();
+
+        new ModuleBuilder("O")
+                .exports("openO")
+                .requiresPublic("J", jarModules)
+                .classes("package openO; public class O { openJ.J j; }")
+                .classes("package closedO; public class O { }")
+                .build(modules);
+        new ModuleBuilder("N")
+                .requiresPublic("O", modules, jarModules)
+                .exports("openN")
+                .classes("package openN; public class N { }")
+                .classes("package closedN; public class N { }")
+                .build(modules);
+        new ModuleBuilder("L")
+                .requiresPublic("O", modules, jarModules)
+                .exports("openL")
+                .classes("package openL; public class L { }")
+                .classes("package closedL; public class L { }")
+                .build(modules);
+        ModuleBuilder m = new ModuleBuilder("M");
+        //positive case
+        Path positiveSrc = m
+                .requires("N", modules)
+                .requires("L", modules)
+                .classes("package p; public class Positive { openO.O o; openN.N n; openL.L l; }")
+                .write(base.resolve("positiveSrc"));
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-mp", modules + File.pathSeparator + jarModules)
+                .outdir(Files.createDirectories(base.resolve("positive")))
+                .files(findJavaFiles(positiveSrc))
+                .run()
+                .writeAll();
+        //negative case
+        Path negativeSrc = m.classes("package p; public class Negative { closedO.O o; closedN.N n; closedL.L l; }")
+                .write(base.resolve("negativeSrc"));
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-mp", modules + File.pathSeparator + jarModules)
+                .outdir(Files.createDirectories(base.resolve("negative")))
+                .files(findJavaFiles(negativeSrc))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "Negative.java:1:43: compiler.err.doesnt.exist: closedO",
+                "Negative.java:1:56: compiler.err.doesnt.exist: closedN",
+                "Negative.java:1:69: compiler.err.doesnt.exist: closedL");
+        if (!log.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+        //multi module mode
+        m.write(modules);
+        List<String> out = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", modules + "/*/src",
+                        "-mp", jarModules.toString()
+                )
+                .outdir(Files.createDirectories(base.resolve("negative")))
+                .files(findJavaFiles(modules))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        expected = Arrays.asList(
+                "Negative.java:1:43: compiler.err.not.def.access.package.cant.access: closedO.O, closedO",
+                "Negative.java:1:56: compiler.err.not.def.access.package.cant.access: closedN.N, closedN",
+                "Negative.java:1:69: compiler.err.not.def.access.package.cant.access: closedL.L, closedL");
+        if (!out.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+        //checks if the output does not contain messages about exported packages.
+        Pattern regex = Pattern.compile("compiler\\.err.*(openO\\.O|openN\\.N|openL\\.L)");
+        for (String s : out) {
+            if (regex.matcher(s).find()) {
+                throw new Exception("Unexpected output: " + s);
+            }
+        }
+    }
+
+    /**
+     * 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|
+    +-------------+        |                    |        +---------------+
+                           +--------------------+
+    */
+    @Test
+    public void reexportOfQualifiedExport(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("M")
+                .requiresPublic("N")
+                .write(modules);
+        new ModuleBuilder("N")
+                .exportsTo("pack", "M")
+                .classes("package pack; public class Clazz { }")
+                .write(modules);
+        new ModuleBuilder("L")
+                .requires("M")
+                .classes("package p; public class A { A(pack.Clazz cl){} } ")
+                .write(modules);
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", modules + "/*/src")
+                .outdir(Files.createDirectories(base.resolve("negative")))
+                .files(findJavaFiles(modules))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        String expected = "A.java:1:35: compiler.err.not.def.access.package.cant.access: pack.Clazz, pack";
+        if (!log.contains(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/HelloWorldTest.java b/langtools/test/tools/javac/modules/HelloWorldTest.java
new file mode 100644
index 0000000..aa5d3ac
--- /dev/null
+++ b/langtools/test/tools/javac/modules/HelloWorldTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @summary simple tests of javac compilation modes
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main HelloWorldTest
+ */
+
+import java.nio.file.*;
+import javax.tools.*;
+
+public class HelloWorldTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        HelloWorldTest t = new HelloWorldTest();
+        t.runTests();
+    }
+
+    public static final String HELLO_WORLD =
+          "class HelloWorld {\n"
+        + "    public static void main(String... args) {\n"
+        + "        System.out.println(\"Hello World!\");\n"
+        + "    }\n"
+        + "}";
+
+    public static final String PKG_HELLO_WORLD =
+          "package p;\n"
+        + HELLO_WORLD;
+
+    @Test
+    void testLegacyMode(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        Path smallRtJar = base.resolve("small-rt.jar");
+        try (JavaFileManager fm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) {
+            tb.new JarTask(smallRtJar)
+                .files(fm, StandardLocation.PLATFORM_CLASS_PATH,
+                    "java.lang.**", "java.io.*", "java.util.*")
+                .run();
+        }
+
+        tb.new JavacTask()
+            .options("-source", "8",
+                "-target", "8",
+                "-bootclasspath", smallRtJar.toString())
+            .outdir(classes)
+            .files(src.resolve("HelloWorld.java"))
+            .run();
+
+        checkFiles(classes.resolve("HelloWorld.class"));
+    }
+
+    @Test
+    void testUnnamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+            .outdir(classes)
+            .files(src.resolve("HelloWorld.java"))
+            .run();
+
+        checkFiles(classes.resolve("HelloWorld.class"));
+    }
+
+    @Test
+    void testSingleModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "module m { }");
+        tb.writeJavaFiles(src, PKG_HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+            .outdir(classes)
+            .files(src.resolve("module-info.java"), src.resolve("p/HelloWorld.java"))
+            .run()
+            .writeAll();
+
+        checkFiles(
+            classes.resolve("module-info.class"),
+            classes.resolve("p/HelloWorld.class"));
+    }
+
+    @Test
+    void testModuleSourcePath(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 { }");
+        tb.writeJavaFiles(src_m1, PKG_HELLO_WORLD);
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+            .options("-modulesourcepath", src.toString())
+            .outdir(classes)
+            .files(src_m1.resolve("p/HelloWorld.java"))
+            .run()
+            .writeAll();
+
+        checkFiles(
+            classes.resolve("m1/module-info.class"),
+            classes.resolve("m1/p/HelloWorld.class"));
+    }
+
+    void checkFiles(Path... files) throws Exception {
+        for (Path f: files) {
+            if (!Files.exists(f))
+                throw new Exception("expected file not found: " + f);
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/MOptionTest.java b/langtools/test/tools/javac/modules/MOptionTest.java
new file mode 100644
index 0000000..379df01
--- /dev/null
+++ b/langtools/test/tools/javac/modules/MOptionTest.java
@@ -0,0 +1,263 @@
+/*
+ * 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 8146946
+ * @summary implement javac -m option
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main MOptionTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+
+import com.sun.source.util.JavacTask;
+
+public class MOptionTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new MOptionTest().runTests();
+    }
+
+    @Test
+    void testOneModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        Path build = base.resolve("build");
+        Files.createDirectories(build);
+
+        tb.writeJavaFiles(m1,
+                "module m1 {}",
+                "package test; public class Test {}");
+
+        tb.new JavacTask()
+                .options("-m", "m1", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        Path moduleInfoClass = build.resolve("m1/module-info.class");
+        Path testTestClass = build.resolve("m1/test/Test.class");
+
+        FileTime moduleInfoTimeStamp = Files.getLastModifiedTime(moduleInfoClass);
+        FileTime testTestTimeStamp = Files.getLastModifiedTime(testTestClass);
+
+        Path moduleInfo = m1.resolve("module-info.java");
+        if (moduleInfoTimeStamp.compareTo(Files.getLastModifiedTime(moduleInfo)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        Path testTest = m1.resolve("test/Test.java");
+        if (testTestTimeStamp.compareTo(Files.getLastModifiedTime(testTest)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        Thread.sleep(2000); //timestamps
+
+        tb.new JavacTask()
+                .options("-m", "m1", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        if (!moduleInfoTimeStamp.equals(Files.getLastModifiedTime(moduleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (!testTestTimeStamp.equals(Files.getLastModifiedTime(testTestClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        Thread.sleep(2000); //timestamps
+
+        Files.setLastModifiedTime(testTest, FileTime.fromMillis(System.currentTimeMillis()));
+
+        tb.new JavacTask()
+                .options("-m", "m1", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        if (!moduleInfoTimeStamp.equals(Files.getLastModifiedTime(moduleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (Files.getLastModifiedTime(testTestClass).compareTo(Files.getLastModifiedTime(testTest)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+    }
+
+    @Test
+    void testNoOutputDir(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        Path build = base.resolve("build");
+        Files.createDirectories(build);
+
+        tb.writeJavaFiles(m1,
+                "module m1 {}",
+                "package test; public class Test {}");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                    "-m", "m1",
+                    "-modulesourcepath", src.toString())
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.output.dir.must.be.specified.with.dash.m.option"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testNoModuleSourcePath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        Path build = base.resolve("build");
+        Files.createDirectories(build);
+
+        tb.writeJavaFiles(m1,
+                "module m1 {}",
+                "package test; public class Test {}");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-m", "m1",
+                        "-d", build.toString())
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.modulesourcepath.must.be.specified.with.dash.m.option"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testMultiModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        Path m2 = src.resolve("m2");
+        Path build = base.resolve("build");
+        Files.createDirectories(build);
+
+        tb.writeJavaFiles(m1,
+                "module m1 {}",
+                "package p1; public class C1 {}");
+
+        tb.writeJavaFiles(m2,
+                "module m2 {}",
+                "package p2; public class C2 {}");
+
+        tb.new JavacTask()
+                .options("-m", "m1,m2", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        Path m1ModuleInfoClass = build.resolve("m1/module-info.class");
+        Path classC1 = build.resolve("m1/p1/C1.class");
+
+        Path m2ModuleInfoClass = build.resolve("m2/module-info.class");
+        Path classC2 = build.resolve("m2/p2/C2.class");
+
+        FileTime m1ModuleInfoTimeStamp = Files.getLastModifiedTime(m1ModuleInfoClass);
+        FileTime C1TimeStamp = Files.getLastModifiedTime(classC1);
+
+        FileTime m2ModuleInfoTimeStamp = Files.getLastModifiedTime(m2ModuleInfoClass);
+        FileTime C2TimeStamp = Files.getLastModifiedTime(classC2);
+
+        Path m1ModuleInfo = m1.resolve("module-info.java");
+        Path m2ModuleInfo = m2.resolve("module-info.java");
+
+        if (m1ModuleInfoTimeStamp.compareTo(Files.getLastModifiedTime(m1ModuleInfo)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        if (m2ModuleInfoTimeStamp.compareTo(Files.getLastModifiedTime(m2ModuleInfo)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        Path C1Source = m1.resolve("p1/C1.java");
+        Path C2Source = m2.resolve("p2/C2.java");
+
+        if (C1TimeStamp.compareTo(Files.getLastModifiedTime(C1Source)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        if (C2TimeStamp.compareTo(Files.getLastModifiedTime(C2Source)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        Thread.sleep(2000); //timestamps
+
+        tb.new JavacTask()
+                .options("-m", "m1,m2", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        if (!m1ModuleInfoTimeStamp.equals(Files.getLastModifiedTime(m1ModuleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (!m2ModuleInfoTimeStamp.equals(Files.getLastModifiedTime(m2ModuleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (!C1TimeStamp.equals(Files.getLastModifiedTime(classC1))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (!C2TimeStamp.equals(Files.getLastModifiedTime(classC2))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        Thread.sleep(2000); //timestamps
+
+        Files.setLastModifiedTime(C1Source, FileTime.fromMillis(System.currentTimeMillis()));
+        Files.setLastModifiedTime(C2Source, FileTime.fromMillis(System.currentTimeMillis()));
+
+        tb.new JavacTask()
+                .options("-m", "m1,m2", "-modulesourcepath", src.toString(), "-d", build.toString())
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        if (!m1ModuleInfoTimeStamp.equals(Files.getLastModifiedTime(m1ModuleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (!m2ModuleInfoTimeStamp.equals(Files.getLastModifiedTime(m2ModuleInfoClass))) {
+            throw new AssertionError("Classfile update!");
+        }
+
+        if (Files.getLastModifiedTime(classC1).compareTo(Files.getLastModifiedTime(C1Source)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+
+        if (Files.getLastModifiedTime(classC2).compareTo(Files.getLastModifiedTime(C2Source)) < 0) {
+            throw new AssertionError("Classfiles too old!");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModuleFinderTest.java b/langtools/test/tools/javac/modules/ModuleFinderTest.java
new file mode 100644
index 0000000..302357f
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModuleFinderTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for module finder
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ModuleFinderTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ModuleFinderTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        ModuleFinderTest t = new ModuleFinderTest();
+        t.runTests();
+    }
+
+    @Test
+    void testDuplicateModulesOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m1 { }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        tb.new JarTask(modules.resolve("m1-1.jar"))
+                .baseDir(classes)
+                .files(".")
+                .run();
+
+        tb.new JarTask(modules.resolve("m1-2.jar"))
+                .baseDir(classes)
+                .files(".")
+                .run();
+
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2, "module m2 { requires m1; }");
+
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics", "-modulepath", modules.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src2))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.duplicate.module.on.path: (compiler.misc.locn.module_path), m1"))
+            throw new Exception("expected output not found");
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModuleInfoTest.java b/langtools/test/tools/javac/modules/ModuleInfoTest.java
new file mode 100644
index 0000000..0c52319
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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 tests for modfule declarations
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ModuleInfoTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ModuleInfoTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        ModuleInfoTest t = new ModuleInfoTest();
+        t.runTests();
+    }
+
+    /**
+     * Check error message if module declaration not in module-info.java.
+     */
+    @Test
+    void testModuleDeclNotInModuleJava(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("M.java"), "module M { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("M.java:1:1: compiler.err.module.decl.sb.in.module-info.java"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a package private class can be put in module-info.java.
+     */
+    @Test
+    void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "class C { }");
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    /**
+     * Verify that a public class cannot be put in module-info.java.
+     */
+    @Test
+    void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeFile(src.resolve("module-info.java"), "public class C { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:8: compiler.err.class.public.should.be.in.file: C"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that only one module decl can be put in module-info.java.
+     */
+    @Test
+    void testSingleModuleDecl(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:14: compiler.err.expected: token.end-of-input"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that missing requires are reported.
+     */
+    @Test
+    void testRequiresNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { requires M2; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:22: compiler.err.module.not.found: M2"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that missing exports are reported.
+     */
+    @Test
+    void testExportsNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M1 { exports p to M2; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:26: compiler.err.module.not.found: M2"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a simple loop is detected.
+     */
+    @Test
+    void testRequiresSelf(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module M { requires M; }");
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:21: compiler.err.cyclic.requires: M"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a multi-module loop is detected.
+     */
+    @Test
+    void testRequiresLoop(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 m3; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:22: compiler.err.cyclic.requires: m3"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that a multi-module loop is detected.
+     */
+    @Test
+    void testRequiresPublicLoop(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; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:29: compiler.err.cyclic.requires: m3"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that duplicate requires are detected.
+     */
+    @Test
+    void testDuplicateRequires(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 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires m1; requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:35: compiler.err.duplicate.requires: m1"))
+            throw new Exception("expected output not found");
+    }
+
+    /**
+     * Verify that duplicate exported packages are detected.
+     */
+    @Test
+    void testDuplicateExports_packages(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 = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.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
+    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 classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.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
+    void testDuplicateExports_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 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { exports p to m1, m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:30: compiler.err.duplicate.exports: m1"))
+            throw new Exception("expected output not found");
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModulePathTest.java b/langtools/test/tools/javac/modules/ModulePathTest.java
new file mode 100644
index 0000000..1ef7866
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModulePathTest.java
@@ -0,0 +1,417 @@
+/*
+ * 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 tests for -modulepath
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ *      jdk.jlink/jdk.tools.jmod
+ * @build ToolBox ModuleTestBase
+ * @run main ModulePathTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ModulePathTest extends ModuleTestBase {
+
+    public static final String PATH_SEP = File.pathSeparator;
+
+    public static void main(String... args) throws Exception {
+        ModulePathTest t = new ModulePathTest();
+        t.runTests();
+    }
+
+    @Test
+    void testNotExistsOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "doesNotExist")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, doesNotExist"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testNotADirOnPath_1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.txt", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.txt")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, dummy.txt"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testNotADirOnPath_2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.jimage", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.jimage")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.illegal.argument.for.option: -modulepath, dummy.jimage"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExplodedModuleOnPath(Path base) throws Exception {
+        Path modSrc = base.resolve("modSrc");
+        tb.writeJavaFiles(modSrc,
+                "module m1 { exports p; }",
+                "package p; public class CC { }");
+        Path modClasses = base.resolve("modClasses");
+        Files.createDirectories(modClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(modClasses)
+                .files(findJavaFiles(modSrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires m1 ; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .options("-modulepath", modClasses.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testBadExplodedModuleOnPath(Path base) throws Exception {
+        Path modClasses = base.resolve("modClasses");
+        tb.writeFile(modClasses.resolve("module-info.class"), "module m1 { }");
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires m1 ; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", modClasses.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.locn.bad.module-info: " + modClasses.toString()))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testAutoJarOnPath(Path base) throws Exception {
+        Path jarSrc = base.resolve("jarSrc");
+        tb.writeJavaFiles(jarSrc,
+                "package p; public class CC { }");
+        Path jarClasses = base.resolve("jarClasses");
+        Files.createDirectories(jarClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(jarClasses)
+                .files(findJavaFiles(jarSrc))
+                .run()
+                .writeAll();
+
+        Path moduleJar = base.resolve("m1.jar");
+        tb.new JarTask(moduleJar)
+          .baseDir(jarClasses)
+          .files("p/CC.class")
+          .run();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { p.CC cc; }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .options("-modulepath", moduleJar.toString(), "-addmods", "m1")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testModJarOnPath(Path base) throws Exception {
+        Path jarSrc = base.resolve("jarSrc");
+        tb.writeJavaFiles(jarSrc,
+                "module m1 { exports p; }",
+                "package p; public class CC { }");
+        Path jarClasses = base.resolve("jarClasses");
+        Files.createDirectories(jarClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(jarClasses)
+                .files(findJavaFiles(jarSrc))
+                .run()
+                .writeAll();
+
+        Path moduleJar = base.resolve("myModule.jar"); // deliberately not m1
+        tb.new JarTask(moduleJar)
+          .baseDir(jarClasses)
+          .files("module-info.class", "p/CC.class")
+          .run();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires m1 ; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .options("-modulepath", moduleJar.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testBadJarOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.jar", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.jar")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.locn.cant.read.file: dummy.jar"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testJModOnPath(Path base) throws Exception {
+        Path jmodSrc = base.resolve("jmodSrc");
+        tb.writeJavaFiles(jmodSrc,
+                "module m1 { exports p; }",
+                "package p; public class CC { }");
+        Path jmodClasses = base.resolve("jmodClasses");
+        Files.createDirectories(jmodClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(jmodClasses)
+                .files(findJavaFiles(jmodSrc))
+                .run()
+                .writeAll();
+
+        Path jmod = base.resolve("myModule.jmod"); // deliberately not m1
+        jmod(jmodClasses, jmod);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires m1 ; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes)
+                .options("-modulepath", jmod.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testBadJModOnPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { }");
+        tb.writeFile("dummy.jmod", "");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", "dummy.jmod")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.locn.cant.read.file: dummy.jmod"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void relativePath(Path base) throws Exception {
+        final Path modules = base.resolve("modules");
+        new ModuleBuilder("m1").build(modules);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", modules + "/./../modules")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void duplicatePaths_1(Path base) throws Exception {
+        final Path modules = base.resolve("modules");
+        new ModuleBuilder("m1").build(modules);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", modules + "/./../modules" + PATH_SEP + modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void duplicatePaths_2(Path base) throws Exception {
+        final Path modules = base.resolve("modules");
+        new ModuleBuilder("m1").build(modules);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", modules.toString(),
+                        "-modulepath", modules.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void oneModuleHidesAnother(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path deepModuleDir = module.resolve("deepModuleDir");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class E { }")
+                .build(deepModuleDir);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }", " package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", deepModuleDir + PATH_SEP + module)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void modulesInDifferentContainers(Path base) throws Exception {
+        final Path modules = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("one")
+                .classes("package one; public class A { }")
+                .build(modules);
+
+        new ModuleBuilder("m2")
+                .requires("m1", modules)
+                .build(base.resolve("tmp"));
+        jar(base.resolve("tmp/m2"), modules.resolve("m2.jar"));
+
+        new ModuleBuilder("m3")
+                .requires("m2", modules)
+                .build(base.resolve("tmp"));
+        jmod(base.resolve("tmp/m3"), modules.resolve("m3.jmod"));
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m { requires m3; requires m2; requires m1; }",
+                "package p; class A { void main() { one.A.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", modules.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    private void jar(Path dir, Path jar) throws IOException {
+        tb.new JarTask(jar)
+                .baseDir(dir)
+                .files(".")
+                .run()
+                .writeAll();
+    }
+
+    private void jmod(Path dir, Path jmod) throws Exception {
+        String[] args = {
+                "create",
+                "--class-path", dir.toString(),
+                jmod.toString()
+        };
+        jdk.tools.jmod.Main.run(args, System.out);
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java
new file mode 100644
index 0000000..a1ed43a
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java
@@ -0,0 +1,459 @@
+/*
+ * 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 tests for -modulesourcepath
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ModuleSourcePathTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+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.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ModuleSourcePathTest extends ModuleTestBase {
+
+    public static final char PATH_SEP = File.pathSeparatorChar;
+
+    public static void main(String... args) throws Exception {
+        ModuleSourcePathTest t = new ModuleSourcePathTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSourcePathConflict(Path base) throws Exception {
+        Path sp = base.resolve("src");
+        Path msp = base.resolve("srcmodules");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-sourcepath", sp.toString().replace('/', File.separatorChar),
+                        "-modulesourcepath", msp.toString().replace('/', File.separatorChar),
+                        "dummyClass")
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("cannot specify both -sourcepath and -modulesourcepath"))
+            throw new Exception("expected diagnostic not found");
+    }
+
+    @Test
+    void testUnnormalizedPath1(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(prefixAll(findJavaFiles(src), Paths.get("./")))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testUnnormalizedPath2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", "./" + src)
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    private Path[] prefixAll(Path[] paths, Path prefix) {
+        return Stream.of(paths)
+                .map(prefix::resolve)
+                .collect(Collectors.toList())
+                .toArray(new Path[paths.length]);
+    }
+
+    @Test
+    void regularBraces(Path base) throws Exception {
+        generateModules(base, "src1", "src2/inner_dir");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{src1,src2/inner_dir}")
+                .files(base.resolve("src1/m0/pkg0/A.java"), base.resolve("src2/inner_dir/m1/pkg1/A.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("m0/pkg0/A.class"),
+                modules.resolve("m1/pkg1/A.class"),
+                modules.resolve("m0/module-info.class"),
+                modules.resolve("m1/module-info.class"));
+    }
+
+    @Test
+    void mismatchedBraces(Path base) throws Exception {
+        final List<String> sourcePaths = Arrays.asList(
+                "{",
+                "}",
+                "}{",
+                "./}",
+                ".././{./",
+                "src{}}",
+                "{{}{}}{}}",
+                "src/{a,b}/{",
+                "src/{a,{,{}}",
+                "{.,..{}/src",
+                "*}{",
+                "{}*}"
+        );
+        for (String sourcepath : sourcePaths) {
+            String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                    .options("-XDrawDiagnostics",
+                            "-modulesourcepath", sourcepath.replace('/', File.separatorChar))
+                    .run(ToolBox.Expect.FAIL)
+                    .writeAll()
+                    .getOutput(ToolBox.OutputKind.DIRECT);
+
+            if (!log.contains("- compiler.err.illegal.argument.for.option: -modulesourcepath, mismatched braces"))
+                throw new Exception("expected output for path [" + sourcepath + "] not found");
+        }
+    }
+
+    @Test
+    void deepBraces(Path base) throws Exception {
+        String[] modulePaths = {"src/src1",
+                "src/src2",
+                "src/src3",
+                "src/srcB/src1",
+                "src/srcB/src2/srcXX",
+                "src/srcB/src2/srcXY",
+                "src/srcC/src1",
+                "src/srcC/src2/srcXX",
+                "src/srcC/src2/srcXY"};
+        generateModules(base, modulePaths);
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath",
+                        base + "/{src/{{src1,src2,src3},{srcB,srcC}/{src1,src2/srcX{X,Y}/}},.}"
+                                .replace('/', File.separatorChar))
+                .files(findJavaFiles(base.resolve(modulePaths[modulePaths.length - 1])))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        for (int i = 0; i < modulePaths.length; i++) {
+            checkFiles(modules.resolve("m" + i + "/module-info.class"));
+        }
+        checkFiles(modules.resolve("m8/pkg8/A.class"));
+    }
+
+    @Test
+    void fileInPath(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
+        tb.writeFile(base.resolve("dummy.txt"), "");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{dummy.txt,src}")
+                .files(src.resolve("kettle$/electric/Heater.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("kettle$/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle$/module-info.class"));
+    }
+
+    @Test
+    void noAlternative(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{src}")
+                .files(src.resolve("kettle$/electric/Heater.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("kettle$/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle$/module-info.class"));
+    }
+
+    @Test
+    void noChoice(Path base) throws Exception {
+        tb.writeJavaFiles(base.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{}")
+                .files(base.resolve("kettle$/electric/Heater.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("kettle$/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle$/module-info.class"));
+    }
+
+    @Test
+    void nestedModules(Path src) throws Exception {
+        Path carModule = src.resolve("car");
+        tb.writeJavaFiles(carModule, "module car { }", "package light; class Headlight { }");
+        tb.writeJavaFiles(carModule.resolve("engine"), "module engine { }", "package flat; class Piston { }");
+
+        final Path modules = src.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", "{" + src + "," + src + "/car}")
+                .files(findJavaFiles(src))
+                .outdir(modules)
+                .run()
+                .writeAll();
+        checkFiles(modules.resolve("car/light/Headlight.class"));
+        checkFiles(modules.resolve("engine/flat/Piston.class"));
+    }
+
+    @Test
+    void relativePaths(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("kettle"), "module kettle { }", "package electric; class Heater { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/src/./../src")
+                .files(src.resolve("kettle/electric/Heater.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+        checkFiles(modules.resolve("kettle/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle/module-info.class"));
+    }
+
+    @Test
+    void duplicatePaths(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{src,src,src}")
+                .files(src.resolve("m1/a/A.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("m1/module-info.class"));
+    }
+
+    @Test
+    void notExistentPaths(Path base) throws Exception {
+        tb.writeJavaFiles(base.resolve("m1"), "module m1 { requires m0; }", "package a; class A { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/not_exist" + PATH_SEP + base + "/{not_exist,}")
+                .files(base.resolve("m1/a/A.java"))
+                .outdir(modules)
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("compiler.err.module.not.found: m0"))
+            throw new Exception("expected output for not existent module source path not found");
+    }
+
+    @Test
+    void notExistentPathShouldBeSkipped(Path base) throws Exception {
+        tb.writeJavaFiles(base.resolve("m1"), "module m1 { }", "package a; class A { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "{/not_exist,/}")
+                .files(base.resolve("m1/a/A.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("m1/module-info.class"));
+    }
+
+    @Test
+    void commas(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/{,{,,,,src,,,}}")
+                .files(src.resolve("m1/a/A.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("m1/module-info.class"));
+    }
+
+    @Test
+    void asterisk(Path base) throws Exception {
+        tb.writeJavaFiles(base.resolve("kettle").resolve("classes"), "module kettle { }",
+                "package electric; class Heater { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", base + "/*/classes/")
+                .files(base.resolve("kettle/classes/electric/Heater.java"))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("kettle/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle/module-info.class"));
+    }
+
+    @Test
+    void asteriskInDifferentSets(Path base) throws Exception {
+        Path src = base.resolve("src");
+        final Path module = src.resolve("kettle");
+        tb.writeJavaFiles(module.resolve("classes"), "module kettle { }", "package electric; class Heater { }");
+        tb.writeJavaFiles(module.resolve("gensrc"), "package model; class Java { }");
+        tb.writeJavaFiles(module.resolve("special/classes"), "package gas; class Heater { }");
+
+        final Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src + "{/*/gensrc/,/*/classes/}" + PATH_SEP
+                                + src + "/*/special/classes")
+                .files(findJavaFiles(src))
+                .outdir(modules)
+                .run()
+                .writeAll();
+
+        checkFiles(modules.resolve("kettle/electric/Heater.class"));
+        checkFiles(modules.resolve("kettle/gas/Heater.class"));
+        checkFiles(modules.resolve("kettle/model/Java.class"));
+        checkFiles(modules.resolve("kettle/module-info.class"));
+    }
+
+    @Test
+    void asteriskIllegalUse(Path base) throws Exception {
+        final List<String> sourcePaths = Arrays.asList(
+                "*",
+                "**",
+                "***",
+                "*.*",
+                ".*",
+                "*.",
+                "src/*/*/",
+                "{*,*}",
+                "src/module*/"
+        );
+        for (String sourcepath : sourcePaths) {
+            String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                    .options("-XDrawDiagnostics",
+                            "-modulesourcepath", sourcepath.replace('/', File.separatorChar))
+                    .run(ToolBox.Expect.FAIL)
+                    .writeAll()
+                    .getOutput(ToolBox.OutputKind.DIRECT);
+
+            if (!log.contains("- compiler.err.illegal.argument.for.option: -modulesourcepath, illegal use of *"))
+                throw new Exception("expected output for path [" + sourcepath + "] not found");
+        }
+    }
+
+    private void generateModules(Path base, String... paths) throws IOException {
+        for (int i = 0; i < paths.length; i++) {
+            String moduleName = "m" + i;
+            String dependency = i > 0 ? "requires m" + (i - 1) + ";" : "";
+            tb.writeJavaFiles(base.resolve(paths[i]).resolve(moduleName),
+                    "module " + moduleName + " { " + dependency + " }",
+                    "package pkg" + i + "; class A { }");
+        }
+    }
+
+    private void checkFiles(Path... files) throws Exception {
+        for (Path file : files) {
+            if (!Files.exists(file)) {
+                throw new Exception("File not exists: " + file);
+            }
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModuleTestBase.java b/langtools/test/tools/javac/modules/ModuleTestBase.java
new file mode 100644
index 0000000..fc572f1
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModuleTestBase.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2013, 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.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+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.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+/**
+ * Base class for module tests.
+ */
+public class ModuleTestBase {
+    protected ToolBox tb;
+    protected PrintStream out;
+    private int errors;
+
+    /** Marker annotation for test methods to be invoked by runTests. */
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Test { }
+
+    /**
+     * Run all methods annotated with @Test, and throw an exception if any
+     * errors are reported..
+     *
+     * @throws Exception if any errors occurred
+     */
+    void runTests() throws Exception {
+        if (tb == null)
+            tb = new ToolBox();
+        out = System.err;
+
+        for (Method m: getClass().getDeclaredMethods()) {
+            Annotation a = m.getAnnotation(Test.class);
+            if (a != null) {
+                try {
+                    out.println("Running test " + m.getName());
+                    Path baseDir = Paths.get(m.getName());
+                    m.invoke(this, new Object[] { baseDir });
+                } catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
+                    error("Exception: " + e.getCause());
+                    cause.printStackTrace(out);
+                }
+                out.println();
+            }
+        }
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    // move to ToolBox?
+    // change returntyp to List<Path> -- means updating ToolBox methods
+    Path[] findJavaFiles(Path... paths) throws IOException {
+        Set<Path> files = new TreeSet<>();
+        for (Path p : paths) {
+            Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                        throws IOException {
+                    if (file.getFileName().toString().endsWith(".java")) {
+                        files.add(file);
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        }
+        return files.toArray(new Path[files.size()]);
+    }
+
+    void error(String message) {
+        out.println("Error: " + message);
+        errors++;
+    }
+
+    public class ModuleBuilder {
+
+        private final String name;
+        private String requires = "";
+        private String exports = "";
+        private String uses = "";
+        private String provides = "";
+        private String modulePath = "";
+        private List<String> content = new ArrayList<>();
+
+        public ModuleBuilder(String name) {
+            this.name = name;
+        }
+
+        public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
+            return requires("public " + requires, modulePath);
+        }
+
+        public ModuleBuilder requires(String requires, Path... modulePath) {
+            this.requires += "    requires " + requires + ";\n";
+            this.modulePath += Arrays.stream(modulePath)
+                    .map(Path::toString)
+                    .collect(Collectors.joining(File.pathSeparator));
+            return this;
+        }
+
+        public ModuleBuilder exportsTo(String pkg, String module) {
+            return exports(pkg + " to " + module);
+        }
+
+        public ModuleBuilder exports(String pkg) {
+            this.exports += "    exports " + pkg + ";\n";
+            return this;
+        }
+
+        public ModuleBuilder uses(String uses) {
+            this.uses += "    uses " + uses + ";\n";
+            return this;
+        }
+
+        public ModuleBuilder provides(String service, String implementation) {
+            this.provides += "    provides " + service + " with " + implementation + ";\n";
+            return this;
+        }
+
+        public ModuleBuilder classes(String... content) {
+            this.content.addAll(Arrays.asList(content));
+            return this;
+        }
+
+        public Path write(Path where) throws IOException {
+            Files.createDirectories(where);
+            List<String> sources = new ArrayList<>();
+            sources.add("module " + name + "{"
+                    + requires
+                    + exports
+                    + uses
+                    + provides
+                    + "}");
+            sources.addAll(content);
+            Path moduleSrc = where.resolve(name + "/src");
+            tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
+            return moduleSrc;
+        }
+
+        public void build(Path where) throws IOException {
+            Path moduleSrc = write(where);
+            tb.new JavacTask()
+                    .outdir(where.resolve(name))
+                    .options("-mp", modulePath)
+                    .files(findJavaFiles(moduleSrc))
+                    .run()
+                    .writeAll();
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java
new file mode 100644
index 0000000..acd3359
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java
@@ -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.
+ */
+
+/*
+ * @test
+ * @summary Ensure named modules cannot refer to classpath types.
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ModulesAndClassPathTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+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.TypeElement;
+
+public class ModulesAndClassPathTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new ModulesAndClassPathTest().runTests();
+    }
+
+    @Test
+    void testModulesAndClassPath(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { api.Api api; }");
+
+        List<String> modLog = tb.new JavacTask()
+                                .options("-classpath", jar.toString(),
+                                         "-XDrawDiagnostics")
+                                .outdir(classes)
+                                .files(findJavaFiles(moduleSrc))
+                                .run(ToolBox.Expect.FAIL)
+                                .writeAll()
+                                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
+                                              "1 error");
+
+        if (!expected.equals(modLog)) {
+            throw new Exception("unexpected output: " + modLog);
+        }
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString(),
+                   "-XaddReads:m1=ALL-UNNAMED")
+          .outdir(classes)
+          .files(findJavaFiles(moduleSrc))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString() + File.pathSeparator + System.getProperty("test.classes"),
+                   "-XaddReads:m1=ALL-UNNAMED",
+                   "-processor", ProcessorImpl.class.getName())
+          .outdir(classes)
+          .files(findJavaFiles(moduleSrc))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+    }
+
+    @Test
+    void testImplicitSourcePathModuleInfo(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { api.Api api; }");
+
+        List<String> modLog = tb.new JavacTask()
+                                .options("-classpath", jar.toString(),
+                                         "-sourcepath", m1.toString(),
+                                         "-XDrawDiagnostics")
+                                .outdir(classes)
+                                .files(m1.resolve("impl").resolve("Impl.java"))
+                                .run(ToolBox.Expect.FAIL)
+                                .writeAll()
+                                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
+                                              "1 error");
+
+        if (!expected.equals(modLog)) {
+            throw new Exception("unexpected output: " + modLog);
+        }
+    }
+
+    @Test
+    void testModuleInfoFromOutput(Path base) throws Exception {
+        Path jar = prepareTestJar(base);
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package impl; public class Impl { api.Api api; }");
+
+        tb.new JavacTask()
+          .options("-classpath", jar.toString(),
+                   "-XDrawDiagnostics")
+          .outdir(classes)
+          .files(m1.resolve("module-info.java"))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> modLog = tb.new JavacTask()
+                                .options("-classpath", jar.toString(),
+                                         "-XDrawDiagnostics")
+                                .outdir(classes)
+                                .files(m1.resolve("impl").resolve("Impl.java"))
+                                .run(ToolBox.Expect.FAIL)
+                                .writeAll()
+                                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("Impl.java:1:38: compiler.err.doesnt.exist: api",
+                                              "1 error");
+
+        if (!expected.equals(modLog)) {
+            throw new Exception("unexpected output: " + modLog);
+        }
+    }
+
+    private Path prepareTestJar(Path base) throws Exception {
+        Path legacySrc = base.resolve("legacy-src");
+        tb.writeJavaFiles(legacySrc,
+                          "package api; public abstract class Api {}");
+        Path legacyClasses = base.resolve("legacy-classes");
+        Files.createDirectories(legacyClasses);
+
+        String log = tb.new JavacTask()
+                .options()
+                .outdir(legacyClasses)
+                .files(findJavaFiles(legacySrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Path lib = base.resolve("lib");
+
+        Files.createDirectories(lib);
+
+        Path jar = lib.resolve("test-api-1.0.jar");
+
+        tb.new JarTask(jar)
+          .baseDir(legacyClasses)
+          .files("api/Api.class")
+          .run();
+
+        return jar;
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static class ProcessorImpl extends AbstractProcessor {
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            return false;
+        }
+    }
+
+    @Test
+    void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports impl; }",
+                          "package impl; public class Impl { }",
+                          "package src; public class Src { }",
+                          "package test; public class TestCP extends impl.Impl { }",
+                          "package test; public class TestSP extends src.Src { }");
+
+        tb.new JavacTask()
+          .outdir(classes)
+          .files(m1.resolve("impl").resolve("Impl.java"))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        tb.new JavacTask()
+          .outdir(classes)
+          .files(m1.resolve("module-info.java"))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        tb.new JavacTask()
+          .outdir(classes)
+          .files(m1.resolve("test").resolve("TestCP.java"))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        tb.new JavacTask()
+          .options("-sourcepath", m1.toString())
+          .outdir(classes)
+          .files(m1.resolve("test").resolve("TestSP.java"))
+          .run()
+          .writeAll()
+          .getOutputLines(ToolBox.OutputKind.DIRECT);
+    }
+}
diff --git a/langtools/test/tools/javac/modules/MultiModuleModeTest.java b/langtools/test/tools/javac/modules/MultiModuleModeTest.java
new file mode 100644
index 0000000..d3e3057
--- /dev/null
+++ b/langtools/test/tools/javac/modules/MultiModuleModeTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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 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.javap
+ * @build ToolBox ModuleTestBase
+ * @run main MultiModuleModeTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MultiModuleModeTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new MultiModuleModeTest().runTests();
+    }
+
+    @Test
+    void testDuplicateModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2, "module m1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:1: compiler.err.duplicate.module: m1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testCantFindModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m1 { }");
+        Path misc = base.resolve("misc");
+        tb.writeJavaFiles(misc, "package p; class C { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(join(findJavaFiles(src), findJavaFiles(misc)))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:1: compiler.err.unnamed.pkg.not.allowed.named.modules"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testModuleNameMismatch(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1, "module m2 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:8: compiler.err.module.name.mismatch: m2, m1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testImplicitModuleSource(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
+        tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(src.resolve("m2/module-info.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleClass(Path base) throws Exception {
+        Path src1 = base.resolve("src1");
+        tb.writeJavaFiles(src1.resolve("m1"), "module m1 { }");
+        Path modules1 = base.resolve("modules1");
+        Files.createDirectories(modules1);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src1.toString())
+                .outdir(modules1)
+                .files(src1.resolve("m1/module-info.java"))
+                .run()
+                .writeAll();
+
+        Path src2= base.resolve("src2");
+        tb.writeJavaFiles(src2.resolve("m2"), "module m2 { requires m1; }");
+        Path modules2 = base.resolve("modules2");
+        Files.createDirectories(modules2);
+
+        tb.new JavacTask()
+                .options("-modulepath", modules1.toString(),
+                        "-modulesourcepath", src2.toString())
+                .outdir(modules2)
+                .files(src2.resolve("m2/module-info.java"))
+                .run()
+                .writeAll();
+    }
+
+    Path[] join(Path[] a, Path[] b) {
+        List<Path> result = new ArrayList<>();
+        result.addAll(Arrays.asList(a));
+        result.addAll(Arrays.asList(b));
+        return result.toArray(new Path[result.size()]);
+    }
+}
diff --git a/langtools/test/tools/javac/modules/NPEEmptyFileTest.java b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java
new file mode 100644
index 0000000..c1aa1aa
--- /dev/null
+++ b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary NPE while compiling empty javafile with -modulesourcepath option
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main NPEEmptyFileTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class NPEEmptyFileTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new NPEEmptyFileTest().runTests();
+    }
+
+    @Test
+    void compileEmptyFile(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+        Path emptyJavaFile = base.resolve("Test.java");
+        tb.writeFile(emptyJavaFile, "");
+        tb.new JavacTask(ToolBox.Mode.EXEC)
+                .options("-modulesourcepath", modules.toString(),
+                        "-d", modules.toString(), emptyJavaFile.toString())
+                .run()
+                .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/modules/OutputDirTest.java b/langtools/test/tools/javac/modules/OutputDirTest.java
new file mode 100644
index 0000000..96f6a61
--- /dev/null
+++ b/langtools/test/tools/javac/modules/OutputDirTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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 tests for output directory
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main OutputDirTest
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class OutputDirTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new OutputDirTest().run();
+    }
+
+    Path src;
+
+    void run() throws Exception {
+        tb = new ToolBox();
+
+        src = Paths.get("src");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m { }",
+                "package p; class C { }");
+
+        runTests();
+    }
+
+    @Test
+    void testError(Path base) throws Exception {
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.no.output.dir"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testProcOnly(Path base) throws IOException {
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-proc:only",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testClassOutDir(Path base) throws IOException {
+        Path classes = base.resolve("classes");
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-d", classes.toString(),
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testExplodedOutDir(Path base) throws Exception {
+        Path modSrc = base.resolve("modSrc");
+        tb.writeJavaFiles(modSrc,
+                "module m1 { exports p; }",
+                "package p; public class CC { }");
+        Path modClasses = base.resolve("modClasses");
+        Files.createDirectories(modClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(modClasses)
+                .files(findJavaFiles(modSrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        Path src_m = src.resolve("m");
+        tb.writeJavaFiles(src_m,
+                "module m { requires m1 ; }",
+                "class C { }");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(modClasses) // an exploded module
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.err.multi-module.outdir.cannot.be.exploded.module: " + modClasses.toString()))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testInExplodedOutDir(Path base) throws Exception {
+        Path modSrc = base.resolve("modSrc");
+        tb.writeJavaFiles(modSrc,
+                "module m1 { exports p; }",
+                "package p; public class CC { }");
+        Path modClasses = base.resolve("modClasses");
+        Files.createDirectories(modClasses);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(modClasses)
+                .files(findJavaFiles(modSrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires m1 ; }",
+                "class C { }");
+
+        Path classes = modClasses.resolve("m");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .outdir(classes) // within an exploded module
+                .options("-XDrawDiagnostics",
+                        "-Xlint", "-Werror",
+                        "-modulepath", modClasses.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.warn.outdir.is.in.exploded.module: " + classes.toString()))
+            throw new Exception("expected output not found");
+    }
+}
diff --git a/langtools/test/tools/javac/modules/PackageConflictTest.java b/langtools/test/tools/javac/modules/PackageConflictTest.java
new file mode 100644
index 0000000..8e90039
--- /dev/null
+++ b/langtools/test/tools/javac/modules/PackageConflictTest.java
@@ -0,0 +1,274 @@
+/*
+ * 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 test module/package conflicts
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main PackageConflictTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class PackageConflictTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        PackageConflictTest t = new PackageConflictTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "package java.util; public class MyList { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("MyList.java:1:1: compiler.err.package.in.other.module: java.base"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testDisjoint(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m1,
+                          "module m1 { }",
+                          "package test; public class A { }");
+        tb.writeJavaFiles(m2,
+                          "module m2 { }",
+                          "package test; public class B { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+          .options("-Werror", "-modulesourcepath", base.toString())
+          .outdir(classes)
+          .files(findJavaFiles(base))
+          .run()
+          .writeAll();
+    }
+
+    @Test
+    void testConflictInDependencies(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        Path m2 = base.resolve("m2");
+        Path m3 = base.resolve("m3");
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports test; }",
+                          "package test; public class A { }");
+        tb.writeJavaFiles(m2,
+                          "module m2 { exports test; }",
+                          "package test; public class B { }");
+        tb.writeJavaFiles(m3,
+                          "module m3 { requires m1; requires m2; }",
+                          "package impl; public class Impl { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                       .options("-XDrawDiagnostics", "-modulesourcepath", base.toString())
+                       .outdir(classes)
+                       .files(findJavaFiles(base))
+                       .run(ToolBox.Expect.FAIL)
+                       .writeAll()
+                       .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected =
+                Arrays.asList("module-info.java:1:1: compiler.err.package.clash.from.requires: m3, test, m1, m2",
+                              "1 error");
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    void testSimple2(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("N")
+                .exports("pack")
+                .classes("package pack; public class A { }")
+                .build(modules);
+        new ModuleBuilder("M")
+                .requires("N")
+                .classes("package pack; public class B { pack.A f; }")
+                .write(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-mp", modules.toString())
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules.resolve("M")))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("B.java:1:1: compiler.err.package.in.other.module: N"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testPrivateConflict(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("N")
+                .exports("publ")
+                .classes("package pack; public class A { }")
+                .classes("package publ; public class B { }")
+                .write(modules);
+        new ModuleBuilder("M")
+                .requires("N")
+                .classes("package pack; public class C { publ.B b; }")
+                .write(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", modules + "/*/src")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains(""))
+            throw new Exception("unexpected output not found");
+
+    }
+
+    @Test
+    void testPrivateConflictOnModulePath(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("N")
+                .exports("publ")
+                .classes("package pack; public class A { }")
+                .classes("package publ; public class B { }")
+                .build(modules);
+        new ModuleBuilder("M")
+                .requires("N")
+                .classes("package pack; public class C { publ.B b; }")
+                .write(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-mp", modules.toString())
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules.resolve("M")))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains(""))
+            throw new Exception("expected output not found");
+
+    }
+
+    @Test
+    void testRequiresConflictExports(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("M")
+                .exports("pack")
+                .classes("package pack; public class A { }")
+                .build(modules);
+        new ModuleBuilder("N")
+                .exports("pack")
+                .classes("package pack; public class B { }")
+                .build(modules);
+        new ModuleBuilder("K")
+                .requires("M")
+                .requires("N")
+                .classes("package pkg; public class C { pack.A a; pack.B b; }")
+                .write(modules);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-mp", modules.toString())
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules.resolve("K")))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected =
+                Arrays.asList("module-info.java:1:1: compiler.err.package.clash.from.requires: K, pack, M, N",
+                        "1 error");
+        if (!log.containsAll(expected))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testQulifiedExportsToDifferentModules(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("U").write(modules);
+        new ModuleBuilder("M")
+                .exports("pkg to U")
+                .classes("package pkg; public class A { public static boolean flagM; }")
+                .write(modules);
+        new ModuleBuilder("N")
+                .exports("pkg to K")
+                .classes("package pkg; public class A { public static boolean flagN; }")
+                .write(modules);
+        ModuleBuilder moduleK = new ModuleBuilder("K");
+        moduleK.requires("M")
+                .requires("N")
+                .classes("package p; public class DependsOnN { boolean f = pkg.A.flagN; } ")
+                .write(modules);
+        tb.new JavacTask()
+                .options("-modulesourcepath", modules + "/*/src")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules.resolve("K")))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+        //negative case
+        moduleK.classes("package pkg; public class DuplicatePackage { } ")
+                .classes("package p; public class DependsOnM { boolean f = pkg.A.flagM; } ")
+                .write(modules);
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", modules + "/*/src")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules.resolve("K")))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "DependsOnM.java:1:55: compiler.err.cant.resolve.location: kindname.variable, flagM, , , (compiler.misc.location: kindname.class, pkg.A, null)");
+        if (!output.containsAll(expected)) {
+            throw new Exception("expected output not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/PackageMultipleModules.java b/langtools/test/tools/javac/modules/PackageMultipleModules.java
new file mode 100644
index 0000000..d8a3b07
--- /dev/null
+++ b/langtools/test/tools/javac/modules/PackageMultipleModules.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Verify modules can contain packages of the same name, unless these meet.
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main PackageMultipleModules
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class PackageMultipleModules extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        PackageMultipleModules t = new PackageMultipleModules();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m1,
+                          "module m1 {}",
+                          "package test; import test.B; public class A {}",
+                          "package test; public class A1 extends A {}");
+        tb.writeJavaFiles(m2,
+                          "module m2 {}",
+                          "package test; import test.A; public class B {}",
+                          "package test; public class B1 extends B {}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", base.toString())
+                .outdir(classes)
+                .files(findJavaFiles(base))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("A.java:1:26: compiler.err.not.def.access.package.cant.access: test.B, test",
+                                              "B.java:1:26: compiler.err.not.def.access.package.cant.access: test.A, test",
+                                              "2 errors");
+        if (!log.equals(expected))
+            throw new Exception("expected output not found");
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/PluginsInModulesTest.java b/langtools/test/tools/javac/modules/PluginsInModulesTest.java
new file mode 100644
index 0000000..1e296a8
--- /dev/null
+++ b/langtools/test/tools/javac/modules/PluginsInModulesTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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 Verify that plugins inside modules works
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main PluginsInModulesTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class PluginsInModulesTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new PluginsInModulesTest().runTests();
+    }
+
+    private static final String pluginModule1 =
+            "module pluginMod1 {\n" +
+            "    requires jdk.compiler;\n" +
+            "\n" +
+            "    provides com.sun.source.util.Plugin\n" +
+            "      with mypkg1.SimplePlugin1;\n" +
+            "}";
+
+    private static final String plugin1 =
+            "package mypkg1;\n" +
+            "import com.sun.source.util.JavacTask;\n" +
+            "import com.sun.source.util.Plugin;\n" +
+            "import com.sun.source.util.TaskEvent;\n" +
+            "import com.sun.source.util.TaskListener;\n" +
+            "\n" +
+            "public class SimplePlugin1 implements Plugin {\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public String getName() {\n" +
+            "        return \"simpleplugin1\";\n" +
+            "    }\n" +
+            "\n" +
+            "    @Override\n" +
+            "    public void init(JavacTask task, String... args) {\n" +
+            "        task.addTaskListener(new PostAnalyzeTaskListener());\n" +
+            "    }\n" +
+            "\n" +
+            "    private static class PostAnalyzeTaskListener implements TaskListener {\n" +
+            "        @Override\n" +
+            "        public void started(TaskEvent taskEvent) { \n" +
+            "            if (taskEvent.getKind().equals(TaskEvent.Kind.COMPILATION)) {\n" +
+            "                System.out.println(\"simpleplugin1 started for event \" + taskEvent.getKind());\n" +
+            "            }\n" +
+            "        }\n" +
+            "\n" +
+            "        @Override\n" +
+            "        public void finished(TaskEvent taskEvent) {\n" +
+            "            if (taskEvent.getKind().equals(TaskEvent.Kind.COMPILATION)) {\n" +
+            "                System.out.println(\"simpleplugin1 finished for event \" + taskEvent.getKind());\n" +
+            "            }\n" +
+            "        }\n" +
+            "    }\n" +
+            "}";
+
+    private static final String testClass = "class Test { }";
+
+    void initialization(Path base) throws Exception {
+        moduleSrc = base.resolve("plugin_mods_src");
+        Path pluginMod1 = moduleSrc.resolve("pluginMod1");
+
+        processorCompiledModules = base.resolve("mods");
+
+        Files.createDirectories(processorCompiledModules);
+
+        tb.writeJavaFiles(
+                pluginMod1,
+                pluginModule1,
+                plugin1);
+
+        String log = tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(processorCompiledModules)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        classes = base.resolve("classes");
+        Files.createDirectories(classes);
+    }
+
+    Path processorCompiledModules;
+    Path moduleSrc;
+    Path classes;
+
+    @Test
+    void testUseOnlyOneProcessor(Path base) throws Exception {
+        initialization(base);
+        List<String> log = tb.new JavacTask()
+                .options("-processormodulepath", processorCompiledModules.toString(),
+                        "-Xplugin:simpleplugin1")
+                .outdir(classes)
+                .sources(testClass)
+                .run()
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.STDOUT);
+        if (!log.equals(Arrays.asList("simpleplugin1 started for event COMPILATION",
+                                      "simpleplugin1 finished for event COMPILATION"))) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ProvidesTest.java b/langtools/test/tools/javac/modules/ProvidesTest.java
new file mode 100644
index 0000000..33d15b2
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java
@@ -0,0 +1,433 @@
+/*
+ * 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 simple tests of module provides
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ProvidesTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class ProvidesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ProvidesTest t = new ProvidesTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; provides p1.C1 with p2.C2; }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+
+    }
+
+    @Test
+    void testMissingWith(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.C; }",
+                "package p; public class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:24: compiler.err.expected: 'with'"))
+            throw new Exception("expected output not found");
+
+    }
+
+    @Test
+    void testDuplicateProvides(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostic")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll();
+    }
+
+    @Test
+    void testMissingService(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.Missing with p.C; }",
+                "package p; public class C extends p.Missing { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "C.java:1:36: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)",
+                "module-info.java:1:22: compiler.err.cant.resolve.location: kindname.class, Missing, , , (compiler.misc.location: kindname.package, p, null)",
+                "module-info.java:1:37: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: <any>",
+                "3 errors");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testProvidesFromAnotherModule(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        tb.writeJavaFiles(modules.resolve("M"),
+                "module M { exports p; }",
+                "package p; public class Service { }");
+        tb.writeJavaFiles(modules.resolve("L"),
+                "module L { requires M; provides p.Service with p.Service; }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", modules.toString())
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(modules))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:24: compiler.err.service.implementation.not.in.right.module: M",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+
+    }
+
+    @Test
+    void testServiceIsNotImplemented(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.A with p.B; }",
+                "package p; public class A { }",
+                "package p; public class B { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:31: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: p.B, p.A)",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testMissingImplementation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.C with p.Impl; }",
+                "package p; public class C { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:31: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.package, p, null)",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testSeveralImplementations(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
+                "package p; public class C { }",
+                "package p; public class Impl1 extends p.C { }",
+                "package p; public class Impl2 extends p.C { }");
+
+        tb.new JavacTask()
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testOneImplementationsForServices(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }",
+                "package p; public interface Service1 { }",
+                "package p; public abstract class Service2 { }",
+                "package p; public class Impl extends p.Service2 implements p.Service1 { }");
+
+        tb.new JavacTask()
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testAbstractImplementation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public abstract class C2 extends p1.C1 { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:34: compiler.err.service.implementation.is.abstract: p2.C2");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testInterfaceImplementation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.Service with p2.Impl; }",
+                "package p1; public interface Service { }",
+                "package p2; public interface Impl extends p1.Service { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:39: compiler.err.service.implementation.is.abstract: p2.Impl");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testProtectedImplementation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; class C2 extends p1.C1 { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:34: compiler.err.not.def.public.cant.access: p2.C2, p2",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testNoNoArgConstructor(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { public C2(String str) { } }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:46: compiler.err.service.implementation.doesnt.have.a.no.args.constructor: p2.C2");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testPrivateNoArgConstructor(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { private C2() { } }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:46: compiler.err.service.implementation.no.args.constructor.not.public: p2.C2");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testServiceIndirectlyImplemented(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C3; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 {  }",
+                "package p2; public class C3 extends p2.C2 {  }");
+
+        tb.new JavacTask()
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testServiceImplementationInnerClass(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2.Inner; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2  { public class Inner extends p1.C1 { } }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:37: compiler.err.service.implementation.is.inner: p2.C2.Inner");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testServiceDefinitionInnerClass(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1.InnerDefinition with p2.C2; }",
+                "package p1; public class C1 { public class InnerDefinition { } }",
+                "package p2; public class C2 extends p1.C1.InnerDefinition { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:26: compiler.err.service.definition.is.inner: p1.C1.InnerDefinition",
+                "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p1.C1.InnerDefinition",
+                "C2.java:1:20: compiler.err.encl.class.required: p1.C1.InnerDefinition",
+                "2 errors",
+                "1 warning");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/QueryBeforeEnter.java b/langtools/test/tools/javac/modules/QueryBeforeEnter.java
new file mode 100644
index 0000000..a55758f
--- /dev/null
+++ b/langtools/test/tools/javac/modules/QueryBeforeEnter.java
@@ -0,0 +1,434 @@
+/*
+ * 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 module resolution
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main QueryBeforeEnter
+ */
+
+import java.io.File;
+import java.io.OutputStream;
+import java.nio.file.*;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.Plugin;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.Main;
+
+public class QueryBeforeEnter extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        QueryBeforeEnter t = new QueryBeforeEnter();
+        t.runTests();
+    }
+
+    @Test
+    void testEmpty(Path base) throws Exception {
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        JavacTask task = (JavacTask) javaCompiler.getTask(null, null, null, null, null, null);
+        TypeElement jlString = task.getElements().getTypeElement("java.lang.String");
+
+        assertNotNull(jlString);
+    }
+
+    @Test
+    void testUnnamed(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports m1; }",
+                          "package m1; public class M1 {}");
+
+        Path m2 = moduleSrc.resolve("m2");
+
+        tb.writeJavaFiles(m2,
+                          "module m2 { exports m2; }",
+                          "package m2; public class M2 {}");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+
+        Path cpSrc = base.resolve("cp-src");
+
+        tb.writeJavaFiles(cpSrc,
+                          "package cp; public class CP {}");
+
+        Path cp = base.resolve("cp");
+
+        Files.createDirectories(cp);
+
+        tb.new JavacTask()
+                .outdir(cp)
+                .files(findJavaFiles(cpSrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+
+        tb.writeJavaFiles(src,
+                          "package test; public class Test1 {}",
+                          "package test; public class Test2 {}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            JavacTask task = (JavacTask) javaCompiler.getTask(null,
+                                                              null,
+                                                              d -> { throw new IllegalStateException(d.toString()); },
+                                                              Arrays.asList("-modulepath", modulePath.toString(),
+                                                                            "-classpath", cp.toString(),
+                                                                            "-sourcepath", src.toString()),
+                                                              null,
+                                                              fm.getJavaFileObjects(src.resolve("test").resolve("Test2.java")));
+            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
+            assertNotNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
+            assertNull(task.getElements().getTypeElement("m1.M1"));
+            assertNull(task.getElements().getTypeElement("m2.M2"));
+            assertNotNull(task.getElements().getTypeElement("cp.CP"));
+            assertNotNull(task.getElements().getTypeElement("test.Test1"));
+            assertNotNull(task.getElements().getTypeElement("test.Test2"));
+            assertNotNull(task.getElements().getModuleElement("java.base"));
+            assertNotNull(task.getElements().getModuleElement("java.compiler"));
+            assertNull(task.getElements().getModuleElement("m1"));
+            assertNull(task.getElements().getModuleElement("m2"));
+        }
+    }
+
+    @Test
+    void testSingleNamed(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports m1; }",
+                          "package m1; public class M1 {}");
+
+        Path m2 = moduleSrc.resolve("m2");
+
+        tb.writeJavaFiles(m2,
+                          "module m2 { exports m2; }",
+                          "package m2; public class M2 {}");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+
+        Path cpSrc = base.resolve("cp-src");
+
+        tb.writeJavaFiles(cpSrc,
+                          "package cp; public class CP {}");
+
+        Path cp = base.resolve("cp");
+
+        Files.createDirectories(cp);
+
+        tb.new JavacTask()
+                .outdir(cp)
+                .files(findJavaFiles(cpSrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+
+        tb.writeJavaFiles(src,
+                          "module test { requires java.base; requires m1; } ",
+                          "package test; public class Test {}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            JavacTask task = (JavacTask) javaCompiler.getTask(null,
+                                                              null,
+                                                              d -> { throw new IllegalStateException(d.toString()); },
+                                                              Arrays.asList("-modulepath", modulePath.toString(),
+                                                                            "-classpath", cp.toString(),
+                                                                            "-sourcepath", src.toString()),
+                                                              null,
+                                                              fm.getJavaFileObjects(findJavaFiles(src)));
+            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
+            assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
+            assertNotNull(task.getElements().getTypeElement("m1.M1"));
+            assertNull(task.getElements().getTypeElement("m2.M2"));
+            assertNotNull(task.getElements().getTypeElement("test.Test"));
+            assertNotNull(task.getElements().getModuleElement("java.base"));
+            assertNull(task.getElements().getModuleElement("java.compiler"));
+            assertNotNull(task.getElements().getModuleElement("m1"));
+            assertNull(task.getElements().getModuleElement("m2"));
+            assertNotNull(task.getElements().getModuleElement("test"));
+        }
+    }
+
+    @Test
+    void testMultiModule(Path base) throws Exception {
+        Path modulePathSrc = base.resolve("module-path-src");
+        Path m1 = modulePathSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports m1; }",
+                          "package m1; public class M1 {}");
+
+        Path m2 = modulePathSrc.resolve("m2");
+
+        tb.writeJavaFiles(m2,
+                          "module m2 { exports m2; }",
+                          "package m2; public class M2 {}");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", modulePathSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(modulePathSrc))
+                .run()
+                .writeAll();
+
+        Path cpSrc = base.resolve("cp-src");
+
+        tb.writeJavaFiles(cpSrc,
+                          "package cp; public class CP {}");
+
+        Path cp = base.resolve("cp");
+
+        Files.createDirectories(cp);
+
+        tb.new JavacTask()
+                .outdir(cp)
+                .files(findJavaFiles(cpSrc))
+                .run()
+                .writeAll();
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m3 = moduleSrc.resolve("m3");
+
+        tb.writeJavaFiles(m3,
+                          "module m3 { requires m1; exports m3; }",
+                          "package m3; public class M3 {  }");
+
+        Path m4 = moduleSrc.resolve("m4");
+
+        tb.writeJavaFiles(m4,
+                          "module m4 { exports m4; }",
+                          "package m4; public class M4 {}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            JavacTask task = (JavacTask) javaCompiler.getTask(null,
+                                                              null,
+                                                              d -> { throw new IllegalStateException(d.toString()); },
+                                                              Arrays.asList("-modulepath", modulePath.toString(),
+                                                                            "-classpath", cp.toString(),
+                                                                            "-modulesourcepath", moduleSrc.toString(),
+                                                                            "-d", out.toString()),
+                                                              null,
+                                                              fm.getJavaFileObjects(findJavaFiles(moduleSrc)));
+            assertNotNull(task.getElements().getTypeElement("java.lang.String"));
+            assertNull(task.getElements().getTypeElement("javax.tools.ToolProvider"));
+            assertNotNull(task.getElements().getTypeElement("m1.M1"));
+            assertNull(task.getElements().getTypeElement("m2.M2"));
+            assertNotNull(task.getElements().getTypeElement("m3.M3"));
+            assertNotNull(task.getElements().getTypeElement("m4.M4"));
+            assertNotNull(task.getElements().getModuleElement("java.base"));
+            assertNull(task.getElements().getModuleElement("java.compiler"));
+            assertNotNull(task.getElements().getModuleElement("m1"));
+            assertNull(task.getElements().getModuleElement("m2"));
+            assertNotNull(task.getElements().getModuleElement("m3"));
+            assertNotNull(task.getElements().getModuleElement("m4"));
+        }
+    }
+
+    @Test
+    void testTooSoon(Path base) throws Exception {
+        Path src = base.resolve("src");
+
+        tb.writeJavaFiles(src,
+                          "package test; public class Test {}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        Path reg = base.resolve("reg");
+        Path regFile = reg.resolve("META-INF").resolve("services").resolve(Plugin.class.getName());
+
+        Files.createDirectories(regFile.getParent());
+
+        try (OutputStream regOut = Files.newOutputStream(regFile)) {
+            regOut.write(PluginImpl.class.getName().getBytes());
+        }
+
+        String processorPath = System.getProperty("test.class.path") + File.pathSeparator + reg.toString();
+
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        Path testSource = src.resolve("test").resolve("Test.java");
+        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+            JavacTask task = (JavacTask) javaCompiler.getTask(null,
+                                                              null,
+                                                              d -> { throw new IllegalStateException(d.toString()); },
+                                                              Arrays.asList("-processorpath", processorPath,
+                                                                            "-processor", AP.class.getName(),
+                                                                            "-Xplugin:test"),
+                                                              null,
+                                                              fm.getJavaFileObjects(testSource));
+            task.call();
+        }
+
+        Main.compile(new String[] {"-processorpath", processorPath,
+                                   "-Xplugin:test",
+                                   testSource.toString()});
+    }
+
+    public static class PluginImpl implements Plugin {
+
+        @Override
+        public String getName() {
+            return "test";
+        }
+
+        @Override
+        public void init(JavacTask task, String... args) {
+            task.addTaskListener(new TaskListener() {
+                boolean wasEntered;
+                @Override
+                public void started(TaskEvent e) {
+                    switch (e.getKind()) {
+                        case COMPILATION: case PARSE:
+                            shouldFail(e.getKind());
+                            break;
+                        case ANNOTATION_PROCESSING: case ENTER:
+                            if (wasEntered) {
+                                shouldPass(e.getKind());
+                            } else {
+                                shouldFail(e.getKind());
+                            }
+                            break;
+                        default:
+                            shouldPass(e.getKind());
+                            break;
+                    }
+                }
+                @Override
+                public void finished(TaskEvent e) {
+                    switch (e.getKind()) {
+                        case PARSE:
+                            shouldFail(e.getKind());
+                            break;
+                        case ENTER:
+                            wasEntered = true;
+                            //fall-through:
+                        default:
+                            shouldPass(e.getKind());
+                            break;
+                    }
+                }
+                private void shouldFail(TaskEvent.Kind kind) {
+                    try {
+                        task.getElements().getTypeElement("java.lang.String");
+                        throw new AssertionError("Expected exception not observed; kind=" + kind.name());
+                    } catch (IllegalStateException ex) {
+                        //correct
+                    }
+                }
+                private void shouldPass(TaskEvent.Kind kind) {
+                    assertNotNull(task.getElements().getTypeElement("java.lang.String"));
+                }
+            });
+
+        }
+
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class AP extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+
+    private static void assertNotNull(Object actual) {
+        if (actual == null) {
+            throw new AssertionError("unexpected null!");
+        }
+    }
+
+    private static void assertNull(Object actual) {
+        if (actual != null) {
+            throw new AssertionError("unexpected non null!");
+        }
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java
new file mode 100644
index 0000000..286a75c
--- /dev/null
+++ b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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 8145012
+ * @summary Javac doesn't report errors on duplicate uses or provides
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main RepeatedUsesAndProvidesTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class RepeatedUsesAndProvidesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        RepeatedUsesAndProvidesTest t = new RepeatedUsesAndProvidesTest();
+        t.runTests();
+    }
+
+    @Test
+    void testDuplicateUses(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p1.C1; uses p1.C1; }",
+                "package p1; public class C1 {}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:24: compiler.err.duplicate.uses: p1.C1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testDuplicateProvides(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 {}",
+                "package p2; public class C2 extends p1.C1 {}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:39: 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
new file mode 100644
index 0000000..7af9571
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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 8144342 8149658
+ * @summary javac doesn't report errors if module exports non-existent package
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ReportNonExistentPackageTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class ReportNonExistentPackageTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ReportNonExistentPackageTest t = new ReportNonExistentPackageTest();
+        t.runTests();
+    }
+
+    @Test
+    void testExportUnknownPackage(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m { exports p1; }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:20: compiler.err.package.empty.or.not.found: p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExportEmptyPackage(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { exports p1; }",
+                "package p1;");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:20: compiler.err.package.empty.or.not.found: p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m { exports p1; }");
+        Path p1 = src.resolve("p1");
+        Path C = p1.resolve("C.java");
+        tb.writeFile(C, "// comment");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:20: compiler.err.package.empty.or.not.found: p1"))
+            throw new Exception("expected output not found");
+    }
+}
diff --git a/langtools/test/tools/javac/modules/RequiresPublicTest.java b/langtools/test/tools/javac/modules/RequiresPublicTest.java
new file mode 100644
index 0000000..61a1614
--- /dev/null
+++ b/langtools/test/tools/javac/modules/RequiresPublicTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for "requires public"
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main RequiresPublicTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class RequiresPublicTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        RequiresPublicTest t = new RequiresPublicTest();
+        t.runTests();
+    }
+
+    @Test
+    void testJavaSE_OK(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires java.se; }",
+                "import java.awt.Frame;\n"  // in java.se
+                + "class Test {\n"
+                + "    Frame f;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testJavaSE_Fail(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires 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 = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .outdir(classes.toString()) // should allow Path here
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.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
+    void testComplex_OK(Path base) throws Exception {
+        Path src = getComplexSrc(base, "", "");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testComplex_Fail(Path base) throws Exception {
+        Path src = getComplexSrc(base,
+                "import p5.C5; import p6.C6; import p7.C7;\n",
+                "C5 c5; C6 c6; C7 c7;\n");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulesourcepath", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.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: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)"
+        };
+
+        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
+     *              -> m6 => m7
+     * where -> is requires, => is requires public
+     */
+    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 public m3;\n"
+                + "  requires        m6;\n"
+                + "  exports p2;\n"
+                + "}",
+                "package p2;\n"
+                + "public class C2 { }\n");
+
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                "module m3 { requires public m4; exports p3; }",
+                "package p3;\n"
+                + "public class C3 { }\n");
+
+        Path src_m4 = src.resolve("m4");
+        tb.writeJavaFiles(src_m4,
+                "module m4 { requires m5; exports p4; }",
+                "package p4;\n"
+                + "public class C4 { }\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 public m7; exports p6; }",
+                "package p6;\n"
+                + "public class C6 { }\n");
+
+        Path src_m7 = src.resolve("m7");
+        tb.writeJavaFiles(src_m7,
+                "module m7 { exports p7; }",
+                "package p7;\n"
+                + "public class C7 { }\n");
+
+        return src;
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ResolveTest.java b/langtools/test/tools/javac/modules/ResolveTest.java
new file mode 100644
index 0000000..03d1748
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ResolveTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary tests for module resolution
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ResolveTest
+ */
+
+import java.nio.file.*;
+
+public class ResolveTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ResolveTest t = new ResolveTest();
+        t.runTests();
+    }
+
+    @Test
+    void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class C { D d; }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:11: compiler.err.cant.resolve.location: "
+                + "kindname.class, D, , , (compiler.misc.location: kindname.class, C, null)"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testMissingSimpleTypeNamedModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { D d; }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:11: compiler.err.cant.resolve.location: "
+                + "kindname.class, D, , , (compiler.misc.location: kindname.class, C, null)"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testUnexportedTypeUnreadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testUnexportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1 to m3; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        tb.writeJavaFiles(src.resolve("m3"),
+                "module m3 { requires m1; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExportedTypeUnreadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("C2.java:1:33: compiler.err.not.def.access.package.cant.access: p1.C1, p1"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testExportedTypeReadableModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testExportedTypeReadableModule2(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1 to m2; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; }",
+                "package p2; public class C2 { p1.C1 c; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java
new file mode 100644
index 0000000..8b262ad
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8149033
+ * @summary ClassCastException in case of service implementation is nested static class
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ServiceInStaticClassErrorTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+public class ServiceInStaticClassErrorTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ServiceInStaticClassErrorTest t = new ServiceInStaticClassErrorTest();
+        t.runTests();
+    }
+
+    @Test
+    void testError(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.I with p1.Outer.A; }",
+                "package p1; public interface I {}",
+                "package p1; public class Outer { public static class A implements p1.I {} }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        List<String> output = tb.new JavacTask()
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java
new file mode 100644
index 0000000..54805b6
--- /dev/null
+++ b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8145013
+ * @summary Javac doesn't report warnings/errors if module provides unexported service and doesn't use it itself
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main ServiceProvidedButNotExportedOrUsedTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class ServiceProvidedButNotExportedOrUsedTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        ServiceProvidedButNotExportedOrUsedTest t = new ServiceProvidedButNotExportedOrUsedTest();
+        t.runTests();
+    }
+
+    @Test
+    void testWarning(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { provides p1.C1 with p2.C2; }",
+                "package p1; public class C1 { }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        List<String> output = tb.new JavacTask()
+                .outdir(classes)
+                .options("-Werror", "-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:12: compiler.warn.service.provided.but.not.exported.or.used: p1.C1",
+                "- compiler.err.warnings.and.werror",
+                "1 error",
+                "1 warning");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p1; }",
+                "package p1; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; requires m3; provides p1.C1 with p2.C2; }");
+        tb.writeJavaFiles(src.resolve("m3"),
+                "module m3 { requires m1; exports p2; }",
+                "package p2; public class C2 extends p1.C1 { }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:39: compiler.err.service.implementation.not.in.right.module: m3",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/SingleModuleModeTest.java b/langtools/test/tools/javac/modules/SingleModuleModeTest.java
new file mode 100644
index 0000000..030e16b
--- /dev/null
+++ b/langtools/test/tools/javac/modules/SingleModuleModeTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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 tests for single 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.javap
+ * @build ToolBox ModuleTestBase
+ * @run main SingleModuleModeTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+public class SingleModuleModeTest extends ModuleTestBase{
+
+    public static void main(String... args) throws Exception {
+        new SingleModuleModeTest().run();
+    }
+
+    void run() throws Exception {
+        tb = new ToolBox();
+
+        runTests();
+    }
+
+    @Test
+    void testTooManyModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
+        tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
+
+        String log = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("module-info.java:1:1: compiler.err.too.many.modules"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    void testImplicitModuleSource(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { }");
+
+        tb.new JavacTask()
+                .classpath(src)
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleClass(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(src.resolve("module-info.java"))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .classpath(classes)
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleClassAP(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses java.lang.Runnable; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(src.resolve("module-info.java"))
+                .run()
+                .writeAll();
+
+        tb.new JavacTask()
+                .options("-processor", VerifyUsesProvides.class.getName(),
+                         "-processorpath", System.getProperty("test.classes"))
+                .outdir(classes)
+                .classpath(classes)
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testImplicitModuleSourceAP(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses java.lang.Runnable; }",
+                "class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .options("-processor", VerifyUsesProvides.class.getName(),
+                         "-processorpath", System.getProperty("test.classes"))
+                .outdir(classes)
+                .sourcepath(src)
+                .classpath(classes)
+                .files(src.resolve("C.java"))
+                .run()
+                .writeAll();
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class VerifyUsesProvides extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            if (processingEnv.getElementUtils().getModuleElement("m") == null) {
+                throw new AssertionError();
+            }
+
+            return false;
+        }
+
+        @Override
+        public SourceVersion getSupportedSourceVersion() {
+            return SourceVersion.latest();
+        }
+
+    }
+}
diff --git a/langtools/test/tools/javac/modules/SubpackageTest.java b/langtools/test/tools/javac/modules/SubpackageTest.java
new file mode 100644
index 0000000..bc063c7
--- /dev/null
+++ b/langtools/test/tools/javac/modules/SubpackageTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary tests for subpackage issues
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main SubpackageTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SubpackageTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        SubpackageTest t = new SubpackageTest();
+        t.runTests();
+    }
+
+    @Test // based on JDK-8075435
+    void testUnnamedModule(Path base) throws Exception {
+        Path libsrc = base.resolve("lib/src");
+        tb.writeJavaFiles(libsrc,
+            "package p; public class E extends Error { }");
+        Path libclasses = base.resolve("lib/classes");
+        Files.createDirectories(libclasses);
+        tb.new JavacTask()
+                .outdir(libclasses)
+                .files(findJavaFiles(libsrc))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+            "package p.q;\n"
+            + "import p.E;\n"
+            + "class Test {\n"
+            + "  void m() { throw new E(); }\n"
+            + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .classpath(libclasses)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void testSimpleMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("mp"),
+                "module mp { exports p; }",
+                "package p; public class C1 { }");
+        tb.writeJavaFiles(src.resolve("mpq"),
+                "module mpq { exports p.q; }",
+                "package p.q; public class C2 { }");
+        tb.writeJavaFiles(src.resolve("mpqr"),
+                "module mpqr { exports p.q.r; }",
+                "package p.q.r; public class C3 { }");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m {"
+                + "  requires mp;\n"
+                + "  requires mpq;\n"
+                + "  requires mpqr;\n"
+                + "}",
+                "package x;\n"
+                + "class C {\n"
+                + "  p.C1 c1;\n"
+                + "  p.q.C2 c2;\n"
+                + "  p.q.r.C3 c3;\n"
+                + "}");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/UpgradeModulePathTest.java b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java
new file mode 100644
index 0000000..a2b255c
--- /dev/null
+++ b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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 tests for -upgrademodulepath
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main UpgradeModulePathTest
+ */
+
+import java.io.File;
+import java.nio.file.Path;
+
+public class UpgradeModulePathTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        UpgradeModulePathTest t = new UpgradeModulePathTest();
+        t.runTests();
+    }
+
+    @Test
+    void simpleUsage(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path upgradeModule = base.resolve("upgradeModule");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class E { }")
+                .build(upgradeModule);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-upgrademodulepath", upgradeModule.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void onlyUpgradeModulePath(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path upgradeModule = base.resolve("upgradeModule");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class E { }")
+                .build(upgradeModule);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-upgrademodulepath", upgradeModule + File.pathSeparator + module)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void withModuleSourcePath(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path upgradeModule = base.resolve("upgradeModule");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class E { }")
+                .build(upgradeModule);
+
+        final Path s = base.resolve("source");
+        tb.writeJavaFiles(s.resolve("m3"), "module m3 { }");
+
+        final Path upgradeModule3 = base.resolve("upgradeModule");
+        new ModuleBuilder("m3")
+                .exports("pkg3")
+                .classes("package pkg3; public class E { }")
+                .build(upgradeModule);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; requires m3; }",
+                "package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-modulesourcepath", src + File.pathSeparator + s,
+                        "-upgrademodulepath", upgradeModule + File.pathSeparator + upgradeModule3)
+                .outdir(module)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void sameUpgradeAndModulePath(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path upgradeModule = base.resolve("upgradeModule");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class E { }")
+                .build(upgradeModule);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", upgradeModule + File.pathSeparator + module,
+                        "-upgrademodulepath", upgradeModule.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    void dummyFileInUpgradeModulePath(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        Path dummy = base.resolve("dummy.txt");
+        tb.writeFile(dummy, "");
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.E.class.getName(); } }");
+
+        String output = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", module.toString(),
+                        "-upgrademodulepath", dummy.toString())
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!output.contains("compiler.err.illegal.argument.for.option: -upgrademodulepath, " + dummy)) {
+            throw new Exception("Expected output was not found");
+        }
+    }
+
+    @Test
+    void severalUpgradeModules(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class A { }")
+                .build(module);
+
+        new ModuleBuilder("m2")
+                .exports("pkg2")
+                .classes("package pkg2; public class B { }")
+                .build(module);
+
+        Path upgradeModule = base.resolve("upgradeModule");
+        new ModuleBuilder("m2")
+                .exports("pkg2")
+                .classes("package pkg2; public class BC { }")
+                .build(upgradeModule);
+        new ModuleBuilder("m3")
+                .exports("pkg3")
+                .classes("package pkg3; public class DC { }")
+                .build(upgradeModule);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m4 { requires m1; requires m2; requires m3; }",
+                "package p; class A { void main() { pkg1.A.class.getName(); pkg2.BC.class.getName(); pkg3.DC.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-upgrademodulepath", upgradeModule.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2, "module m4 { requires m1; }",
+                "package p; class A { void main() { pkg2.B.class.getName(); } }");
+
+        String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", module.toString(),
+                        "-upgrademodulepath", upgradeModule.toString())
+                .files(findJavaFiles(src2))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+        if (!log.contains("compiler.err.doesnt.exist: pkg2")) {
+            throw new Exception("Expected output was not found");
+        }
+    }
+
+    @Test
+    void severalUpgradeModulePathsLastWin(Path base) throws Exception {
+        final Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("pkg1")
+                .classes("package pkg1; public class E { }")
+                .build(module);
+
+        final Path upgradeModule1 = base.resolve("upgradeModule1");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class EC1 { }")
+                .build(upgradeModule1);
+
+        final Path upgradeModule2 = base.resolve("upgradeModule2");
+        new ModuleBuilder("m1")
+                .exports("pkg2")
+                .classes("package pkg2; public class EC2 { }")
+                .build(upgradeModule2);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.EC2.class.getName(); } }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-upgrademodulepath", upgradeModule1.toString(),
+                        "-upgrademodulepath", upgradeModule2.toString())
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2, "module m2 { requires m1; }",
+                "package p; class A { void main() { pkg2.EC1.class.getName(); } }");
+
+        final String log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", module.toString(),
+                        "-upgrademodulepath", upgradeModule1.toString(),
+                        "-upgrademodulepath", upgradeModule2.toString())
+                .files(findJavaFiles(src2))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.contains("compiler.err.cant.resolve.location: kindname.class, EC1, , , (compiler.misc.location: kindname.package, pkg2, null)")) {
+            throw new Exception("Expected output was not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/UsesTest.java b/langtools/test/tools/javac/modules/UsesTest.java
new file mode 100644
index 0000000..e768ecb
--- /dev/null
+++ b/langtools/test/tools/javac/modules/UsesTest.java
@@ -0,0 +1,266 @@
+/*
+ * 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 simple tests of module uses
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox ModuleTestBase
+ * @run main UsesTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public class UsesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        UsesTest t = new UsesTest();
+        t.runTests();
+    }
+
+    @Test
+    void testSimple(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.C; }",
+                "package p; public class C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testSimpleInner(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.C.Inner; }",
+                "package p; public class C { public class Inner { } }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testSimpleAnnotation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.C; }",
+                "package p; public @interface C { }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        tb.new JavacTask()
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testPrivateService(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.C.A; uses p.C; }",
+                "package p; public class C { protected class A { } }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:20: compiler.err.report.access: p.C.A, protected, p.C",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testMulti(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { exports p; }",
+                "package p; public class C { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; uses p.C; }");
+        Path modules = base.resolve("modules");
+        Files.createDirectories(modules);
+
+        tb.new JavacTask()
+                .options("-modulesourcepath", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testMultiOnModulePath(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("p")
+                .classes("package p; public class C { }")
+                .build(modules);
+        new ModuleBuilder("m2")
+                .requires("m1")
+                .uses("p.C")
+                .write(modules);
+
+        tb.new JavacTask()
+                .options("-mp", modules.toString())
+                .outdir(modules)
+                .files(findJavaFiles(modules.resolve("m2")))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testMultiOnModulePathInner(Path base) throws Exception {
+        Path modules = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .exports("p")
+                .classes("package p; public class C { public class Inner { } }")
+                .build(modules);
+        new ModuleBuilder("m2")
+                .requires("m1")
+                .uses("p.C.Inner")
+                .write(modules);
+
+        tb.new JavacTask()
+                .options("-mp", modules.toString())
+                .outdir(modules)
+                .files(findJavaFiles(modules.resolve("m2")))
+                .run(ToolBox.Expect.SUCCESS)
+                .writeAll();
+    }
+
+    @Test
+    void testDuplicateUses(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m"),
+                "module m { uses p.C; uses p.C; }",
+                "package p; public class C { }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        if (!output.containsAll(Arrays.asList(
+                "module-info.java:1:22: compiler.err.duplicate.uses: p.C"))) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testServiceNotExist(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { uses p.NotExist; }",
+                "package p; public class C { }");
+
+        List<String> output = tb.new JavacTask()
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+        Collection<?> expected = Arrays.asList("module-info.java:1:18: compiler.err.cant.resolve.location: kindname.class, NotExist, , , (compiler.misc.location: kindname.package, p, null)",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testUsesUnexportedService(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { }",
+                "package p; public class C { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; uses p.C; }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(Files.createDirectories(base.resolve("modules")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:32: compiler.err.not.def.access.package.cant.access: p.C, p",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+
+    @Test
+    void testUsesUnexportedButProvidedService(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                "module m1 { provides p.C with p.C; }",
+                "package p; public class C { }");
+        tb.writeJavaFiles(src.resolve("m2"),
+                "module m2 { requires m1; uses p.C; }");
+
+        List<String> output = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                .outdir(Files.createDirectories(base.resolve("modules")))
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:32: compiler.err.not.def.access.package.cant.access: p.C, p",
+                "1 error");
+        if (!output.containsAll(expected)) {
+            throw new Exception("Expected output not found");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/modules/XModuleTest.java b/langtools/test/tools/javac/modules/XModuleTest.java
new file mode 100644
index 0000000..3070962
--- /dev/null
+++ b/langtools/test/tools/javac/modules/XModuleTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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 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.javap
+ * @build ToolBox ModuleTestBase
+ * @run main XModuleTest
+ */
+
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class XModuleTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new XModuleTest().runTests();
+    }
+
+    @Test
+    void testCorrectXModule(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-Xmodule:java.compiler")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testSourcePath(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element, Other { }", "package javax.lang.model.element; interface Other { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-Xmodule:java.compiler", "-sourcepath", src.toString())
+                .outdir(classes)
+                .files(src.resolve("javax/lang/model/element/Extra.java"))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testClassPath(Path base) throws Exception {
+        Path cpSrc = base.resolve("cpSrc");
+        tb.writeJavaFiles(cpSrc, "package p; public interface Other { }");
+        Path cpClasses = base.resolve("cpClasses");
+        tb.createDirectories(cpClasses);
+
+        String cpLog = tb.new JavacTask()
+                .outdir(cpClasses)
+                .files(findJavaFiles(cpSrc))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!cpLog.isEmpty())
+            throw new Exception("expected output not found: " + cpLog);
+
+        Path src = base.resolve("src");
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element, p.Other { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = tb.new JavacTask()
+                .options("-Xmodule:java.compiler", "-classpath", cpClasses.toString())
+                .outdir(classes)
+                .files(src.resolve("javax/lang/model/element/Extra.java"))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testNoModuleInfoOnSourcePath(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "module java.compiler {}",
+                          "package javax.lang.model.element; public interface Extra { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-Xmodule:java.compiler")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.xmodule.sourcepath",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testNoModuleInfoInClassOutput(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path srcMod = base.resolve("src-mod");
+        tb.writeJavaFiles(srcMod,
+                          "module mod {}");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String logMod = tb.new JavacTask()
+                .options()
+                .outdir(classes)
+                .files(findJavaFiles(srcMod))
+                .run()
+                .writeAll()
+                .getOutput(ToolBox.OutputKind.DIRECT);
+
+        if (!logMod.isEmpty())
+            throw new Exception("unexpected output found: " + logMod);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "package javax.lang.model.element; public interface Extra { }");
+        tb.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-Xmodule:java.compiler")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("Extra.java:1:1: compiler.err.module-info.with.xmodule.classpath",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testModuleSourcePathXModule(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask()
+                .options("-XDrawDiagnostics", "-Xmodule:java.compiler", "-modulesourcepath", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("- compiler.err.xmodule.no.module.sourcepath",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testXModuleTooMany(Path base) throws Exception {
+        //note: avoiding use of java.base, as that gets special handling on some places:
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics", "-Xmodule:java.compiler", "-Xmodule:java.compiler")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("javac: option -Xmodule: can only be specified once",
+                                              "Usage: javac <options> <source files>",
+                                              "use -help for a list of possible options");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testWithModulePath(Path base) throws Exception {
+        Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .classes("package pkg1; public interface E { }")
+                .build(module);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; interface A extends pkg1.E { }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-Xmodule:m1")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        //checks module bounds still exist
+        new ModuleBuilder("m2")
+                .classes("package pkg2; public interface D { }")
+                .build(module);
+
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2, "package p; interface A extends pkg2.D { }");
+
+        List<String> log = tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "-modulepath", module.toString(),
+                        "-Xmodule:m1")
+                .files(findJavaFiles(src2))
+                .run(ToolBox.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(ToolBox.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("A.java:1:36: compiler.err.doesnt.exist: pkg2",
+                "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+    @Test
+    void testWithUpgradeModulePath(Path base) throws Exception {
+        Path module = base.resolve("modules");
+        new ModuleBuilder("m1")
+                .classes("package pkg1; public interface E { }")
+                .build(module);
+
+        Path upgrade = base.resolve("upgrade");
+        new ModuleBuilder("m1")
+                .classes("package pkg1; public interface D { }")
+                .build(upgrade);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "package p; interface A extends pkg1.D { }");
+
+        tb.new JavacTask(ToolBox.Mode.CMDLINE)
+                .options("-modulepath", module.toString(),
+                        "-upgrademodulepath", upgrade.toString(),
+                        "-Xmodule:m1")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/newlines/NewLineTest.java b/langtools/test/tools/javac/newlines/NewLineTest.java
index a6808d3..4534b46 100644
--- a/langtools/test/tools/javac/newlines/NewLineTest.java
+++ b/langtools/test/tools/javac/newlines/NewLineTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main NewLineTest
  */
diff --git a/langtools/test/tools/javac/options/modes/Tester.java b/langtools/test/tools/javac/options/modes/Tester.java
index 3e0a831..9423116 100644
--- a/langtools/test/tools/javac/options/modes/Tester.java
+++ b/langtools/test/tools/javac/options/modes/Tester.java
@@ -30,6 +30,7 @@
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.io.UncheckedIOException;
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -138,9 +139,10 @@
         } finally {
             try {
                 ((JavacFileManager) context.get(JavaFileManager.class)).close();
-                tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
             } catch (IOException e) {
+                throw new UncheckedIOException(e);
             }
+            tr.setLogs(sw.toString(), sysOut.close(), sysErr.close());
         }
         tr.setContext(context);
         tr.show();
diff --git a/langtools/test/tools/javac/options/xprefer/XPreferTest.java b/langtools/test/tools/javac/options/xprefer/XPreferTest.java
index a957d33..3cf9bd5 100644
--- a/langtools/test/tools/javac/options/xprefer/XPreferTest.java
+++ b/langtools/test/tools/javac/options/xprefer/XPreferTest.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
@@ -213,6 +213,7 @@
             com.sun.tools.javac.Main.compile(new String[] {
                     "-verbose",
                     option.optionString,
+                    "-source", "8", "-target", "8",
                     "-sourcepath", Dir.SOURCE_PATH.file.getPath(),
                     "-classpath", Dir.CLASS_PATH.file.getPath(),
                     "-Xbootclasspath/p:" + Dir.BOOT_PATH.file.getPath(),
diff --git a/langtools/test/tools/javac/platform/PlatformProviderTest.java b/langtools/test/tools/javac/platform/PlatformProviderTest.java
index 21cfa81..46bf67c 100644
--- a/langtools/test/tools/javac/platform/PlatformProviderTest.java
+++ b/langtools/test/tools/javac/platform/PlatformProviderTest.java
@@ -28,6 +28,11 @@
  *          correctly.
  * @library /tools/lib
  * @build ToolBox PlatformProviderTest
+ * @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.jdeps/com.sun.tools.javap
  * @run main/othervm PlatformProviderTest
  */
 
@@ -91,6 +96,8 @@
                   .outdir(".")
                   .options("-J-classpath",
                            "-J" + System.getProperty("test.classes"),
+                           "-J-XaddExports:jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED," +
+                                           "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
                            "-XDrawDiagnostics",
                            "-release",
                            platformSpec,
@@ -125,6 +132,8 @@
                   .outdir(".")
                   .options("-J-classpath",
                            "-J" + System.getProperty("test.classes"),
+                           "-J-XaddExports:jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED," +
+                                           "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
                            "-release",
                            "fail",
                            System.getProperty("test.src") + "/PlatformProviderTestSource.java")
diff --git a/langtools/test/tools/javac/plugin/showtype/Test.java b/langtools/test/tools/javac/plugin/showtype/Test.java
index 8363722..dd5f096 100644
--- a/langtools/test/tools/javac/plugin/showtype/Test.java
+++ b/langtools/test/tools/javac/plugin/showtype/Test.java
@@ -28,29 +28,24 @@
  *  @modules jdk.compiler/com.sun.tools.javac.api
  *           jdk.compiler/com.sun.tools.javac.file
  *           jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  *  @build ToolBox
  *  @run main Test
  *  @summary Provide a simple light-weight "plug-in" mechanism for javac
  */
 
 import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
+
 import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
 import javax.tools.ToolProvider;
 
+import com.sun.source.util.JavacTask;
+
 public class Test {
     public static void main(String... args) throws Exception {
         new Test().run();
diff --git a/langtools/test/tools/javac/processing/T8142931.java b/langtools/test/tools/javac/processing/T8142931.java
index 29b32d1..5971043 100644
--- a/langtools/test/tools/javac/processing/T8142931.java
+++ b/langtools/test/tools/javac/processing/T8142931.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
@@ -49,16 +49,19 @@
     public static void main(String... args) throws IOException {
         String testSrc = System.getProperty("test.src", ".");
         String testClasses = System.getProperty("test.classes");
-        JavacTool tool = JavacTool.create();
+        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
         MyDiagListener dl = new MyDiagListener();
         try (StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null)) {
             Iterable<? extends JavaFileObject> files =
                 fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, T8142931.class.getName()+".java")));
-            Iterable<String> opts = Arrays.asList("-proc:only",
+            Iterable<String> opts = Arrays.asList("-XaddExports:" +
+                                                  "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
+                                                  "-XDaccessInternalAPI",
+                                                  "-proc:only",
                                                   "-processor", "T8142931",
                                                   "-processorpath", testClasses);
             StringWriter out = new StringWriter();
-            JavacTask task = tool.getTask(out, fm, dl, opts, null, files);
+            JavacTask task = (JavacTask)tool.getTask(out, fm, dl, opts, null, files);
             task.call();
             String s = out.toString();
             System.err.print(s);
@@ -98,4 +101,5 @@
 
         public int count;
     }
-}
\ No newline at end of file
+}
+
diff --git a/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java b/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java
index 5ed8a60..3522278 100644
--- a/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java
+++ b/langtools/test/tools/javac/processing/environment/ProcessingEnvAnnoDiscovery.java
@@ -29,7 +29,7 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor ProcessingEnvAnnoDiscovery
- * @compile/process -processor ProcessingEnvAnnoDiscovery ProcessingEnvAnnoDiscovery.java
+ * @compile/process -XDaccessInternalAPI -processor ProcessingEnvAnnoDiscovery ProcessingEnvAnnoDiscovery.java
  */
 
 import java.lang.annotation.*;
diff --git a/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java
index a6e87ba..9f0208a 100644
--- a/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java
+++ b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Processor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -32,7 +32,6 @@
 import com.sun.tools.javac.util.Assert;
 
 public class Processor extends JavacTestingAbstractProcessor {
-
     private boolean seenGenerated;
 
     @Override
diff --git a/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java
index 32a4835..028e01c 100644
--- a/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java
+++ b/langtools/test/tools/javac/processing/errors/EnsureAnnotationTypeMismatchException/Source.java
@@ -6,7 +6,7 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor Processor
- * @compile/fail/ref=Source.out -XDrawDiagnostics -processor Processor Source.java
+ * @compile/fail/ref=Source.out -XDaccessInternalAPI -XDrawDiagnostics -processor Processor Source.java
  */
 
 @Gen(fileName="Generated",
diff --git a/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Processor.java b/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Processor.java
index 71e722e..86b15a5 100644
--- a/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Processor.java
+++ b/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Processor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -29,10 +29,8 @@
 import javax.lang.model.type.MirroredTypeException;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.type.TypeKind;
-import javax.tools.*;
 
 import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.code.Symbol;
 import static com.sun.tools.javac.code.Symbol.TypeSymbol;
 
 public class Processor extends JavacTestingAbstractProcessor {
diff --git a/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Source.java b/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Source.java
index ea2cd51..daf2ef3 100644
--- a/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Source.java
+++ b/langtools/test/tools/javac/processing/errors/EnsureMirroredTypeException/Source.java
@@ -6,7 +6,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.code
  *          jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor Processor
- * @compile/fail/ref=Source.out -XDrawDiagnostics -processor Processor Source.java
+ * @compile/fail/ref=Source.out -XDaccessInternalAPI -XDrawDiagnostics -processor Processor Source.java
  */
 
 @Processor.A(a=some.path.to.SomeUnknownClass$Inner.class)
diff --git a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateFunctionalInterface.java b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateFunctionalInterface.java
index 530180d..ccb1d31 100644
--- a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateFunctionalInterface.java
+++ b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateFunctionalInterface.java
@@ -28,7 +28,7 @@
  *          which will make the current interface functional
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build GenerateSuperInterfaceProcessor
- * @compile -processor GenerateSuperInterfaceProcessor GenerateFunctionalInterface.java
+ * @compile -XDaccessInternalAPI -processor GenerateSuperInterfaceProcessor GenerateFunctionalInterface.java
  */
 
 import java.lang.FunctionalInterface;
diff --git a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateSuperInterfaceProcessor.java b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateSuperInterfaceProcessor.java
index 994c844..7df0037 100644
--- a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateSuperInterfaceProcessor.java
+++ b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/GenerateSuperInterfaceProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,6 +22,7 @@
  */
 
 import com.sun.tools.javac.util.Assert;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Set;
@@ -57,4 +58,4 @@
 @interface Generate {
     String fileName();
     String content();
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/processing/errors/TestBadProcessor.java b/langtools/test/tools/javac/processing/errors/TestBadProcessor.java
index 93cf845..fd7a7e7 100644
--- a/langtools/test/tools/javac/processing/errors/TestBadProcessor.java
+++ b/langtools/test/tools/javac/processing/errors/TestBadProcessor.java
@@ -74,7 +74,7 @@
         String expect = "error: Bad service configuration file, " +
                 "or exception thrown while constructing Processor object: " +
                 "javax.annotation.processing.Processor: " +
-                "Provider AnnoProc could not be instantiated: java.lang.Error\n" +
+                "Provider AnnoProc could not be instantiated\n" +
                 "1 error";
         String lineSeparator = System.getProperty("line.separator");
         if (!out.trim().replace(lineSeparator, "\n").equals(expect)) {
diff --git a/langtools/test/tools/javac/processing/loader/testClose/TestClose.java b/langtools/test/tools/javac/processing/loader/testClose/TestClose.java
index d69d6e9..b01b5e3 100644
--- a/langtools/test/tools/javac/processing/loader/testClose/TestClose.java
+++ b/langtools/test/tools/javac/processing/loader/testClose/TestClose.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
@@ -35,8 +35,6 @@
 import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
 import com.sun.tools.javac.api.BasicJavacTask;
 import com.sun.tools.javac.api.JavacTool;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.util.Context;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
@@ -133,7 +131,12 @@
                 List<? extends JavaFileObject> files = Arrays.asList(
                         new MemFile("AnnoProc.java", annoProc),
                         new MemFile("Callback.java", callback));
-                JavacTask task = tool.getTask(null, fm, null, null, null, files);
+                List<String> options = Arrays.asList(
+                        "-XaddExports:"
+                        + "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED,"
+                        + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                        "-XDaccessInternalAPI");
+                JavacTask task = tool.getTask(null, fm, null, options, null, files);
                 check(task.call());
             }
 
@@ -151,7 +154,7 @@
                             Arrays.asList(extraClasses, testClasses));
                     List<? extends JavaFileObject> files = Arrays.asList(
                             new MemFile("my://dummy", "class Dummy { }"));
-                    List<String> options = Arrays.asList("-processor", "AnnoProc");
+                    List<String> options = Arrays.asList("-XDaccessInternalAPI", "-processor", "AnnoProc");
                     JavacTask task = tool.getTask(null, fm, null, options, null, files);
                     task.setTaskListener(this);
                     check(task.call());
@@ -189,6 +192,7 @@
     }
 
     public static void add(ProcessingEnvironment env, Runnable r) {
+        // ensure this class in this class loader can access javac internals
         try {
             JavacTask task = JavacTask.instance(env);
             TaskListener l = ((BasicJavacTask) task).getTaskListeners().iterator().next();
diff --git a/langtools/test/tools/javac/processing/loader/testClose/TestClose2.java b/langtools/test/tools/javac/processing/loader/testClose/TestClose2.java
index ff44cfe..71fb723 100644
--- a/langtools/test/tools/javac/processing/loader/testClose/TestClose2.java
+++ b/langtools/test/tools/javac/processing/loader/testClose/TestClose2.java
@@ -92,6 +92,10 @@
         Iterable<? extends JavaFileObject> files =
                 fm.getJavaFileObjects(new File(testSrc, TestClose2.class.getName() + ".java"));
         List<String> options = Arrays.asList(
+                "-XaddExports:"
+                    + "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED,"
+                    + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
                 "-processor", TestClose2.class.getName());
 
         JavacTask task = tool.getTask(null, fm, null, options, null, files);
diff --git a/langtools/test/tools/javac/processing/messager/MessagerDiags.java b/langtools/test/tools/javac/processing/messager/MessagerDiags.java
index 217d93e..64c2a3a 100644
--- a/langtools/test/tools/javac/processing/messager/MessagerDiags.java
+++ b/langtools/test/tools/javac/processing/messager/MessagerDiags.java
@@ -85,12 +85,11 @@
         assert tool != null;
 
         DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<>();
-        List<String> options = new LinkedList<>();
-        options.addAll(Arrays.asList("-bootclasspath",  bootPath,
-                        "-source", "1.8", "-classpath",
-                        System.getProperty("java.class.path")));
-        options.addAll(Arrays.asList("-processor",
-                       MessagerDiags.class.getName()));
+        List<String> options = Arrays.asList(
+                "-source", "1.8",
+                "-Xlint:-options",
+                "-classpath", System.getProperty("java.class.path"),
+                "-processor", MessagerDiags.class.getName());
         JavacTask ct = (JavacTask)tool.getTask(null, null, dc, options, null,
                         Arrays.asList(new MyFileObject("class " + CNAME + " {}")));
         ct.analyze();
diff --git a/langtools/test/tools/javac/processing/model/TestSymtabItems.java b/langtools/test/tools/javac/processing/model/TestSymtabItems.java
index 66cca99..3872052 100644
--- a/langtools/test/tools/javac/processing/model/TestSymtabItems.java
+++ b/langtools/test/tools/javac/processing/model/TestSymtabItems.java
@@ -33,8 +33,10 @@
  */
 
 import java.lang.reflect.Field;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.TypeParameterElement;
@@ -83,6 +85,11 @@
             if (f.getName().toLowerCase().contains("methodhandle"))
                 continue;
 
+            //both noModule and unnamedModule claim the unnamed package, ignore noModule for now:
+            if (f.getName().equals("noModule"))
+                continue;
+
+            f.setAccessible(true);
             Class<?> ft = f.getType();
             if (TypeMirror.class.isAssignableFrom(ft))
                 print(f.getName(), (TypeMirror) f.get(syms), types);
@@ -117,6 +124,15 @@
 
     class ElemPrinter extends ElementScanner9<Void, Void> {
         @Override
+        public Void visitModule(ModuleElement e, Void p) {
+            show("module", e);
+            indent(+1);
+            super.visitModule(e, p);
+            indent(-1);
+            return null;
+        }
+
+        @Override
         public Void visitPackage(PackageElement e, Void p) {
             show("package", e);
             indent(+1);
diff --git a/langtools/test/tools/javac/processing/model/element/8009367/TestQualifiedNameUsed.java b/langtools/test/tools/javac/processing/model/element/8009367/TestQualifiedNameUsed.java
index 3e5dceb..8e0834c 100644
--- a/langtools/test/tools/javac/processing/model/element/8009367/TestQualifiedNameUsed.java
+++ b/langtools/test/tools/javac/processing/model/element/8009367/TestQualifiedNameUsed.java
@@ -29,7 +29,7 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build   JavacTestingAbstractProcessor TestQualifiedNameUsed p.Q p.QQ p.R p.RR
- * @run compile -processor TestQualifiedNameUsed -proc:only TestQualifiedNameUsed.java
+ * @run compile -XDaccessInternalAPI -processor TestQualifiedNameUsed -proc:only TestQualifiedNameUsed.java
  */
 
 import java.lang.annotation.Repeatable;
@@ -40,9 +40,8 @@
 
 import com.sun.tools.javac.util.Assert;
 
-import java.util.Arrays;
-
 public class TestQualifiedNameUsed extends JavacTestingAbstractProcessor {
+
     @Q
     @p.Q
     @p.R.Q
diff --git a/langtools/test/tools/javac/processing/model/element/TestEmptyContainer.java b/langtools/test/tools/javac/processing/model/element/TestEmptyContainer.java
index ea27ec3..a8c66d7 100644
--- a/langtools/test/tools/javac/processing/model/element/TestEmptyContainer.java
+++ b/langtools/test/tools/javac/processing/model/element/TestEmptyContainer.java
@@ -29,7 +29,7 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build   JavacTestingAbstractProcessor TestEmptyContainer
- * @compile -processor TestEmptyContainer -proc:only TestEmptyContainer.java
+ * @compile -XDaccessInternalAPI -processor TestEmptyContainer -proc:only TestEmptyContainer.java
  */
 
 import com.sun.tools.javac.util.Assert;
@@ -45,6 +45,7 @@
 
 @TestEmptyContainer.Foo(1)
 public class TestEmptyContainer extends JavacTestingAbstractProcessor {
+
     public boolean process(Set<? extends TypeElement> annotations,
                            RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
index fb71747..c22dfcb 100644
--- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
+++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java
@@ -29,7 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.processing
  *          jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor TestMissingElement
- * @compile/fail/ref=TestMissingElement.ref -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java
+ * @compile/fail/ref=TestMissingElement.ref -XDaccessInternalAPI -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/processing/model/element/TestNonInherited.java b/langtools/test/tools/javac/processing/model/element/TestNonInherited.java
index 2dcdc13..4d53665 100644
--- a/langtools/test/tools/javac/processing/model/element/TestNonInherited.java
+++ b/langtools/test/tools/javac/processing/model/element/TestNonInherited.java
@@ -29,7 +29,7 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build   JavacTestingAbstractProcessor TestNonInherited
- * @compile -processor TestNonInherited -proc:only TestNonInherited.java
+ * @compile -XDaccessInternalAPI -processor TestNonInherited -proc:only TestNonInherited.java
  */
 
 import com.sun.tools.javac.util.Assert;
@@ -39,7 +39,6 @@
 import java.util.Set;
 import javax.annotation.processing.*;
 import javax.lang.model.element.*;
-import javax.lang.model.util.*;
 
 import static javax.lang.model.util.ElementFilter.*;
 
diff --git a/langtools/test/tools/javac/processing/model/inheritedByType/EnsureOrder.java b/langtools/test/tools/javac/processing/model/inheritedByType/EnsureOrder.java
index d1e5fd5..4679567 100644
--- a/langtools/test/tools/javac/processing/model/inheritedByType/EnsureOrder.java
+++ b/langtools/test/tools/javac/processing/model/inheritedByType/EnsureOrder.java
@@ -28,19 +28,13 @@
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.util
  * @build   JavacTestingAbstractProcessor EnsureOrder
- * @compile -processor EnsureOrder -proc:only EnsureOrder.java
+ * @compile -XDaccessInternalAPI -processor EnsureOrder -proc:only EnsureOrder.java
  */
 
 import java.util.Set;
 import java.lang.annotation.*;
 import javax.annotation.processing.*;
-import javax.lang.model.SourceVersion;
-import static javax.lang.model.SourceVersion.*;
 import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-import static javax.lang.model.util.ElementFilter.*;
-import static javax.tools.Diagnostic.Kind.*;
-import static javax.tools.StandardLocation.*;
 import com.sun.tools.javac.util.Assert;
 
 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE})
@@ -64,6 +58,7 @@
 class Sub extends Base {}
 
 public class EnsureOrder<@Foos({@Foo(0), @Foo(1)}) @Foo(2)T> extends JavacTestingAbstractProcessor {
+
     public boolean process(Set<? extends TypeElement> annotations,
                            RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver()) {
diff --git a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java
index de1bb13..c61a4d4 100644
--- a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java
+++ b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.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
@@ -26,22 +26,30 @@
  * @bug     6374357 6308351 6707027
  * @summary PackageElement.getEnclosedElements() throws ClassReader$BadClassFileException
  * @author  Peter von der Ah\u00e9
- * @modules jdk.compiler
+ * @modules jdk.compiler/com.sun.tools.javac.model
  * @run main/othervm -Xmx256m Main
  */
 
 import java.io.File;
 import java.util.*;
+import java.util.Map.Entry;
+import java.util.stream.StreamSupport;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.util.Elements;
 import javax.tools.*;
+import javax.tools.JavaFileManager.Location;
+
 import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.model.JavacElements;
 
 import static javax.tools.StandardLocation.CLASS_PATH;
 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
+import static javax.tools.StandardLocation.SYSTEM_MODULES;
 import static javax.tools.JavaFileObject.Kind.CLASS;
 
 
@@ -66,7 +74,7 @@
             JavacTask javac = (JavacTask)tool.getTask(null, fm, null, null, null, null);
             Elements elements = javac.getElements();
 
-            final Set<String> packages = new LinkedHashSet<String>();
+            final Map<String, Set<String>> packages = new LinkedHashMap<>();
 
             int nestedClasses = 0;
             int classes = 0;
@@ -75,16 +83,23 @@
                 String type = fm.inferBinaryName(PLATFORM_CLASS_PATH, file);
                 if (type.endsWith("package-info"))
                     continue;
+                if (type.endsWith("module-info"))
+                    continue;
+                String moduleName = fm.asPath(file).getName(1).toString();
                 try {
-                    TypeElement elem = elements.getTypeElement(type);
+                    ModuleElement me = elements.getModuleElement(moduleName);
+                    me.getClass();
+                    TypeElement elem = ((JavacElements) elements).getTypeElement(me, type);
                     if (elem == null && type.indexOf('$') > 0) {
                         nestedClasses++;
                         type = null;
                         continue;
                     }
                     classes++;
-                    packages.add(getPackage(elem).getQualifiedName().toString());
-                    elements.getTypeElement(type).getKind(); // force completion
+                    String pack = getPackage(elem).getQualifiedName().toString();
+                    packages.computeIfAbsent(me.getQualifiedName().toString(),
+                                             m -> new LinkedHashSet<>()).add(pack);
+                    elem.getKind(); // force completion
                     type = null;
                 } finally {
                     if (type != null)
@@ -97,10 +112,13 @@
             javac = (JavacTask)tool.getTask(null, fm, null, null, null, null);
             elements = javac.getElements();
 
-            for (String name : packages) {
-                PackageElement pe = elements.getPackageElement(name);
-                for (Element e : pe.getEnclosedElements()) {
-                    e.getSimpleName().getClass();
+            for (Entry<String, Set<String>> module2Packages : packages.entrySet()) {
+                ModuleElement me = elements.getModuleElement(module2Packages.getKey());
+                for (String name : module2Packages.getValue()) {
+                    PackageElement pe = ((JavacElements) elements).getPackageElement(me, name);
+                    for (Element e : pe.getEnclosedElements()) {
+                        e.getSimpleName().getClass();
+                    }
                 }
             }
             /*
@@ -117,7 +135,7 @@
                               packages.size(), classes, nestedClasses);
             if (classes < 9000)
                 throw new AssertionError("Too few classes in PLATFORM_CLASS_PATH ;-)");
-            if (packages.size() < 530)
+            if (packages.values().stream().flatMap(packs -> packs.stream()).count() < 530)
                 throw new AssertionError("Too few packages in PLATFORM_CLASS_PATH ;-)");
             if (nestedClasses < 3000)
                 throw new AssertionError("Too few nested classes in PLATFORM_CLASS_PATH ;-)");
diff --git a/langtools/test/tools/javac/processing/model/type/BasicAnnoTests.java b/langtools/test/tools/javac/processing/model/type/BasicAnnoTests.java
index 52ce6f6..85a6f6a 100644
--- a/langtools/test/tools/javac/processing/model/type/BasicAnnoTests.java
+++ b/langtools/test/tools/javac/processing/model/type/BasicAnnoTests.java
@@ -32,7 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor DPrinter BasicAnnoTests
- * @compile/process -processor BasicAnnoTests -proc:only BasicAnnoTests.java
+ * @compile/process -XDaccessInternalAPI -processor BasicAnnoTests -proc:only BasicAnnoTests.java
  */
 
 import java.io.PrintWriter;
diff --git a/langtools/test/tools/javac/processing/model/type/BoundsTest.java b/langtools/test/tools/javac/processing/model/type/BoundsTest.java
index f47c08e..b7e9121 100644
--- a/langtools/test/tools/javac/processing/model/type/BoundsTest.java
+++ b/langtools/test/tools/javac/processing/model/type/BoundsTest.java
@@ -32,10 +32,7 @@
  */
 
 import com.sun.source.util.*;
-import com.sun.tools.javac.api.*;
-import com.sun.tools.javac.file.*;
 import javax.annotation.processing.*;
-import javax.lang.model.SourceVersion;
 import javax.lang.model.type.*;
 import javax.lang.model.util.ElementFilter;
 import javax.lang.model.element.*;
diff --git a/langtools/test/tools/javac/processing/model/type/NoTypes.java b/langtools/test/tools/javac/processing/model/type/NoTypes.java
index f7db93a..cb911ce 100644
--- a/langtools/test/tools/javac/processing/model/type/NoTypes.java
+++ b/langtools/test/tools/javac/processing/model/type/NoTypes.java
@@ -69,8 +69,21 @@
         Element pkg = i.getEnclosingElement().getEnclosingElement();
         verifyKind(PACKAGE, pkg.asType());
 
-        // A package isn't enclosed.  Not yet, anyway.
-        if (pkg.getEnclosingElement() != null)
+        Element module = pkg.getEnclosingElement();
+
+        if (module == null)
+            throw new AssertionError();
+
+        if (module.getKind() != ElementKind.MODULE)
+            throw new AssertionError();
+
+        ModuleElement modle = (ModuleElement) module;
+
+        if (!modle.isUnnamed())
+            throw new AssertionError();
+
+        // A module isn't enclosed.
+        if (module.getEnclosingElement() != null)
             throw new AssertionError();
 
         verifyKind(VOID, types.getNoType(VOID));
diff --git a/langtools/test/tools/javac/processing/rounds/BaseClassesNotReRead.java b/langtools/test/tools/javac/processing/rounds/BaseClassesNotReRead.java
index e4116ec..a39ec38 100644
--- a/langtools/test/tools/javac/processing/rounds/BaseClassesNotReRead.java
+++ b/langtools/test/tools/javac/processing/rounds/BaseClassesNotReRead.java
@@ -111,7 +111,8 @@
         @Override
         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind)
                 throws IOException {
-            return new OnlyOneReadJavaFileObject(super.getJavaFileForInput(location, className, kind));
+            JavaFileObject fo = super.getJavaFileForInput(location, className, kind);
+            return (fo == null) ? null : new OnlyOneReadJavaFileObject(fo);
         }
 
         @Override
diff --git a/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java b/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java
index fc0140b..7705131 100644
--- a/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java
+++ b/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java
@@ -30,6 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox JavacTestingAbstractProcessor
  * @run main CompleteOnClosed
  */
diff --git a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java
index 0f10c6d..f94435d 100644
--- a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java
+++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java
@@ -32,11 +32,12 @@
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.processing
  *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.jdeps/com.sun.tools.javap
  * @clean *
  * @build OverwriteBetweenCompilations ToolBox JavacTestingAbstractProcessor
- * @compile/ref=OverwriteBetweenCompilations_1.out -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
- * @compile/ref=OverwriteBetweenCompilations_2.out -processor OverwriteBetweenCompilations -Apass=2 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
- * @compile/ref=OverwriteBetweenCompilations_3.out -processor OverwriteBetweenCompilations -Apass=3 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
+ * @compile/ref=OverwriteBetweenCompilations_1.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
+ * @compile/ref=OverwriteBetweenCompilations_2.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=2 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
+ * @compile/ref=OverwriteBetweenCompilations_3.out -XDaccessInternalAPI -processor OverwriteBetweenCompilations -Apass=3 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javac/profiles/ProfileTest.java b/langtools/test/tools/javac/profiles/ProfileTest.java
deleted file mode 100644
index d5d4efc..0000000
--- a/langtools/test/tools/javac/profiles/ProfileTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2013, 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 8022287
- * @summary javac.sym.Profiles uses a static Map when it should not
- * @modules jdk.compiler/com.sun.tools.javac.sym
- */
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import com.sun.tools.javac.sym.Profiles;
-
-public class ProfileTest {
-    public static void main(String... args) throws Exception {
-        new ProfileTest().run();
-    }
-
-    public void run() throws Exception {
-        test("A");
-        test("B");
-
-        if (errors > 0)
-            throw new Exception(errors + " occurred");
-    }
-
-    void test(String base) throws IOException {
-        System.err.println("test " + base);
-        File profileDesc = createFiles(base);
-        checkProfile(profileDesc, base);
-    }
-
-    void checkProfile(File profileDesc, String base) throws IOException {
-        Profiles p = Profiles.read(profileDesc);
-        for (int i = 0; i < p.getProfileCount(); i++) {
-            System.err.println(p.getPackages(i));
-            for (String pkg: p.getPackages(i)) {
-                if (!pkg.endsWith(base))
-                    error("unexpected package " + pkg + " for profile " + i);
-            }
-        }
-    }
-
-    File createFiles(String base) throws IOException {
-        File baseDir = new File(base);
-        baseDir.mkdirs();
-        for (int p = 1; p <= 4; p++) {
-            String pkg = "pkg" + p + base;
-            File pkgDir = new File(baseDir, pkg);
-            pkgDir.mkdirs();
-            File clssFile = new File(pkgDir, pkg + "Class.java");
-            try (PrintWriter out = new PrintWriter(new FileWriter(clssFile))) {
-                out.println("package " + pkgDir.getName() + ";");
-                out.println("class " + clssFile.getName().replace(".java", ""));
-            }
-        }
-
-        File profileDesc = new File(baseDir, "profiles" + base + ".txt");
-        try (PrintWriter out = new PrintWriter(new FileWriter(profileDesc))) {
-            for (int p = 1; p <= 4; p++) {
-                String pkg = "pkg" + p + base;
-                createPackage(baseDir, pkg, "Pkg" + p + base + "Class");
-                out.println("PROFILE_" + p + "_RTJAR_INCLUDE_PACKAGES := " + pkg);
-                out.println("PROFILE_" + p + "_RTJAR_INCLUDE_TYPES :=");
-                out.println("PROFILE_" + p + "_RTJAR_EXCLUDE_TYPES :=");
-                out.println("PROFILE_" + p + "_INCLUDE_METAINF_SERVICES := ");
-            }
-        }
-
-        return profileDesc;
-    }
-
-    void createPackage(File baseDir, String pkg, String... classNames) throws IOException {
-        File pkgDir = new File(baseDir, pkg);
-        pkgDir.mkdirs();
-        for (String className: classNames) {
-            File clssFile = new File(pkgDir, className + ".java");
-            try (PrintWriter out = new PrintWriter(new FileWriter(clssFile))) {
-                out.println("package " + pkg + ";");
-                out.println("public class " + className + " { }");
-            }
-        }
-    }
-
-    void error(String msg) {
-        System.err.println("Error: " + msg);
-        errors++;
-    }
-
-    int errors;
-}
diff --git a/langtools/test/tools/javac/proprietary/WarnClass.java b/langtools/test/tools/javac/proprietary/WarnClass.java
deleted file mode 100644
index 3cd77f2..0000000
--- a/langtools/test/tools/javac/proprietary/WarnClass.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @modules java.base/sun.security.x509
- * @compile WarnClass.java
- * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror WarnClass.java
- * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror -nowarn WarnClass.java
- * @compile/fail/ref=WarnClass.out -XDrawDiagnostics  -Werror -Xlint:none WarnClass.java
- */
-
-public class WarnClass extends sun.security.x509.X509CertInfo {}
diff --git a/langtools/test/tools/javac/proprietary/WarnClass.out b/langtools/test/tools/javac/proprietary/WarnClass.out
deleted file mode 100644
index 47abeea..0000000
--- a/langtools/test/tools/javac/proprietary/WarnClass.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnClass.java:13:49: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/proprietary/WarnImport.java b/langtools/test/tools/javac/proprietary/WarnImport.java
deleted file mode 100644
index 8782a04..0000000
--- a/langtools/test/tools/javac/proprietary/WarnImport.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @compile WarnImport.java
- * @compile/fail/ref=WarnImport.out -XDrawDiagnostics  -Werror WarnImport.java
- * @compile/fail/ref=WarnImport.out -XDrawDiagnostics  -Werror -nowarn WarnImport.java
- * @compile/fail/ref=WarnImport.out -XDrawDiagnostics  -Werror -Xlint:none WarnImport.java
- */
-
-import sun.security.x509.X509CertInfo;
-
-public class WarnImport {}
diff --git a/langtools/test/tools/javac/proprietary/WarnImport.out b/langtools/test/tools/javac/proprietary/WarnImport.out
deleted file mode 100644
index 274ffa3..0000000
--- a/langtools/test/tools/javac/proprietary/WarnImport.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnImport.java:12:25: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/proprietary/WarnMethod.java b/langtools/test/tools/javac/proprietary/WarnMethod.java
deleted file mode 100644
index f8eb51d..0000000
--- a/langtools/test/tools/javac/proprietary/WarnMethod.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @modules java.base/sun.security.x509
- * @compile WarnMethod.java
- * @compile/fail/ref=WarnMethod.out -XDrawDiagnostics  -Werror WarnMethod.java
- * @compile/fail/ref=WarnMethod.out -XDrawDiagnostics  -Werror -nowarn WarnMethod.java
- * @compile/fail/ref=WarnMethod.out -XDrawDiagnostics  -Werror -Xlint:none WarnMethod.java
- */
-
-public class WarnMethod {
-    public static void main(String... args) {
-        System.out.println(sun.security.x509.OIDMap.getOID(""));
-    }
-}
diff --git a/langtools/test/tools/javac/proprietary/WarnMethod.out b/langtools/test/tools/javac/proprietary/WarnMethod.out
deleted file mode 100644
index 83fb6bd..0000000
--- a/langtools/test/tools/javac/proprietary/WarnMethod.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnMethod.java:15:45: compiler.warn.sun.proprietary: sun.security.x509.OIDMap
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/proprietary/WarnStaticImport.java b/langtools/test/tools/javac/proprietary/WarnStaticImport.java
deleted file mode 100644
index 91fc369..0000000
--- a/langtools/test/tools/javac/proprietary/WarnStaticImport.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @compile WarnStaticImport.java
- * @compile/fail/ref=WarnStaticImport.out -XDrawDiagnostics  -Werror WarnStaticImport.java
- * @compile/fail/ref=WarnStaticImport.out -XDrawDiagnostics  -Werror -nowarn WarnStaticImport.java
- * @compile/fail/ref=WarnStaticImport.out -XDrawDiagnostics  -Werror -Xlint:none WarnStaticImport.java
- */
-
-import static sun.security.x509.OIDMap.getOID;
-
-public class WarnStaticImport {}
diff --git a/langtools/test/tools/javac/proprietary/WarnStaticImport.out b/langtools/test/tools/javac/proprietary/WarnStaticImport.out
deleted file mode 100644
index 7e7d91f..0000000
--- a/langtools/test/tools/javac/proprietary/WarnStaticImport.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnStaticImport.java:12:32: compiler.warn.sun.proprietary: sun.security.x509.OIDMap
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/proprietary/WarnVariable.java b/langtools/test/tools/javac/proprietary/WarnVariable.java
deleted file mode 100644
index e3d1b88..0000000
--- a/langtools/test/tools/javac/proprietary/WarnVariable.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @modules java.base/sun.security.x509
- * @compile WarnVariable.java
- * @compile/fail/ref=WarnVariable.out -XDrawDiagnostics  -Werror WarnVariable.java
- * @compile/fail/ref=WarnVariable.out -XDrawDiagnostics  -Werror -nowarn WarnVariable.java
- * @compile/fail/ref=WarnVariable.out -XDrawDiagnostics  -Werror -Xlint:none WarnVariable.java
- */
-
-public class WarnVariable {
-    public static void main(String... args) {
-        System.out.println(sun.security.x509.X509CertImpl.NAME);
-    }
-}
diff --git a/langtools/test/tools/javac/proprietary/WarnVariable.out b/langtools/test/tools/javac/proprietary/WarnVariable.out
deleted file mode 100644
index 5dacbdf..0000000
--- a/langtools/test/tools/javac/proprietary/WarnVariable.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnVariable.java:15:45: compiler.warn.sun.proprietary: sun.security.x509.X509CertImpl
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/proprietary/WarnWildcard.java b/langtools/test/tools/javac/proprietary/WarnWildcard.java
deleted file mode 100644
index b8b1527..0000000
--- a/langtools/test/tools/javac/proprietary/WarnWildcard.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * @test    /nodynamiccopyright/
- * @bug     6380059
- * @summary Emit warnings for proprietary packages in the boot class path
- * @author  Peter von der Ah\u00e9
- * @modules java.base/sun.security.x509
- * @compile WarnWildcard.java
- * @compile/fail/ref=WarnWildcard.out -XDrawDiagnostics  -Werror WarnWildcard.java
- * @compile/fail/ref=WarnWildcard.out -XDrawDiagnostics  -Werror -nowarn WarnWildcard.java
- * @compile/fail/ref=WarnWildcard.out -XDrawDiagnostics  -Werror -Xlint:none WarnWildcard.java
- */
-
-public class WarnWildcard {
-    java.util.Collection<? extends sun.security.x509.X509CertImpl> x;
-}
diff --git a/langtools/test/tools/javac/proprietary/WarnWildcard.out b/langtools/test/tools/javac/proprietary/WarnWildcard.out
deleted file mode 100644
index 4cee842..0000000
--- a/langtools/test/tools/javac/proprietary/WarnWildcard.out
+++ /dev/null
@@ -1,4 +0,0 @@
-WarnWildcard.java:14:53: compiler.warn.sun.proprietary: sun.security.x509.X509CertImpl
-- compiler.err.warnings.and.werror
-1 error
-1 warning
diff --git a/langtools/test/tools/javac/redefineObject/Object1-test.java b/langtools/test/tools/javac/redefineObject/Object1-test.java
new file mode 100644
index 0000000..86827f5
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/Object1-test.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1997,2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 4091755
+ * @summary java.lang.Object can't be redefined without crashing javac
+ * @author gafter
+ *
+ * @compile/module=java.base/fail/ref=Object1.out -XDrawDiagnostics Object1.java
+ */
+
diff --git a/langtools/test/tools/javac/redefineObject/Object1.out b/langtools/test/tools/javac/redefineObject/Object1.out
new file mode 100644
index 0000000..cb21505
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/Object1.out
@@ -0,0 +1,2 @@
+Object1.java:7:22: compiler.err.cyclic.inheritance: java.lang.Throwable
+1 error
diff --git a/langtools/test/tools/javac/redefineObject/Object2-test.java b/langtools/test/tools/javac/redefineObject/Object2-test.java
new file mode 100644
index 0000000..34a4055
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/Object2-test.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997,2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 4091755
+ * @summary java.lang.Object can't be redefined without crashing javac
+ * @author gafter
+ *
+ * @compile/module=java.base/fail/ref=Object2.out -XDrawDiagnostics  Object2.java
+ */
diff --git a/langtools/test/tools/javac/redefineObject/Object2.out b/langtools/test/tools/javac/redefineObject/Object2.out
new file mode 100644
index 0000000..ed23495
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/Object2.out
@@ -0,0 +1,2 @@
+Object2.java:7:25: compiler.err.cyclic.inheritance: java.lang.Cloneable
+1 error
diff --git a/langtools/test/tools/javac/redefineObject/java.base/Object1.java b/langtools/test/tools/javac/redefineObject/java.base/Object1.java
new file mode 100644
index 0000000..1601f24
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/java.base/Object1.java
@@ -0,0 +1,19 @@
+/*
+ * /nodynamiccopyright/
+ * See ../Object1-test.java
+ */
+
+package java.lang;
+class Object extends Throwable {
+    public final native Class getClass();
+    public native int hashCode();
+    public native boolean equals(Object obj);
+    protected native Object clone() throws CloneNotSupportedException;
+    public native String toString();
+    public final native void notify();
+    public final native void notifyAll();
+    public final native void wait(long timeout) throws InterruptedException;
+    public native final void wait(long timeout, int nanos) throws InterruptedException;
+    public native final void wait() throws InterruptedException;
+    protected void finalize() throws Throwable { }
+}
diff --git a/langtools/test/tools/javac/redefineObject/java.base/Object2.java b/langtools/test/tools/javac/redefineObject/java.base/Object2.java
new file mode 100644
index 0000000..0f30ce9
--- /dev/null
+++ b/langtools/test/tools/javac/redefineObject/java.base/Object2.java
@@ -0,0 +1,19 @@
+/*
+ * /nodynamiccopyright/
+ * See ../Object2-test.java
+ */
+
+package java.lang;
+class Object implements Cloneable {
+    public final native Class getClass();
+    public native int hashCode();
+    public native boolean equals(Object obj);
+    public native Object clone() throws CloneNotSupportedException;
+    public native String toString();
+    public final native void notify();
+    public final native void notifyAll();
+    public final native void wait(long timeout) throws InterruptedException;
+    public native final void wait(long timeout, int nanos) throws InterruptedException;
+    public native final void wait() throws InterruptedException;
+    protected void finalize() throws Throwable { }
+}
diff --git a/langtools/test/tools/javac/resolve/BitWiseOperators.java b/langtools/test/tools/javac/resolve/BitWiseOperators.java
index 4ae6e18..9c81eec 100644
--- a/langtools/test/tools/javac/resolve/BitWiseOperators.java
+++ b/langtools/test/tools/javac/resolve/BitWiseOperators.java
@@ -27,6 +27,10 @@
  * @summary Verify that bitwise operators don't allow to mix numeric and boolean operands.
  * @library ../lib
  * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.comp
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  * @build combo.ComboTestHelper
  * @run main BitWiseOperators
diff --git a/langtools/test/tools/javac/scope/DupUnsharedTest.java b/langtools/test/tools/javac/scope/DupUnsharedTest.java
index 6735365..309cd94 100644
--- a/langtools/test/tools/javac/scope/DupUnsharedTest.java
+++ b/langtools/test/tools/javac/scope/DupUnsharedTest.java
@@ -73,7 +73,7 @@
     void runScopeContentTest() throws Exception {
         Set<Symbol> expected = Collections.newSetFromMap(new IdentityHashMap<>() {});
         Set<Symbol> notExpected = Collections.newSetFromMap(new IdentityHashMap<>());
-        WriteableScope s1 = WriteableScope.create(symtab.rootPackage);
+        WriteableScope s1 = WriteableScope.create(symtab.unnamedModule.unnamedPackage);
         ClassSymbol acceptSym = symtab.arrayClass;
         s1.enter(acceptSym);
         expected.add(acceptSym);
@@ -140,7 +140,7 @@
      *   'A' and would stop the search prematurely.
      */
     void runClashTest() throws Exception {
-        WriteableScope emptyScope = WriteableScope.create(symtab.unnamedPackage);
+        WriteableScope emptyScope = WriteableScope.create(symtab.unnamedModule.unnamedPackage);
         Field tableField = emptyScope.getClass().getDeclaredField("table");
         tableField.setAccessible(true);
         Method dble = emptyScope.getClass().getDeclaredMethod("dble");
@@ -165,7 +165,7 @@
         System.out.println("first name: " + first);
 
         //now, find another name, that will clash with the first one both in the empty and a doubled scope:
-        Scope doubledEmptyScope = WriteableScope.create(symtab.unnamedPackage);
+        Scope doubledEmptyScope = WriteableScope.create(symtab.unnamedModule.unnamedPackage);
         dble.invoke(doubledEmptyScope);
         Integer firstNameTestScopeIndex = (Integer) getIndex.invoke(emptyScope, first);
         Integer firstNameDoubleScopeIndex = (Integer) getIndex.invoke(doubledEmptyScope, first);
@@ -186,7 +186,7 @@
         Symbol otherSymbol = new VarSymbol(0, other, Type.noType, null);
 
         //test the situation described above:
-        WriteableScope testScope1 = WriteableScope.create(symtab.unnamedPackage);
+        WriteableScope testScope1 = WriteableScope.create(symtab.unnamedModule.unnamedPackage);
         testScope1.enter(firstSymbol);
 
         WriteableScope dupped1 = testScope1.dup();
@@ -200,7 +200,7 @@
         }
 
         //also check a situation where the clashing Symbol is removed from the dupped scope:
-        WriteableScope testScope2 = WriteableScope.create(symtab.unnamedPackage);
+        WriteableScope testScope2 = WriteableScope.create(symtab.unnamedModule.unnamedPackage);
         testScope2.enter(firstSymbol);
 
         WriteableScope dupped2 = testScope2.dup();
diff --git a/langtools/test/tools/javac/scope/HashCollisionTest.java b/langtools/test/tools/javac/scope/HashCollisionTest.java
index ac7a2ce..1793799 100644
--- a/langtools/test/tools/javac/scope/HashCollisionTest.java
+++ b/langtools/test/tools/javac/scope/HashCollisionTest.java
@@ -67,7 +67,7 @@
         types = Types.instance(context);
 
         // determine hashMask for an empty scope
-        Scope emptyScope = WriteableScope.create(symtab.unnamedPackage); // any owner will do
+        Scope emptyScope = WriteableScope.create(symtab.unnamedModule.unnamedPackage); // any owner will do
         Field field = emptyScope.getClass().getDeclaredField("hashMask");
         field.setAccessible(true);
         scopeHashMask = field.getInt(emptyScope);
@@ -105,7 +105,7 @@
          */
 
         // 3. Create a nested class named Entry
-        ClassSymbol cc = createClass(names.fromString("C"), symtab.unnamedPackage);
+        ClassSymbol cc = createClass(names.fromString("C"), symtab.unnamedModule.unnamedPackage);
         ClassSymbol ce = createClass(entry, cc);
 
         // 4. Create a package containing a nested class using the name from 2
@@ -174,7 +174,7 @@
     ClassSymbol createClass(Name name, Symbol owner) {
         ClassSymbol sym = new ClassSymbol(0, name, owner);
         sym.members_field = WriteableScope.create(sym);
-        if (owner != symtab.unnamedPackage)
+        if (owner != symtab.unnamedModule.unnamedPackage)
             owner.members().enter(sym);
         return sym;
     }
diff --git a/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java b/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java
index 1b9628a..51f12be 100644
--- a/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java
+++ b/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java
@@ -56,7 +56,7 @@
         ClassSymbol clazz = new ClassSymbol(0,
                                             names.fromString("X"),
                                             Type.noType,
-                                            symtab.unnamedPackage);
+                                            symtab.unnamedModule.unnamedPackage);
 
         VarSymbol v = new VarSymbol(0, hasNext, Type.noType, clazz);
         MethodSymbol m = new MethodSymbol(0, hasNext, Type.noType, clazz);
diff --git a/langtools/test/tools/javac/scope/StarImportTest.java b/langtools/test/tools/javac/scope/StarImportTest.java
index 7eb1396..66dde99 100644
--- a/langtools/test/tools/javac/scope/StarImportTest.java
+++ b/langtools/test/tools/javac/scope/StarImportTest.java
@@ -27,6 +27,7 @@
  * @summary Basher for star-import scopes
  * @modules jdk.compiler/com.sun.tools.javac.code
  *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  */
 
@@ -199,7 +200,7 @@
             Name name = names.fromString("c" + (++nextClassSerial));
             int count = rgen.nextInt(MAX_SETUP_CLASS_COUNT);
             log("setup: creating class " + name + " with " + count + " entries");
-            ClassSymbol c = createClass(name, symtab.unnamedPackage);
+            ClassSymbol c = createClass(name, symtab.unnamedModule.unnamedPackage);
 //            log("setup: created " + c);
             for (int i = 0; i < count; i++) {
                 ClassSymbol ic = createClass(names.fromString("Entry" + i), c);
@@ -290,7 +291,7 @@
         ClassSymbol createClass(Name name, Symbol owner) {
             ClassSymbol sym = new ClassSymbol(0, name, owner);
             sym.members_field = WriteableScope.create(sym);
-            if (owner != symtab.unnamedPackage)
+            if (owner != symtab.unnamedModule.unnamedPackage)
                 owner.members().enter(sym);
             return sym;
         }
diff --git a/langtools/test/tools/javac/stackmap/StackMapTest.java b/langtools/test/tools/javac/stackmap/StackMapTest.java
index 003fa3a..00cd654 100644
--- a/langtools/test/tools/javac/stackmap/StackMapTest.java
+++ b/langtools/test/tools/javac/stackmap/StackMapTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile StackMapTest.java
  * @run main StackMapTest
diff --git a/langtools/test/tools/javac/sym/ElementStructureTest.java b/langtools/test/tools/javac/sym/ElementStructureTest.java
index 43b945e..4b2c717 100644
--- a/langtools/test/tools/javac/sym/ElementStructureTest.java
+++ b/langtools/test/tools/javac/sym/ElementStructureTest.java
@@ -27,6 +27,13 @@
  * @summary Check the platform classpath contains the correct elements.
  * @library /tools/lib
  * @build ToolBox ElementStructureTest
+ * @modules jdk.compiler/com.sun.tools.javac.code
+ *          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.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  * @run main ElementStructureTest
  */
 
@@ -70,6 +77,7 @@
 import javax.lang.model.element.ElementVisitor;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Modifier;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.NestingKind;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
@@ -249,7 +257,7 @@
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, null, options, null, files);
 
-        task.parse();
+        task.analyze();
 
         JavaFileManager fm = task.getContext().get(JavaFileManager.class);
 
@@ -482,6 +490,11 @@
         }
 
         @Override
+        public Void visitModule(ModuleElement e, Void p) {
+            throw new IllegalStateException("Not supported yet.");
+        }
+
+        @Override
         public Void visitUnknown(Element e, Void p) {
             throw new IllegalStateException("Should not get here.");
         }
diff --git a/langtools/test/tools/javac/synthesize/Boolean.java b/langtools/test/tools/javac/synthesize/Boolean.java
deleted file mode 100644
index 730a982..0000000
--- a/langtools/test/tools/javac/synthesize/Boolean.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Boolean
-{
-    public static Boolean valueOf(boolean v) {
-        return new Boolean(v);
-    }
-
-    public Boolean(boolean v) {
-        value = v;
-    }
-
-    public boolean booleanValue() {
-        return value;
-    }
-
-    private boolean value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Byte.java b/langtools/test/tools/javac/synthesize/Byte.java
deleted file mode 100644
index 4c3ff93..0000000
--- a/langtools/test/tools/javac/synthesize/Byte.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Byte
-{
-    public static Byte valueOf(byte v) {
-        return new Byte(v);
-    }
-
-    public Byte(byte v) {
-        value = v;
-    }
-
-    public byte byteValue() {
-        return value;
-    }
-
-    private byte value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Character.java b/langtools/test/tools/javac/synthesize/Character.java
deleted file mode 100644
index 8b55da5e..0000000
--- a/langtools/test/tools/javac/synthesize/Character.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Character
-{
-    public static Character valueOf(char v) {
-        return new Character(v);
-    }
-
-    public Character(char v) {
-        value = v;
-    }
-
-    public char characterValue() {
-        return value;
-    }
-
-    private char value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Cloneable.java b/langtools/test/tools/javac/synthesize/Cloneable.java
deleted file mode 100644
index 3532241..0000000
--- a/langtools/test/tools/javac/synthesize/Cloneable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public interface Cloneable {
-}
diff --git a/langtools/test/tools/javac/synthesize/Integer.java b/langtools/test/tools/javac/synthesize/Integer.java
deleted file mode 100644
index ec31c74..0000000
--- a/langtools/test/tools/javac/synthesize/Integer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Integer extends Number
-{
-    public static Integer valueOf(int v) {
-        return new Integer(v);
-    }
-
-    public Integer(int v) {
-        value = v;
-    }
-
-    public int integerValue() {
-        return value;
-    }
-
-    private int value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Long.java b/langtools/test/tools/javac/synthesize/Long.java
deleted file mode 100644
index cebc99a..0000000
--- a/langtools/test/tools/javac/synthesize/Long.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Long extends Number
-{
-    public static Long valueOf(long v) {
-        return new Long(v);
-    }
-
-    public Long(long v) {
-        value = v;
-    }
-
-    public long longValue() {
-        return value;
-    }
-
-    private long value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Main.java b/langtools/test/tools/javac/synthesize/Main.java
index e24de54..5817142 100644
--- a/langtools/test/tools/javac/synthesize/Main.java
+++ b/langtools/test/tools/javac/synthesize/Main.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
@@ -96,14 +96,23 @@
         args.add("-classpath");
         args.add("empty");
 
-        if (!stdBootClassPath) {
-            args.add("-bootclasspath");
-            args.add("empty");
+        if (stdBootClassPath) {
+            args.add("-Xmodule:java.base");
+        } else {
+            args.add("-system");
+            args.add("none");
+            files.add("module-info.java");
         }
+
+
         args.add("-d");
         args.add(".");
+
+        // files to compile are in a separate directory from test to avoid
+        // confusing jtreg
+        File src = new File(testSrc, "src");
         for (String f: files)
-            args.add(new File(testSrc, f).getPath());
+            args.add(new File(src, f).getPath());
 
         System.out.println("Compile: " + args);
         StringWriter out = new StringWriter();
diff --git a/langtools/test/tools/javac/synthesize/Number.java b/langtools/test/tools/javac/synthesize/Number.java
deleted file mode 100644
index 3f003ce..0000000
--- a/langtools/test/tools/javac/synthesize/Number.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Number
-{
-
-}
diff --git a/langtools/test/tools/javac/synthesize/Object.java b/langtools/test/tools/javac/synthesize/Object.java
deleted file mode 100644
index 072218b..0000000
--- a/langtools/test/tools/javac/synthesize/Object.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Object
-{
-}
diff --git a/langtools/test/tools/javac/synthesize/Serializable.java b/langtools/test/tools/javac/synthesize/Serializable.java
deleted file mode 100644
index 04f233c..0000000
--- a/langtools/test/tools/javac/synthesize/Serializable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.io;
-
-public interface Serializable {
-}
diff --git a/langtools/test/tools/javac/synthesize/Short.java b/langtools/test/tools/javac/synthesize/Short.java
deleted file mode 100644
index 724f976..0000000
--- a/langtools/test/tools/javac/synthesize/Short.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Short extends Number
-{
-    public static Short valueOf(short v) {
-        return new Short(v);
-    }
-
-    public Short(short v) {
-        value = v;
-    }
-
-    public short shortValue() {
-        return value;
-    }
-
-    private short value;
-}
diff --git a/langtools/test/tools/javac/synthesize/Test.java b/langtools/test/tools/javac/synthesize/Test.java
deleted file mode 100644
index 651057a..0000000
--- a/langtools/test/tools/javac/synthesize/Test.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// This code (indirectly) requires the presence of
-// Cloneable and Serializable (supertypes for Java arrays)
-// Double and Float (for boxing/unboxing)
-public class Test
-{
-    Object f(boolean b, int[] array) {
-        return b ? array : 2;
-    }
-}
diff --git a/langtools/test/tools/javac/synthesize/Void.java b/langtools/test/tools/javac/synthesize/Void.java
deleted file mode 100644
index f86f5f5..0000000
--- a/langtools/test/tools/javac/synthesize/Void.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-public class Void
-{
-
-}
diff --git a/langtools/test/tools/javac/synthesize/src/Boolean.java b/langtools/test/tools/javac/synthesize/src/Boolean.java
new file mode 100644
index 0000000..0059ef3
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Boolean.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Boolean
+{
+    public static Boolean valueOf(boolean v) {
+        return new Boolean(v);
+    }
+
+    public Boolean(boolean v) {
+        value = v;
+    }
+
+    public boolean booleanValue() {
+        return value;
+    }
+
+    private boolean value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Byte.java b/langtools/test/tools/javac/synthesize/src/Byte.java
new file mode 100644
index 0000000..bf2a1fc
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Byte.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Byte
+{
+    public static Byte valueOf(byte v) {
+        return new Byte(v);
+    }
+
+    public Byte(byte v) {
+        value = v;
+    }
+
+    public byte byteValue() {
+        return value;
+    }
+
+    private byte value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Character.java b/langtools/test/tools/javac/synthesize/src/Character.java
new file mode 100644
index 0000000..99898ac
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Character.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Character
+{
+    public static Character valueOf(char v) {
+        return new Character(v);
+    }
+
+    public Character(char v) {
+        value = v;
+    }
+
+    public char characterValue() {
+        return value;
+    }
+
+    private char value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Cloneable.java b/langtools/test/tools/javac/synthesize/src/Cloneable.java
new file mode 100644
index 0000000..79022e0
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Cloneable.java
@@ -0,0 +1,27 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public interface Cloneable {
+}
diff --git a/langtools/test/tools/javac/synthesize/Double.java b/langtools/test/tools/javac/synthesize/src/Double.java
similarity index 100%
rename from langtools/test/tools/javac/synthesize/Double.java
rename to langtools/test/tools/javac/synthesize/src/Double.java
diff --git a/langtools/test/tools/javac/synthesize/Float.java b/langtools/test/tools/javac/synthesize/src/Float.java
similarity index 100%
rename from langtools/test/tools/javac/synthesize/Float.java
rename to langtools/test/tools/javac/synthesize/src/Float.java
diff --git a/langtools/test/tools/javac/synthesize/src/Integer.java b/langtools/test/tools/javac/synthesize/src/Integer.java
new file mode 100644
index 0000000..f3a59b9
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Integer.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Integer extends Number
+{
+    public static Integer valueOf(int v) {
+        return new Integer(v);
+    }
+
+    public Integer(int v) {
+        value = v;
+    }
+
+    public int integerValue() {
+        return value;
+    }
+
+    private int value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Long.java b/langtools/test/tools/javac/synthesize/src/Long.java
new file mode 100644
index 0000000..3973476
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Long.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Long extends Number
+{
+    public static Long valueOf(long v) {
+        return new Long(v);
+    }
+
+    public Long(long v) {
+        value = v;
+    }
+
+    public long longValue() {
+        return value;
+    }
+
+    private long value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Number.java b/langtools/test/tools/javac/synthesize/src/Number.java
new file mode 100644
index 0000000..1b8e8c9
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Number.java
@@ -0,0 +1,29 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Number
+{
+
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Object.java b/langtools/test/tools/javac/synthesize/src/Object.java
new file mode 100644
index 0000000..a07b573
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Object.java
@@ -0,0 +1,28 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Object
+{
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Serializable.java b/langtools/test/tools/javac/synthesize/src/Serializable.java
new file mode 100644
index 0000000..b7bc2d3
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Serializable.java
@@ -0,0 +1,27 @@
+/*
+ * 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
+ * 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 java.io;
+
+public interface Serializable {
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Short.java b/langtools/test/tools/javac/synthesize/src/Short.java
new file mode 100644
index 0000000..6d0a846
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Short.java
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Short extends Number
+{
+    public static Short valueOf(short v) {
+        return new Short(v);
+    }
+
+    public Short(short v) {
+        value = v;
+    }
+
+    public short shortValue() {
+        return value;
+    }
+
+    private short value;
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Test.java b/langtools/test/tools/javac/synthesize/src/Test.java
new file mode 100644
index 0000000..2b0c236
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Test.java
@@ -0,0 +1,32 @@
+/*
+ * 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
+ * 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 code (indirectly) requires the presence of
+// Cloneable and Serializable (supertypes for Java arrays)
+// Double and Float (for boxing/unboxing)
+public class Test
+{
+    Object f(boolean b, int[] array) {
+        return b ? array : 2;
+    }
+}
diff --git a/langtools/test/tools/javac/synthesize/src/Void.java b/langtools/test/tools/javac/synthesize/src/Void.java
new file mode 100644
index 0000000..40e8d29
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/Void.java
@@ -0,0 +1,29 @@
+/*
+ * 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
+ * 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 java.lang;
+
+public class Void
+{
+
+}
diff --git a/langtools/test/tools/javac/synthesize/src/module-info.java b/langtools/test/tools/javac/synthesize/src/module-info.java
new file mode 100644
index 0000000..2684ab5
--- /dev/null
+++ b/langtools/test/tools/javac/synthesize/src/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module java.base {
+    exports java.lang;
+}
+
diff --git a/langtools/test/tools/javac/tree/8067914/NukeExtraCast.java b/langtools/test/tools/javac/tree/8067914/NukeExtraCast.java
index cc09f99..dc3af94 100644
--- a/langtools/test/tools/javac/tree/8067914/NukeExtraCast.java
+++ b/langtools/test/tools/javac/tree/8067914/NukeExtraCast.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile -XD-printsource T8067914.java
  * @run main NukeExtraCast
diff --git a/langtools/test/tools/javac/tree/ArrayTypeToString.java b/langtools/test/tools/javac/tree/ArrayTypeToString.java
index 9ba24e5..a200f6d 100644
--- a/langtools/test/tools/javac/tree/ArrayTypeToString.java
+++ b/langtools/test/tools/javac/tree/ArrayTypeToString.java
@@ -27,7 +27,7 @@
  * @summary Tests ArrayType.toString with type annotations present
  * @modules jdk.compiler/com.sun.tools.javac.code
  * @build ArrayTypeToString
- * @compile/ref=ArrayTypeToString.out -XDrawDiagnostics -processor ArrayTypeToString -proc:only ArrayTypeToString.java
+ * @compile/ref=ArrayTypeToString.out -XDaccessInternalAPI -XDrawDiagnostics -processor ArrayTypeToString -proc:only ArrayTypeToString.java
  */
 
 import java.lang.annotation.ElementType;
@@ -56,7 +56,6 @@
 @SupportedAnnotationTypes("Foo")
 @SupportedSourceVersion(SourceVersion.RELEASE_9)
 public class ArrayTypeToString extends AbstractProcessor {
-
     @Foo(0) String @Foo(1)[] @Foo(2)[] @Foo(3)[] field;
 
     public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
diff --git a/langtools/test/tools/javac/tree/MakeTypeTest.java b/langtools/test/tools/javac/tree/MakeTypeTest.java
index 67a5059..f9495d5 100644
--- a/langtools/test/tools/javac/tree/MakeTypeTest.java
+++ b/langtools/test/tools/javac/tree/MakeTypeTest.java
@@ -32,7 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  * @build JavacTestingAbstractProcessor MakeTypeTest
- * @compile/process/ref=MakeTypeTest.out -processor MakeTypeTest MakeTypeTest.java
+ * @compile/process/ref=MakeTypeTest.out -XDaccessInternalAPI -processor MakeTypeTest MakeTypeTest.java
  */
 
 import java.lang.annotation.*;
@@ -54,7 +54,6 @@
 import com.sun.tools.javac.util.List;
 
 public class MakeTypeTest extends JavacTestingAbstractProcessor {
-
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (!roundEnv.processingOver())
@@ -135,7 +134,7 @@
         }.scan(path, null);
 
         unseenTypeKinds.removeAll(Arrays.asList(TypeKind.NONE, TypeKind.NULL, TypeKind.ERROR,
-                TypeKind.PACKAGE, TypeKind.EXECUTABLE, TypeKind.OTHER));
+                TypeKind.PACKAGE, TypeKind.EXECUTABLE, TypeKind.OTHER, TypeKind.MODULE));
 
         if (!unseenTypeKinds.isEmpty())
             throw new IllegalStateException("Unhandled types=" + unseenTypeKinds);
diff --git a/langtools/test/tools/javac/tree/ScopeTest.java b/langtools/test/tools/javac/tree/ScopeTest.java
index 2d154ba..3fff056 100644
--- a/langtools/test/tools/javac/tree/ScopeTest.java
+++ b/langtools/test/tools/javac/tree/ScopeTest.java
@@ -87,7 +87,7 @@
                 return packageClause + SOURCE_CODE;
             }
             @Override public boolean isNameCompatible(String simpleName, Kind kind) {
-                return true;
+                return !"module-info".equals(simpleName);
             }
         };
         Iterable<? extends JavaFileObject> fos = Collections.singletonList(source);
diff --git a/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java
index fcae7cc..cbfc178 100644
--- a/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java
+++ b/langtools/test/tools/javac/treeannotests/AnnoTreeTests.java
@@ -27,7 +27,7 @@
  *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
  * @build DA TA Test TestProcessor
- * @compile -proc:only -processor TestProcessor AnnoTreeTests.java
+ * @compile -XDaccessInternalAPI -proc:only -processor TestProcessor AnnoTreeTests.java
  */
 
 @Test(4)
diff --git a/langtools/test/tools/javac/treeannotests/TestProcessor.java b/langtools/test/tools/javac/treeannotests/TestProcessor.java
index 8b6c4ad..99fd780 100644
--- a/langtools/test/tools/javac/treeannotests/TestProcessor.java
+++ b/langtools/test/tools/javac/treeannotests/TestProcessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -21,6 +21,8 @@
  * questions.
  */
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.io.*;
 import java.util.*;
 import javax.annotation.processing.*;
diff --git a/langtools/test/tools/javac/types/ScopeListenerTest.java b/langtools/test/tools/javac/types/ScopeListenerTest.java
index f9bd305..9173ac4 100644
--- a/langtools/test/tools/javac/types/ScopeListenerTest.java
+++ b/langtools/test/tools/javac/types/ScopeListenerTest.java
@@ -26,6 +26,9 @@
  * @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
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.util
  */
 
 import com.sun.tools.javac.code.Scope;
diff --git a/langtools/test/tools/javac/types/TestComparisons.java b/langtools/test/tools/javac/types/TestComparisons.java
index 6d16002..7d6d98a 100644
--- a/langtools/test/tools/javac/types/TestComparisons.java
+++ b/langtools/test/tools/javac/types/TestComparisons.java
@@ -27,9 +27,7 @@
  * @summary javac should correctly enforce binary comparison rules.
  * @modules jdk.compiler
  */
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Symbol.*;
+
 import java.io.*;
 import java.lang.reflect.Array;
 import java.util.EnumSet;
diff --git a/langtools/test/tools/javac/util/T6597678.java b/langtools/test/tools/javac/util/T6597678.java
index 4a7bcf0..53ce500 100644
--- a/langtools/test/tools/javac/util/T6597678.java
+++ b/langtools/test/tools/javac/util/T6597678.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
@@ -39,7 +39,6 @@
 import javax.lang.model.element.TypeElement;
 import javax.tools.Diagnostic;
 
-
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JavacMessages;
@@ -60,6 +59,10 @@
         PrintWriter pw = new PrintWriter(sw);
 
         compile(sw, pw,
+            "-XaddExports:"
+                + "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED,"
+                + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+            "-XDaccessInternalAPI",
             "-proc:only",
             "-processor", myName,
             "-AWriterString=" + pw.toString(),
diff --git a/langtools/test/tools/javac/warnings/6594914/T6594914b.out b/langtools/test/tools/javac/warnings/6594914/T6594914b.out
index 184d9dc..2c2735b 100644
--- a/langtools/test/tools/javac/warnings/6594914/T6594914b.out
+++ b/langtools/test/tools/javac/warnings/6594914/T6594914b.out
@@ -1,3 +1,4 @@
+- compiler.warn.source.no.bootclasspath: 1.8
 T6594914b.java:12:22: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
 T6594914b.java:17:33: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
 T6594914b.java:18:22: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
@@ -6,4 +7,4 @@
 T6594914b.java:27:26: compiler.warn.sun.proprietary: sun.security.x509.X509CertInfo
 - compiler.note.deprecated.filename: T6594914b.java
 - compiler.note.deprecated.recompile
-6 warnings
+7 warnings
diff --git a/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java b/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java
index c153ee8..cd90af2 100644
--- a/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java
+++ b/langtools/test/tools/javac/warnings/VerifyLintDescriptions.java
@@ -29,6 +29,8 @@
  *          jdk.compiler/com.sun.tools.javac.util
  */
 
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -39,8 +41,11 @@
 
 public class VerifyLintDescriptions {
     public static void main(String... args) {
+        Layer boot = Layer.boot();
+        Module jdk_compiler = boot.findModule("jdk.compiler").get();
         ResourceBundle b = ResourceBundle.getBundle("com.sun.tools.javac.resources.javac",
-                                                    Locale.US);
+                                                    Locale.US,
+                                                    jdk_compiler);
 
         List<String> missing = new ArrayList<>();
 
diff --git a/langtools/test/tools/javadoc/6227454/Test.java b/langtools/test/tools/javadoc/6227454/Test.java
index c22bee7..fcdc34f 100644
--- a/langtools/test/tools/javadoc/6227454/Test.java
+++ b/langtools/test/tools/javadoc/6227454/Test.java
@@ -68,10 +68,6 @@
         String thisClassName = Test.class.getName();
         File testSrc = new File(System.getProperty("test.src"));
         String[] args = {
-            "-bootclasspath",
-                System.getProperty("java.class.path")
-                + File.pathSeparator
-                + System.getProperty("sun.boot.class.path"),
             "-classpath", ".",
             "-package",
             "-overview", file.getPath(),
diff --git a/langtools/test/tools/javadoc/6964914/Test.java b/langtools/test/tools/javadoc/6964914/Test.java
index b6ee108..307b5c1 100644
--- a/langtools/test/tools/javadoc/6964914/Test.java
+++ b/langtools/test/tools/javadoc/6964914/Test.java
@@ -48,7 +48,6 @@
         String[] args = {
             "-Xdoclint:none",
             "-source", "8",
-            "-bootclasspath", System.getProperty("sun.boot.class.path"),
             "-classpath", ".",
             "-package",
             new File(testSrc, path).getPath()
diff --git a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java
index 08c99a4..d30ae83 100644
--- a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java
+++ b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -56,7 +56,7 @@
         String thisClassName = TestStdDoclet.class.getName();
         Process p = new ProcessBuilder()
             .command(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
+                "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""),
                 "-classpath", ".", // insulates us from ambient classpath
                 "-Xdoclint:none",
                 "-package",
diff --git a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java b/langtools/test/tools/javadoc/6964914/TestUserDoclet.java
index 6d84975..a098470 100644
--- a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java
+++ b/langtools/test/tools/javadoc/6964914/TestUserDoclet.java
@@ -57,7 +57,7 @@
         String thisClassName = TestUserDoclet.class.getName();
         Process p = new ProcessBuilder()
             .command(javadoc.getPath(),
-                "-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path"),
+                "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""),
                 "-doclet", thisClassName,
                 "-docletpath", testClasses.getPath(),
                 new File(testSrc, thisClassName + ".java").getPath())
diff --git a/langtools/test/tools/javadoc/CheckResourceKeys.java b/langtools/test/tools/javadoc/CheckResourceKeys.java
index bfbe508..7dbd163 100644
--- a/langtools/test/tools/javadoc/CheckResourceKeys.java
+++ b/langtools/test/tools/javadoc/CheckResourceKeys.java
@@ -29,6 +29,8 @@
  */
 
 import java.io.*;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
 import java.util.*;
 import javax.tools.*;
 import com.sun.tools.classfile.*;
@@ -224,6 +226,7 @@
      * Get the set of keys from the javadoc resource bundles.
      */
     Set<String> getResourceKeys() {
+        Module jdk_javadoc = Layer.boot().findModule("jdk.javadoc").get();
         String[] names = {
                 "com.sun.tools.doclets.formats.html.resources.standard",
                 "com.sun.tools.doclets.internal.toolkit.resources.doclets",
@@ -231,7 +234,7 @@
         };
         Set<String> results = new TreeSet<String>();
         for (String name : names) {
-            ResourceBundle b = ResourceBundle.getBundle(name);
+            ResourceBundle b = ResourceBundle.getBundle(name, jdk_javadoc);
             results.addAll(b.keySet());
         }
         return results;
diff --git a/langtools/test/tools/javadoc/CompletionError.java b/langtools/test/tools/javadoc/CompletionError.java
index 2e2e6f9..11a12f6 100644
--- a/langtools/test/tools/javadoc/CompletionError.java
+++ b/langtools/test/tools/javadoc/CompletionError.java
@@ -28,6 +28,7 @@
  *          the javadoc API clients.
  * @library /tools/lib
  * @modules jdk.javadoc com.sun.tools.javac.api
+ *          jdk.jdeps/com.sun.tools.javap
  * @run main CompletionError
  */
 
diff --git a/langtools/test/tools/javadoc/api/basic/TagletPathTest.java b/langtools/test/tools/javadoc/api/basic/TagletPathTest.java
index 0d221e0..54d26e7 100644
--- a/langtools/test/tools/javadoc/api/basic/TagletPathTest.java
+++ b/langtools/test/tools/javadoc/api/basic/TagletPathTest.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
@@ -27,6 +27,7 @@
  * @summary javadoc should have a javax.tools.Tool service provider
  * @modules java.compiler
  *          jdk.compiler
+ *          jdk.javadoc/com.sun.tools.doclets.standard
  * @build APITest
  * @run main TagletPathTest
  */
diff --git a/langtools/test/tools/javah/6257087/T6257087.java b/langtools/test/tools/javah/6257087/T6257087.java
index dcdeff0..89bf977 100644
--- a/langtools/test/tools/javah/6257087/T6257087.java
+++ b/langtools/test/tools/javah/6257087/T6257087.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main T6257087
  */
diff --git a/langtools/test/tools/javah/ModuleClass.java b/langtools/test/tools/javah/ModuleClass.java
new file mode 100644
index 0000000..8286947
--- /dev/null
+++ b/langtools/test/tools/javah/ModuleClass.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8049811
+ * @summary javah should accept module/class names
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build ToolBox
+ * @run main ModuleClass
+ */
+
+import java.util.List;
+
+public class ModuleClass {
+    static public void main(String[] args) throws Exception {
+        ToolBox tb = new ToolBox();
+        check(tb, "java.lang.Object");
+        check(tb, "java.base/java.io.File");
+    }
+
+    static void check(ToolBox tb, String name) throws Exception {
+        tb.new JavahTask()
+                .classes(name)
+                .run();
+
+        int sep = name.indexOf("/");
+        String className = (sep == -1) ? name : name.substring(sep + 1);
+        String file = className.replace(".", "_") + ".h";
+        List<String> outObject = tb.readAllLines(file);
+
+        String text = "#ifndef _Included_" + className.replace(".", "_");
+        if (!outObject.contains(text)) {
+            throw new Exception("expected line not found");
+        }
+    }
+}
+
diff --git a/langtools/test/tools/javah/T4942232/MissingParamClassTest.java b/langtools/test/tools/javah/T4942232/MissingParamClassTest.java
index 0499d53..639155e 100644
--- a/langtools/test/tools/javah/T4942232/MissingParamClassTest.java
+++ b/langtools/test/tools/javah/T4942232/MissingParamClassTest.java
@@ -31,6 +31,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run compile MissingParamClassTest.java
  * @clean MissingParamClassException
diff --git a/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java b/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java
index 3025a3d..927b2ed 100644
--- a/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java
+++ b/langtools/test/tools/javah/constMacroTest/ConstMacroTest.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
@@ -31,6 +31,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main ConstMacroTest
  */
diff --git a/langtools/test/tools/javap/4111861/T4111861.java b/langtools/test/tools/javap/4111861/T4111861.java
index f56b446..45fa22b 100644
--- a/langtools/test/tools/javap/4111861/T4111861.java
+++ b/langtools/test/tools/javap/4111861/T4111861.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @test
  * @bug 4111861
  * @summary static final field contents are not displayed
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 public class T4111861 {
     public static void main(String... args) throws Exception {
diff --git a/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java b/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java
index 2371f30..be877a3 100644
--- a/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java
+++ b/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main JavapShouldLoadClassesFromRTJarTest
  */
diff --git a/langtools/test/tools/javap/4866831/PublicInterfaceTest.java b/langtools/test/tools/javap/4866831/PublicInterfaceTest.java
index bf129df..b3a125a 100644
--- a/langtools/test/tools/javap/4866831/PublicInterfaceTest.java
+++ b/langtools/test/tools/javap/4866831/PublicInterfaceTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main PublicInterfaceTest
  */
diff --git a/langtools/test/tools/javap/4870651/T4870651.java b/langtools/test/tools/javap/4870651/T4870651.java
index a47e7cf..73e8851 100644
--- a/langtools/test/tools/javap/4870651/T4870651.java
+++ b/langtools/test/tools/javap/4870651/T4870651.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug 4870651 6715757
  * @summary javap should recognize generics, varargs, enum;
  *          javap prints "extends java.lang.Object"
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @build T4870651 Test
  * @run main T4870651
  */
diff --git a/langtools/test/tools/javap/6937244/T6937244.java b/langtools/test/tools/javap/6937244/T6937244.java
index b122a2b..13fc1f9 100644
--- a/langtools/test/tools/javap/6937244/T6937244.java
+++ b/langtools/test/tools/javap/6937244/T6937244.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6937244
  * @summary fields display with JVMS names, not Java names
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/6937244/T6937244A.java b/langtools/test/tools/javap/6937244/T6937244A.java
index d9518f1..324e5c2 100644
--- a/langtools/test/tools/javap/6937244/T6937244A.java
+++ b/langtools/test/tools/javap/6937244/T6937244A.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 6937244
  * @summary fields display with JVMS names, not Java names
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/8006334/JavapTaskCtorFailWithNPE.java b/langtools/test/tools/javap/8006334/JavapTaskCtorFailWithNPE.java
index 6c1b70e..6c9fd94 100644
--- a/langtools/test/tools/javap/8006334/JavapTaskCtorFailWithNPE.java
+++ b/langtools/test/tools/javap/8006334/JavapTaskCtorFailWithNPE.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
@@ -26,7 +26,7 @@
  * @bug 8006334
  * @summary javap: JavapTask constructor breaks with null pointer exception if
  * parameter options is null
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.File;
diff --git a/langtools/test/tools/javap/8007907/JavapReturns0AfterClassNotFoundTest.java b/langtools/test/tools/javap/8007907/JavapReturns0AfterClassNotFoundTest.java
index e32b88d..ea679ce 100644
--- a/langtools/test/tools/javap/8007907/JavapReturns0AfterClassNotFoundTest.java
+++ b/langtools/test/tools/javap/8007907/JavapReturns0AfterClassNotFoundTest.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
@@ -26,7 +26,7 @@
  * @bug 8007907
  * @summary javap, method com.sun.tools.javap.Main.run returns 0 even in case
  * of class not found error
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.IOException;
diff --git a/langtools/test/tools/javap/AccessModifiers.java b/langtools/test/tools/javap/AccessModifiers.java
index b1b7cf7..618d8cb 100644
--- a/langtools/test/tools/javap/AccessModifiers.java
+++ b/langtools/test/tools/javap/AccessModifiers.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8027530
  * @summary test -public, -protected, -package, -private options
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/BadAttributeLength.java b/langtools/test/tools/javap/BadAttributeLength.java
index 2cd6a3f..e39301e 100644
--- a/langtools/test/tools/javap/BadAttributeLength.java
+++ b/langtools/test/tools/javap/BadAttributeLength.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8047072
  * @summary javap OOM on fuzzed classfile
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @run main BadAttributeLength
  */
 
diff --git a/langtools/test/tools/javap/BoundsTypeVariableTest.java b/langtools/test/tools/javap/BoundsTypeVariableTest.java
index ce3d8df..9f54ede 100644
--- a/langtools/test/tools/javap/BoundsTypeVariableTest.java
+++ b/langtools/test/tools/javap/BoundsTypeVariableTest.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8003537
  * @summary javap should not use / in Bounds Type Variables
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.File;
diff --git a/langtools/test/tools/javap/DescriptorTest.java b/langtools/test/tools/javap/DescriptorTest.java
index 43acbf5..182621f 100644
--- a/langtools/test/tools/javap/DescriptorTest.java
+++ b/langtools/test/tools/javap/DescriptorTest.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
@@ -25,7 +25,7 @@
  * @test
  * @bug     8007052
  * @summary javap should include the descriptor for a method in verbose mode
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.File;
diff --git a/langtools/test/tools/javap/ExtPath.java b/langtools/test/tools/javap/ExtPath.java
index 2ce3e5d..ca20cc5 100644
--- a/langtools/test/tools/javap/ExtPath.java
+++ b/langtools/test/tools/javap/ExtPath.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
@@ -26,7 +26,7 @@
  * @bug     6428896
  * @summary javap cannot read multiple entries on the extension classpath
  * @author  Wei Tao
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @run main/othervm ExtPath com.sun.crypto.provider.SunJCE
  */
 
diff --git a/langtools/test/tools/javap/InvalidOptions.java b/langtools/test/tools/javap/InvalidOptions.java
index b9dda95..8ddfae6 100644
--- a/langtools/test/tools/javap/InvalidOptions.java
+++ b/langtools/test/tools/javap/InvalidOptions.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8027411 8032869
  * @summary test an invalid option
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/MethodParameters.java b/langtools/test/tools/javap/MethodParameters.java
index 673d097..6052f63 100644
--- a/langtools/test/tools/javap/MethodParameters.java
+++ b/langtools/test/tools/javap/MethodParameters.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 8004727 8005647
  * @summary javac should generate method parameters correctly.
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/StackMapTableTest.java b/langtools/test/tools/javap/StackMapTableTest.java
index 22c915e..87a1e33 100644
--- a/langtools/test/tools/javap/StackMapTableTest.java
+++ b/langtools/test/tools/javap/StackMapTableTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8033930 8033913
  * @summary bad formatting of StackMapTable entries
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4075403.java b/langtools/test/tools/javap/T4075403.java
index 836fd80..48ee632 100644
--- a/langtools/test/tools/javap/T4075403.java
+++ b/langtools/test/tools/javap/T4075403.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4075403
  * @summary Use javap to inquire about a specific inner class
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 
diff --git a/langtools/test/tools/javap/T4459541.java b/langtools/test/tools/javap/T4459541.java
index eeb3754..10887ad 100644
--- a/langtools/test/tools/javap/T4459541.java
+++ b/langtools/test/tools/javap/T4459541.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4459541
  * @summary "javap -l" shows line numbers as signed short; they should be unsigned.
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4501660.java b/langtools/test/tools/javap/T4501660.java
index aa8f4d4..e046188 100644
--- a/langtools/test/tools/javap/T4501660.java
+++ b/langtools/test/tools/javap/T4501660.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug 4501660
  * @summary change diagnostic of -help as 'print this help message and exit'
  *            (actually, verify -help does not cause premature exit)
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4501661.java b/langtools/test/tools/javap/T4501661.java
index 6d07d1c..55661ad 100644
--- a/langtools/test/tools/javap/T4501661.java
+++ b/langtools/test/tools/javap/T4501661.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  * @test
  * @bug 4501661
  * @summary disallow mixing -public, -private, and -protected
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 public class T4501661 {
     public static void main(String... args) throws Exception {
diff --git a/langtools/test/tools/javap/T4777949.java b/langtools/test/tools/javap/T4777949.java
index 3fa1497..00fe821 100644
--- a/langtools/test/tools/javap/T4777949.java
+++ b/langtools/test/tools/javap/T4777949.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,17 +21,18 @@
  * questions.
  */
 
+/*
+ * @test
+ * @bug 4777949
+ * @summary Warn javap usage on package with simple name
+ * @modules jdk.jdeps/com.sun.tools.javap
+ */
+
 import java.io.*;
 import java.util.*;
 import javax.tools.*;
 import com.sun.tools.javap.*;
 
-/*
- * @test
- * @bug 4777949
- * @summary Warn javap usage on package with simple name
- * @modules jdk.jdeps
- */
 public class T4777949 {
     public static void main(String... args) throws Exception {
         new T4777949().run();
diff --git a/langtools/test/tools/javap/T4876942.java b/langtools/test/tools/javap/T4876942.java
index b5f5a99..0570b58 100644
--- a/langtools/test/tools/javap/T4876942.java
+++ b/langtools/test/tools/javap/T4876942.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4876942 6715251
  * @summary javap invoked without args does not print help screen
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4880663.java b/langtools/test/tools/javap/T4880663.java
index f6051c5..4ee8b37 100644
--- a/langtools/test/tools/javap/T4880663.java
+++ b/langtools/test/tools/javap/T4880663.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug 4880663 6715757 7031005
  * @summary javap could output whitespace between class name and opening brace
  *          javap prints "extends java.lang.Object"
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 
diff --git a/langtools/test/tools/javap/T4880672.java b/langtools/test/tools/javap/T4880672.java
index 922c1ae..2727b65 100644
--- a/langtools/test/tools/javap/T4880672.java
+++ b/langtools/test/tools/javap/T4880672.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4880672 7031005
  * @summary javap does not output inner interfaces of an interface
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4884240.java b/langtools/test/tools/javap/T4884240.java
index 4870e5f..bd3f04f 100644
--- a/langtools/test/tools/javap/T4884240.java
+++ b/langtools/test/tools/javap/T4884240.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4884240
  * @summary additional option required for javap
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T4975569.java b/langtools/test/tools/javap/T4975569.java
index d6b72ff..ae117c6 100644
--- a/langtools/test/tools/javap/T4975569.java
+++ b/langtools/test/tools/javap/T4975569.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 4975569 6622215 8034861
  * @summary javap doesn't print new flag bits
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6271787.java b/langtools/test/tools/javap/T6271787.java
index c7e7971..f96ae49 100644
--- a/langtools/test/tools/javap/T6271787.java
+++ b/langtools/test/tools/javap/T6271787.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6271787
  * @summary javap dumps LocalVariableTypeTable attribute in hex, needs to print a table
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6474890.java b/langtools/test/tools/javap/T6474890.java
index 0122898..18778a3 100644
--- a/langtools/test/tools/javap/T6474890.java
+++ b/langtools/test/tools/javap/T6474890.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6474890
  * @summary javap does not open .zip files in -classpath
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6587786.java b/langtools/test/tools/javap/T6587786.java
index 4341996..950ff20 100644
--- a/langtools/test/tools/javap/T6587786.java
+++ b/langtools/test/tools/javap/T6587786.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6587786
  * @summary Javap throws error : "ERROR:Could not find <classname>" for JRE classes
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6622216.java b/langtools/test/tools/javap/T6622216.java
index c9324c8..9a35908 100644
--- a/langtools/test/tools/javap/T6622216.java
+++ b/langtools/test/tools/javap/T6622216.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6622216
  * @summary javap names some attributes incorrectly
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6622232.java b/langtools/test/tools/javap/T6622232.java
index a7ae56c..56c14f7 100644
--- a/langtools/test/tools/javap/T6622232.java
+++ b/langtools/test/tools/javap/T6622232.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6622232
  * @summary javap gets whitespace confused
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6622260.java b/langtools/test/tools/javap/T6622260.java
index c0bb15f..af196e6 100644
--- a/langtools/test/tools/javap/T6622260.java
+++ b/langtools/test/tools/javap/T6622260.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6622260
  * @summary javap prints negative bytes incorrectly in hex
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6715251.java b/langtools/test/tools/javap/T6715251.java
index 4c61a64..af37981 100644
--- a/langtools/test/tools/javap/T6715251.java
+++ b/langtools/test/tools/javap/T6715251.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,16 +21,16 @@
  * questions.
  */
 
-import java.io.*;
-import java.util.*;
-
 /*
  * @test
  * @bug 6715251
  * @summary javap should be consistent with javac and return 2 if given no arguments
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
+import java.io.*;
+import java.util.*;
+
 public class T6715251 {
     public static void main(String... args) throws Exception {
         new T6715251().run();
diff --git a/langtools/test/tools/javap/T6715753.java b/langtools/test/tools/javap/T6715753.java
index 3d69d24..54cfda5 100644
--- a/langtools/test/tools/javap/T6715753.java
+++ b/langtools/test/tools/javap/T6715753.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,15 +21,15 @@
  * questions.
  */
 
-import java.io.*;
-
 /*
  * @test
  * @bug 6715753
  * @summary Use javap to inquire about a specific inner class
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
+import java.io.*;
+
 public class T6715753 {
     public static void main(String... args) throws Exception {
         new T6715753().run();
diff --git a/langtools/test/tools/javap/T6715767.java b/langtools/test/tools/javap/T6715767.java
index 30fbd06..b746701 100644
--- a/langtools/test/tools/javap/T6715767.java
+++ b/langtools/test/tools/javap/T6715767.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6715767
  * @summary javap on java.lang.ClassLoader crashes
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6729471.java b/langtools/test/tools/javap/T6729471.java
index b54f8fe..51c9fc5 100644
--- a/langtools/test/tools/javap/T6729471.java
+++ b/langtools/test/tools/javap/T6729471.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main T6729471
  */
diff --git a/langtools/test/tools/javap/T6824493.java b/langtools/test/tools/javap/T6824493.java
index dda6f1e..ee26e26 100644
--- a/langtools/test/tools/javap/T6824493.java
+++ b/langtools/test/tools/javap/T6824493.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  * @test
  * @bug 6824493
  * @summary experimental support for additional info for instructions
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @compile -g T6824493.java
  * @run main T6824493
  */
diff --git a/langtools/test/tools/javap/T6863746.java b/langtools/test/tools/javap/T6863746.java
index 93ddf4d..c9ed85f 100644
--- a/langtools/test/tools/javap/T6863746.java
+++ b/langtools/test/tools/javap/T6863746.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @test
  * @bug 6863746
  * @summary javap should not scan ct.sym by default
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 public class T6863746 {
diff --git a/langtools/test/tools/javap/T6866657.java b/langtools/test/tools/javap/T6866657.java
index f9046fe..4273b03 100644
--- a/langtools/test/tools/javap/T6866657.java
+++ b/langtools/test/tools/javap/T6866657.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
  * @bug 6866657
  * @summary add byteLength() method to primary classfile types
  * @modules jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6868539.java b/langtools/test/tools/javap/T6868539.java
index c02493b..c4a5643 100644
--- a/langtools/test/tools/javap/T6868539.java
+++ b/langtools/test/tools/javap/T6868539.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug 6868539 6868548 8035364
  * @summary javap should use current names for constant pool entries,
  *              remove spurious ';' from constant pool entries
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6879371.java b/langtools/test/tools/javap/T6879371.java
index 87c2469..ee1761b 100644
--- a/langtools/test/tools/javap/T6879371.java
+++ b/langtools/test/tools/javap/T6879371.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6879371
  * @summary javap does not close internal default file manager
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T6980017.java b/langtools/test/tools/javap/T6980017.java
index 1f607fc..69ac1fa 100644
--- a/langtools/test/tools/javap/T6980017.java
+++ b/langtools/test/tools/javap/T6980017.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
@@ -26,6 +26,7 @@
  * @bug 6980017
  * @summary javap -XDdetail:source behaves badly if source not available.
  * @modules jdk.compiler
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T7004698.java b/langtools/test/tools/javap/T7004698.java
index ad84701..2a23976 100644
--- a/langtools/test/tools/javap/T7004698.java
+++ b/langtools/test/tools/javap/T7004698.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
@@ -25,7 +25,7 @@
  * @test
  * @bug 7004698
  * @summary javap does not output CharacterRangeTable attributes correctly
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
@@ -41,7 +41,10 @@
         File srcDir = new File(System.getProperty("test.src"));
         File srcFile = new File(srcDir, T7004698.class.getSimpleName() + ".java");
         File classesDir = new File(".");
-        compile("-Xjcov", "-d", classesDir.getPath(), srcFile.getPath());
+        compile("-Xjcov",
+                "-XaddExports:jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED",
+                "-d", classesDir.getPath(),
+                srcFile.getPath());
 
         File classFile = new File(classesDir, T7004698.class.getSimpleName() + ".class");
         String out = javap("-v", classFile.getPath());
diff --git a/langtools/test/tools/javap/T7186925.java b/langtools/test/tools/javap/T7186925.java
index c081955..8309ec0 100644
--- a/langtools/test/tools/javap/T7186925.java
+++ b/langtools/test/tools/javap/T7186925.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
@@ -26,6 +26,7 @@
  * @bug 7186925
  * @summary JavapTask passes null to java.io.Writer
  * @modules jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T7190862.java b/langtools/test/tools/javap/T7190862.java
index 103236b..6c9dbc0 100644
--- a/langtools/test/tools/javap/T7190862.java
+++ b/langtools/test/tools/javap/T7190862.java
@@ -3,7 +3,7 @@
  * @test /nodynamiccopyright/
  * @bug 7190862 7109747
  * @summary javap shows an incorrect type for operands if the 'wide' prefix is used
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import com.sun.source.util.JavacTask;
diff --git a/langtools/test/tools/javap/T8032814.java b/langtools/test/tools/javap/T8032814.java
index 16d9295..2c83fd3 100644
--- a/langtools/test/tools/javap/T8032814.java
+++ b/langtools/test/tools/javap/T8032814.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,7 +26,7 @@
  * @bug 8032814
  * @summary LineNumberTable/LocalVariableTable tables duplication for the
  *          "-v -l" combination of options
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @compile -g T8032814.java
  * @run main T8032814
  */
diff --git a/langtools/test/tools/javap/T8032819.java b/langtools/test/tools/javap/T8032819.java
index d42b101..5fdd7eb 100644
--- a/langtools/test/tools/javap/T8032819.java
+++ b/langtools/test/tools/javap/T8032819.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8032819
  * @summary Extra empty line between field declarations for the "-v -c" and "-v -l" combination of options
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  * @compile -g T8032819.java
  * @run main T8032819
  */
diff --git a/langtools/test/tools/javap/T8033180.java b/langtools/test/tools/javap/T8033180.java
index d06ef16..0edc325 100644
--- a/langtools/test/tools/javap/T8033180.java
+++ b/langtools/test/tools/javap/T8033180.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8033180
  * @summary Bad newline characters
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T8033711.java b/langtools/test/tools/javap/T8033711.java
index ea3210b..1e4745c 100644
--- a/langtools/test/tools/javap/T8033711.java
+++ b/langtools/test/tools/javap/T8033711.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,9 @@
  * @test
  * @bug 8033711
  * @summary An exception is thrown if using the "-classpath" option with no arguments
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
-
 import java.io.*;
 
 public class T8033711 {
diff --git a/langtools/test/tools/javap/T8035104.java b/langtools/test/tools/javap/T8035104.java
index 2b798ed..9d93a8b 100644
--- a/langtools/test/tools/javap/T8035104.java
+++ b/langtools/test/tools/javap/T8035104.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8035104
  * @summary reorder class file attributes in javap listing
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/T8038414.java b/langtools/test/tools/javap/T8038414.java
index a2602b5..8963336 100644
--- a/langtools/test/tools/javap/T8038414.java
+++ b/langtools/test/tools/javap/T8038414.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
@@ -21,6 +21,13 @@
  * questions.
  */
 
+/*
+ * @test
+ * @bug 8038414
+ * @summary Constant pool's strings are not escaped properly
+ * @modules jdk.jdeps/com.sun.tools.javap
+ */
+
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -28,12 +35,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-/*
- * @test
- * @bug 8038414
- * @summary Constant pool's strings are not escaped properly
- * @modules jdk.jdeps
- */
 public class T8038414 {
     private static final String NEW_LINE = System.getProperty("line.separator");
     private static final String TEST_CLASSES = System.getProperty("test.classes", ".");
diff --git a/langtools/test/tools/javap/TestSuperclass.java b/langtools/test/tools/javap/TestSuperclass.java
index 99b4896..02fcbf6 100644
--- a/langtools/test/tools/javap/TestSuperclass.java
+++ b/langtools/test/tools/javap/TestSuperclass.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 7031005
  * @summary javap prints "extends java.lang.Object"
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.File;
diff --git a/langtools/test/tools/javap/WhitespaceTest.java b/langtools/test/tools/javap/WhitespaceTest.java
index 68deb2b..e65bcd3 100644
--- a/langtools/test/tools/javap/WhitespaceTest.java
+++ b/langtools/test/tools/javap/WhitespaceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8033581 8033798 8033726
  * @summary Check whitespace in generated output
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
 import java.io.*;
diff --git a/langtools/test/tools/javap/classfile/6888367/T6888367.java b/langtools/test/tools/javap/classfile/6888367/T6888367.java
index 7885f61..232f1e0 100644
--- a/langtools/test/tools/javap/classfile/6888367/T6888367.java
+++ b/langtools/test/tools/javap/classfile/6888367/T6888367.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -24,6 +24,7 @@
 import java.io.*;
 import java.net.*;
 import java.util.*;
+
 import com.sun.tools.classfile.*;
 import com.sun.tools.classfile.Type.ArrayType;
 import com.sun.tools.classfile.Type.ClassSigType;
diff --git a/langtools/test/tools/javap/stackmap/StackmapTest.java b/langtools/test/tools/javap/stackmap/StackmapTest.java
index cde6a81..708190b 100644
--- a/langtools/test/tools/javap/stackmap/StackmapTest.java
+++ b/langtools/test/tools/javap/stackmap/StackmapTest.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
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build ToolBox
  * @run main StackmapTest
  */
diff --git a/langtools/test/tools/javap/typeAnnotations/T6855990.java b/langtools/test/tools/javap/typeAnnotations/T6855990.java
index 6f7e7db..d27101f 100644
--- a/langtools/test/tools/javap/typeAnnotations/T6855990.java
+++ b/langtools/test/tools/javap/typeAnnotations/T6855990.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,15 +21,15 @@
  * questions.
  */
 
-import java.io.*;
-
 /*
  * @test
  * @bug 6855990
  * @summary InstructionDetailWriter should support new 308 annotations attribute
- * @modules jdk.jdeps
+ * @modules jdk.jdeps/com.sun.tools.javap
  */
 
+import java.io.*;
+
 public class T6855990 {
     public static void main(String[] args) throws Exception {
         new T6855990().run();
diff --git a/langtools/test/tools/jdeps/APIDeps.java b/langtools/test/tools/jdeps/APIDeps.java
index 4677f41..7b9450e 100644
--- a/langtools/test/tools/jdeps/APIDeps.java
+++ b/langtools/test/tools/jdeps/APIDeps.java
@@ -29,7 +29,6 @@
  *          java.management
  *          jdk.jdeps/com.sun.tools.classfile
  *          jdk.jdeps/com.sun.tools.jdeps
- * @build m.Bar m.Foo m.Gee b.B c.C c.I d.D e.E f.F g.G
  * @run main APIDeps
  */
 
@@ -37,10 +36,10 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.nio.file.*;
 import java.util.*;
 import java.util.regex.*;
+import java.util.stream.Collectors;
 
 public class APIDeps {
     public static void main(String... args) throws Exception {
@@ -50,8 +49,42 @@
             throw new Exception(errors + " errors found");
     }
 
+    private static final Path dest = Paths.get(System.getProperty("test.classes", "."), "tmp");
+    private static final String[] srcDirs = new String[] {
+            "m", "b", "c", "d", "e", "f", "g"
+    };
+    void setup(Path dest) throws IOException {
+        CompilerUtils.cleanDir(dest);
+        Files.createDirectories(dest);
+        Path testsrc = Paths.get(System.getProperty("test.src"));
+        List<String> options = new ArrayList<>();
+
+        // add -XaddExports
+        String testModules = System.getProperty("test.modules", "");
+        List<String> addExports = new ArrayList<>();
+        for (String s : testModules.split("\\s+")) {
+            if (s.isEmpty()) continue;
+            if (s.indexOf('/') != -1)
+                addExports.add(s.trim() + "=ALL-UNNAMED");
+        }
+        if (addExports.size() > 0) {
+            options.add(addExports.stream().collect(Collectors.joining(",", "-XaddExports:", "")));
+        }
+
+        for (String dir : srcDirs) {
+            Path source = testsrc.resolve(dir);
+            boolean ok = CompilerUtils.compile(source, dest, options.toArray(new String[0]));
+            if (!ok) {
+                throw new RuntimeException("compilation fails");
+            }
+        }
+    }
+
     int run() throws IOException {
-        File testDir = new File(System.getProperty("test.classes", "."));
+        // compile classes in a separate directory for analysis
+        setup(dest);
+
+        File testDir = dest.toFile();
         String testDirBasename = testDir.toPath().getFileName().toString();
         File mDir = new File(testDir, "m");
         // all dependencies
@@ -81,13 +114,14 @@
         test(new File(mDir, "Gee.class"),
              new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.classfile.ClassFile"},
              new String[] {"JDK internal API"},
-             new String[] {"-jdkinternals"});
+             new String[] {"-jdkinternals", "-quiet"});
         // -jdkinternals parses all classes on -classpath and the input arguments
         test(new File(mDir, "Gee.class"),
-             new String[] {"com.sun.tools.jdeps.Main", "com.sun.tools.classfile.ClassFile",
-                           "sun.security.x509.X509CertInfo", "sun.misc.Unsafe"},
+             new String[] {"com.sun.tools.classfile.ClassFile",
+                           "sun.security.x509.X509CertInfo"},
              new String[] {"JDK internal API"},
-             new String[] {"-classpath", testDir.getPath(), "-jdkinternals"});
+             // use -classpath tmp/a with no use of JDK internal API
+             new String[] {"-classpath", dest.resolve("a").toString(), "-jdkinternals", "-quiet"});
 
         // parse only APIs
         test(mDir,
@@ -196,4 +230,5 @@
     }
 
     int errors;
+
 }
diff --git a/langtools/test/tools/jdeps/Basic.java b/langtools/test/tools/jdeps/Basic.java
index 7a884b0..fac5493 100644
--- a/langtools/test/tools/jdeps/Basic.java
+++ b/langtools/test/tools/jdeps/Basic.java
@@ -27,7 +27,7 @@
  * @summary Basic tests for jdeps tool
  * @modules java.management
  *          jdk.jdeps/com.sun.tools.jdeps
- * @build Test p.Foo p.Bar p.C p.SubClass q.Gee javax.activity.NotCompactProfile
+ * @build Test p.Foo p.Bar p.C p.SubClass q.Gee
  * @run main Basic
  */
 
@@ -37,7 +37,6 @@
 import java.io.StringWriter;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.*;
 import java.util.regex.*;
 import static java.nio.file.StandardCopyOption.*;
@@ -57,10 +56,9 @@
              new String[] {"java.lang", "p"},
              new String[] {"compact1", "not found"});
         // test a directory
-        // also test non-SE javax.activity class dependency
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", "compact1"},
              new String[] {"-classpath", testDir.getPath()});
         // test class-level dependency output
         test(new File(testDir, "Test.class"),
@@ -69,13 +67,13 @@
              new String[] {"-verbose:class"});
         // test -filter:none option
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto", "p"},
+             new String[] {"compact1", "compact1", "compact3", "compact1", "p"},
              new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"});
         // test -filter:archive option
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", "compact1"},
              new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"});
         // test -p option
         test(new File(testDir, "Test.class"),
@@ -107,8 +105,8 @@
         // test -classpath and -include options
         test(null,
              new String[] {"java.lang", "java.util", "java.lang.management",
-                           "javax.activity", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+                           "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", "compact1"},
              new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"});
         test(new File(testDir, "Test.class"),
              new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
diff --git a/langtools/test/tools/jdeps/CompilerUtils.java b/langtools/test/tools/jdeps/CompilerUtils.java
new file mode 100644
index 0000000..be2a0ff
--- /dev/null
+++ b/langtools/test/tools/jdeps/CompilerUtils.java
@@ -0,0 +1,139 @@
+/*
+ * 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 javax.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public final class CompilerUtils {
+    private CompilerUtils() { }
+
+    /**
+     * Compile all the java sources in {@code <source>/**} to
+     * {@code <destination>/**}. The destination directory will be created if
+     * it doesn't exist.
+     *
+     * All warnings/errors emitted by the compiler are output to System.out/err.
+     *
+     * @return true if the compilation is successful
+     *
+     * @throws IOException if there is an I/O error scanning the source tree or
+     *                     creating the destination directory
+     */
+    public static boolean compile(Path source, Path destination, String... options)
+        throws IOException
+    {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
+
+        List<Path> sources
+            = Files.find(source, Integer.MAX_VALUE,
+                         (file, attrs) -> (file.toString().endsWith(".java")))
+                   .collect(Collectors.toList());
+
+        Files.createDirectories(destination);
+        jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
+                                 Arrays.asList(destination));
+
+        List<String> opts = Arrays.asList(options);
+        JavaCompiler.CompilationTask task
+            = compiler.getTask(null, jfm, null, opts, null,
+                               jfm.getJavaFileObjectsFromPaths(sources));
+
+        return task.call();
+    }
+
+    /**
+     * Compile the specified module from the given module sourcepath
+     *
+     * All warnings/errors emitted by the compiler are output to System.out/err.
+     *
+     * @return true if the compilation is successful
+     *
+     * @throws IOException if there is an I/O error scanning the source tree or
+     *                     creating the destination directory
+     */
+    public static boolean compileModule(Path source, Path destination,
+                                        String moduleName, String... options) {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
+
+        try {
+            Files.createDirectories(destination);
+            jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
+                                     Arrays.asList(destination));
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+
+        Stream<String> opts = Arrays.stream(new String[] {
+            "-modulesourcepath", source.toString(), "-m", moduleName
+        });
+        List<String> javacOpts = Stream.concat(opts, Arrays.stream(options))
+                                        .collect(Collectors.toList());
+        JavaCompiler.CompilationTask task
+            = compiler.getTask(null, jfm, null, javacOpts, null, null);
+        return task.call();
+    }
+
+
+    public static void cleanDir(Path dir) throws IOException {
+        if (Files.notExists(dir)) return;
+
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                    throws IOException
+            {
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException e)
+                    throws IOException
+            {
+                if (e == null) {
+                    Files.delete(dir);
+                    return FileVisitResult.CONTINUE;
+                } else {
+                    // directory iteration failed
+                    throw e;
+                }
+            }
+        });
+        Files.deleteIfExists(dir);
+    }
+}
diff --git a/langtools/test/tools/jdeps/DotFileTest.java b/langtools/test/tools/jdeps/DotFileTest.java
index 20c73ca..d560ce6 100644
--- a/langtools/test/tools/jdeps/DotFileTest.java
+++ b/langtools/test/tools/jdeps/DotFileTest.java
@@ -27,7 +27,7 @@
  * @summary Basic tests for jdeps -dotoutput option
  * @modules java.management
  *          jdk.jdeps/com.sun.tools.jdeps
- * @build Test p.Foo p.Bar javax.activity.NotCompactProfile
+ * @build Test p.Foo p.Bar
  * @run main DotFileTest
  */
 
@@ -64,10 +64,9 @@
              new String[] {"java.lang", "p"},
              new String[] {"compact1", "not found"});
         // test a directory
-        // also test non-SE javax.activity class dependency
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", "compact1"},
              new String[] {"-classpath", testDir.getPath()});
         // test class-level dependency output
         test(new File(testDir, "Test.class"),
@@ -76,13 +75,13 @@
              new String[] {"-verbose:class"});
         // test -filter:none option
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto", "p"},
+             new String[] {"compact1", "compact1", "compact3", "compact1", "p"},
              new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"});
         // test -filter:archive option
         test(new File(testDir, "p"),
-             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", "compact1"},
              new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"});
         // test -p option
         test(new File(testDir, "Test.class"),
diff --git a/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java b/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java
index fa6aeea..dfba143 100644
--- a/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java
+++ b/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java
@@ -45,14 +45,15 @@
  *          are found within the same archive. For each testcase, compare the
  *          result obtained from jdeps with the expected result.
  * @modules jdk.jdeps/com.sun.tools.jdeps
- * @build use.indirect.DontUseUnsafe2
- * @build use.indirect.UseUnsafeIndirectly
- * @build use.indirect2.DontUseUnsafe3
- * @build use.indirect2.UseUnsafeIndirectly2
- * @build use.unsafe.DontUseUnsafe
- * @build use.unsafe.UseClassWithUnsafe
- * @build use.unsafe.UseUnsafeClass
- * @build use.unsafe.UseUnsafeClass2
+ *          java.base/sun.security.x509
+ * @build use.indirect.DontUseJdkInternal2
+ * @build use.indirect.UseJdkInternalIndirectly
+ * @build use.indirect2.DontUseJdkInternal3
+ * @build use.indirect2.UseJdkInternalIndirectly2
+ * @build use.internal.DontUseJdkInternal
+ * @build use.internal.UseClassWithJdkInternal
+ * @build use.internal.UseJdkInternalClass
+ * @build use.internal.UseJdkInternalClass2
  * @run main JdepsDependencyClosure --test:0
  * @run main JdepsDependencyClosure --test:1
  * @run main JdepsDependencyClosure --test:2
@@ -170,15 +171,15 @@
         final String arcPath = System.getProperty("test.classes", "build/classes");
         final String arcName = Paths.get(arcPath).getFileName().toString();
         final String[][] classes = new String[][] {
-            {"use.indirect2.UseUnsafeIndirectly2", "use.unsafe.UseClassWithUnsafe"},
+            {"use.indirect2.UseJdkInternalIndirectly2", "use.internal.UseClassWithJdkInternal"},
         };
         final String[][] dependencies = new String[][] {
-            {"use.unsafe.UseUnsafeClass"},
+            {"use.internal.UseJdkInternalClass"},
         };
         final String[][] archives = new String[][] {
             {arcName, arcPath, arcName, arcPath},
         };
-        return TestCaseData.make("use.unsafe.UseUnsafeClass", arcPath, classes,
+        return TestCaseData.make("use.internal.UseJdkInternalClass", arcPath, classes,
                 dependencies, archives, false);
     }
 
@@ -186,15 +187,15 @@
         String arcPath = System.getProperty("test.classes", "build/classes");
         String arcName = Paths.get(arcPath).getFileName().toString();
         String[][] classes = new String[][] {
-            {"use.unsafe.UseUnsafeClass", "use.unsafe.UseUnsafeClass2"}
+            {"use.internal.UseJdkInternalClass", "use.internal.UseJdkInternalClass2"}
         };
         String[][] dependencies = new String[][] {
-            {"sun.misc.Unsafe"}
+            {"sun.security.x509.X509CertInfo"}
         };
         String[][] archive = new String[][] {
             {arcName, arcPath, "JDK internal API (java.base)", "java.base"},
         };
-        return TestCaseData.make("sun.misc.Unsafe", arcPath, classes,
+        return TestCaseData.make("sun.security.x509.X509CertInfo", arcPath, classes,
                 dependencies, archive, false);
     }
 
@@ -202,18 +203,18 @@
         final String arcPath = System.getProperty("test.classes", "build/classes");
         final String arcName = Paths.get(arcPath).getFileName().toString();
         final String[][] classes = new String[][] {
-            {"use.indirect2.UseUnsafeIndirectly2", "use.unsafe.UseClassWithUnsafe"},
-            {"use.indirect.UseUnsafeIndirectly"}
+            {"use.indirect2.UseJdkInternalIndirectly2", "use.internal.UseClassWithJdkInternal"},
+            {"use.indirect.UseJdkInternalIndirectly"}
         };
         final String[][] dependencies = new String[][] {
-            {"use.unsafe.UseUnsafeClass"},
-            {"use.unsafe.UseClassWithUnsafe"}
+            {"use.internal.UseJdkInternalClass"},
+            {"use.internal.UseClassWithJdkInternal"}
         };
         final String[][] archives = new String[][] {
             {arcName, arcPath, arcName, arcPath},
             {arcName, arcPath, arcName, arcPath}
         };
-        return TestCaseData.make("use.unsafe.UseUnsafeClass", arcPath, classes,
+        return TestCaseData.make("use.internal.UseJdkInternalClass", arcPath, classes,
                 dependencies, archives, true);
     }
 
@@ -222,21 +223,21 @@
         final String arcPath = System.getProperty("test.classes", "build/classes");
         final String arcName = Paths.get(arcPath).getFileName().toString();
         final String[][] classes = new String[][] {
-            {"use.unsafe.UseUnsafeClass", "use.unsafe.UseUnsafeClass2"},
-            {"use.indirect2.UseUnsafeIndirectly2", "use.unsafe.UseClassWithUnsafe"},
-            {"use.indirect.UseUnsafeIndirectly"}
+            {"use.internal.UseJdkInternalClass", "use.internal.UseJdkInternalClass2"},
+            {"use.indirect2.UseJdkInternalIndirectly2", "use.internal.UseClassWithJdkInternal"},
+            {"use.indirect.UseJdkInternalIndirectly"}
         };
         final String[][] dependencies = new String[][] {
-            {"sun.misc.Unsafe"},
-            {"use.unsafe.UseUnsafeClass"},
-            {"use.unsafe.UseClassWithUnsafe"}
+            {"sun.security.x509.X509CertInfo"},
+            {"use.internal.UseJdkInternalClass"},
+            {"use.internal.UseClassWithJdkInternal"}
         };
         final String[][] archives = new String[][] {
             {arcName, arcPath, "JDK internal API (java.base)", "java.base"},
             {arcName, arcPath, arcName, arcPath},
             {arcName, arcPath, arcName, arcPath}
         };
-        return TestCaseData.make("sun.misc.Unsafe", arcPath, classes, dependencies,
+        return TestCaseData.make("sun.security.x509.X509CertInfo", arcPath, classes, dependencies,
                 archives, true);
     }
 
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseJdkInternal2.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseJdkInternal2.java
new file mode 100644
index 0000000..6770356
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseJdkInternal2.java
@@ -0,0 +1,27 @@
+/*
+ * 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 use.indirect;
+
+public class DontUseJdkInternal2 {
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseUnsafe2.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseUnsafe2.java
deleted file mode 100644
index 300a4a2..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseUnsafe2.java
+++ /dev/null
@@ -1,29 +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 use.indirect;
-
-import use.unsafe.*;
-
-public class DontUseUnsafe2 {
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseJdkInternalIndirectly.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseJdkInternalIndirectly.java
new file mode 100644
index 0000000..3c6c1a2
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseJdkInternalIndirectly.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package use.indirect;
+
+import use.internal.UseClassWithJdkInternal;
+
+public class UseJdkInternalIndirectly {
+    static UseClassWithJdkInternal use = new UseClassWithJdkInternal();
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseUnsafeIndirectly.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseUnsafeIndirectly.java
deleted file mode 100644
index 70003e5..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseUnsafeIndirectly.java
+++ /dev/null
@@ -1,30 +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 use.indirect;
-
-import use.unsafe.UseClassWithUnsafe;
-
-public class UseUnsafeIndirectly {
-    static UseClassWithUnsafe use = new UseClassWithUnsafe();
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseJdkInternal3.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseJdkInternal3.java
new file mode 100644
index 0000000..4a60df3
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseJdkInternal3.java
@@ -0,0 +1,28 @@
+/*
+ * 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 use.indirect2;
+
+public class DontUseJdkInternal3 {
+
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseUnsafe3.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseUnsafe3.java
deleted file mode 100644
index 979c994..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseUnsafe3.java
+++ /dev/null
@@ -1,30 +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 use.indirect2;
-
-import use.unsafe.*;
-
-public class DontUseUnsafe3 {
-
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseJdkInternalIndirectly2.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseJdkInternalIndirectly2.java
new file mode 100644
index 0000000..701a5de
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseJdkInternalIndirectly2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package use.indirect2;
+
+import use.internal.UseJdkInternalClass;
+
+public class UseJdkInternalIndirectly2 {
+    static UseJdkInternalClass use = new UseJdkInternalClass();
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseUnsafeIndirectly2.java b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseUnsafeIndirectly2.java
deleted file mode 100644
index 2b8dc27..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseUnsafeIndirectly2.java
+++ /dev/null
@@ -1,30 +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 use.indirect2;
-
-import use.unsafe.UseUnsafeClass;
-
-public class UseUnsafeIndirectly2 {
-    static UseUnsafeClass use = new UseUnsafeClass();
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/internal/DontUseJdkInternal.java b/langtools/test/tools/jdeps/VerboseFormat/use/internal/DontUseJdkInternal.java
new file mode 100644
index 0000000..18560ab
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/internal/DontUseJdkInternal.java
@@ -0,0 +1,28 @@
+/*
+ * 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 use.internal;
+
+public class DontUseJdkInternal {
+
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseClassWithJdkInternal.java b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseClassWithJdkInternal.java
new file mode 100644
index 0000000..5086611
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseClassWithJdkInternal.java
@@ -0,0 +1,7 @@
+package use.internal;
+
+public class UseClassWithJdkInternal {
+
+    static UseJdkInternalClass use = new UseJdkInternalClass();
+
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass.java b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass.java
new file mode 100644
index 0000000..416ddfd
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass.java
@@ -0,0 +1,31 @@
+/*
+ * 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 use.internal;
+
+import sun.security.x509.X509CertInfo;
+
+public class UseJdkInternalClass {
+    static X509CertInfo cert = new X509CertInfo();
+
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass2.java b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass2.java
new file mode 100644
index 0000000..78bf64f
--- /dev/null
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/internal/UseJdkInternalClass2.java
@@ -0,0 +1,31 @@
+/*
+ * 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 use.internal;
+
+import sun.security.x509.X509CertInfo;
+
+public class UseJdkInternalClass2 {
+    static X509CertInfo cert = new X509CertInfo();
+
+}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/DontUseUnsafe.java b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/DontUseUnsafe.java
deleted file mode 100644
index fac1e7e..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/DontUseUnsafe.java
+++ /dev/null
@@ -1,28 +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 use.unsafe;
-
-public class DontUseUnsafe {
-
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseClassWithUnsafe.java b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseClassWithUnsafe.java
deleted file mode 100644
index f07787a..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseClassWithUnsafe.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package use.unsafe;
-
-public class UseClassWithUnsafe {
-
-    static UseUnsafeClass use = new UseUnsafeClass();
-
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass.java b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass.java
deleted file mode 100644
index 2d8dc57..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass.java
+++ /dev/null
@@ -1,31 +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 use.unsafe;
-
-import sun.misc.Unsafe;
-
-public class UseUnsafeClass {
-    static Unsafe unsafe = Unsafe.getUnsafe();
-
-}
diff --git a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass2.java b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass2.java
deleted file mode 100644
index 2121222..0000000
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass2.java
+++ /dev/null
@@ -1,31 +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 use.unsafe;
-
-import sun.misc.Unsafe;
-
-public class UseUnsafeClass2 {
-    static Unsafe unsafe = Unsafe.getUnsafe();
-
-}
diff --git a/langtools/test/tools/jdeps/f/F.java b/langtools/test/tools/jdeps/f/F.java
index dc43c9c..a874c71 100644
--- a/langtools/test/tools/jdeps/f/F.java
+++ b/langtools/test/tools/jdeps/f/F.java
@@ -23,9 +23,12 @@
 
 package f;
 
+import sun.security.x509.X509CertInfo;
+
 public class F {
+    private final X509CertInfo cert;
     public F() {
         // jdk internal API
-        sun.misc.Unsafe.getUnsafe();
+        cert = new X509CertInfo();
     }
 }
diff --git a/langtools/test/tools/jdeps/javax/activity/NotCompactProfile.java b/langtools/test/tools/jdeps/javax/activity/NotCompactProfile.java
deleted file mode 100644
index 37e4661..0000000
--- a/langtools/test/tools/jdeps/javax/activity/NotCompactProfile.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package javax.activity;
-
-public class NotCompactProfile {
-    public static String name() {
-        return "not Java SE API";
-    }
-}
diff --git a/langtools/test/tools/jdeps/jdk.unsupported/Foo.java b/langtools/test/tools/jdeps/jdk.unsupported/Foo.java
new file mode 100644
index 0000000..b6303e0
--- /dev/null
+++ b/langtools/test/tools/jdeps/jdk.unsupported/Foo.java
@@ -0,0 +1,31 @@
+/*
+ * 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 sun.misc.Unsafe;
+
+public class Foo {
+    public void run() {
+        Unsafe unsafe = Unsafe.getUnsafe();
+    }
+
+}
diff --git a/langtools/test/tools/jdeps/jdk.unsupported/JDKUnsupportedTest.java b/langtools/test/tools/jdeps/jdk.unsupported/JDKUnsupportedTest.java
new file mode 100644
index 0000000..4decbea
--- /dev/null
+++ b/langtools/test/tools/jdeps/jdk.unsupported/JDKUnsupportedTest.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.
+ */
+
+/*
+ * @test
+ * @summary jdeps should flag jdk.unsupported exported API as internal
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @build Foo
+ * @run testng JDKUnsupportedTest
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.regex.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+
+public class JDKUnsupportedTest {
+    private static final String TEST_CLASSES = System.getProperty("test.classes");
+    @DataProvider(name = "data")
+    public Object[][] expected() {
+        return new Object[][]{
+            { "Foo.class", new String[][] {
+                               new String[] { "java.lang", "java.base" },
+                               new String[] { "sun.misc", "JDK internal API (java.base)" }
+                           }
+            }
+        };
+    }
+
+    @Test(dataProvider = "data")
+    public void test(String filename, String[][] expected) {
+        Path path = Paths.get(TEST_CLASSES, filename);
+
+        Map<String, String> result = jdeps("-M", path.toString());
+        for (String[] e : expected) {
+            String pn = e[0];
+            String module = e[1];
+            assertTrue(module.equals(result.get(pn)));
+        }
+    }
+
+    private static Map<String,String> jdeps(String... args) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        System.err.println("jdeps " + Arrays.toString(args));
+        int rc = com.sun.tools.jdeps.Main.run(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+        if (rc != 0)
+            throw new Error("jdeps failed: rc=" + rc);
+        return findDeps(out);
+    }
+
+    // Pattern used to parse lines
+    private static Pattern linePattern = Pattern.compile(".*\r?\n");
+    private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)");
+
+    // Use the linePattern to break the given String into lines, applying
+    // the pattern to each line to see if we have a match
+    private static Map<String,String> findDeps(String out) {
+        Map<String,String> result = new LinkedHashMap<>();
+        Matcher lm = linePattern.matcher(out);  // Line matcher
+        Matcher pm = null;                      // Pattern matcher
+        int lines = 0;
+        while (lm.find()) {
+            lines++;
+            CharSequence cs = lm.group();       // The current line
+            if (pm == null)
+                pm = pattern.matcher(cs);
+            else
+                pm.reset(cs);
+            if (pm.find())
+                result.put(pm.group(1), pm.group(2).trim());
+            if (lm.end() == out.length())
+                break;
+        }
+        return result;
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/GenModuleInfo.java b/langtools/test/tools/jdeps/modules/GenModuleInfo.java
new file mode 100644
index 0000000..fcdcabb
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/GenModuleInfo.java
@@ -0,0 +1,233 @@
+/*
+ * 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 -genmoduleinfo option
+ * @library ..
+ * @build CompilerUtils
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng GenModuleInfo
+ */
+
+import java.io.*;
+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.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+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");
+    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");
+
+    // the names of the modules in this test
+    private static final String UNSUPPORTED = "unsupported";
+    private static String[] modules = new String[] {"m1", "m2", "m3", UNSUPPORTED};
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        CompilerUtils.cleanDir(MODS_DIR);
+        CompilerUtils.cleanDir(LIBS_DIR);
+        CompilerUtils.cleanDir(DEST_DIR);
+        CompilerUtils.cleanDir(NEW_MODS_DIR);
+
+        assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED,
+                                               "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED));
+        Arrays.asList("m1", "m2", "m3")
+              .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
+
+        Files.createDirectory(LIBS_DIR);
+        Files.createDirectory(DEST_DIR);
+
+        for (String mn : modules) {
+            Path root = MODS_DIR.resolve(mn);
+            createJar(LIBS_DIR.resolve(mn + ".jar"), root,
+                      Files.walk(root, Integer.MAX_VALUE)
+                           .filter(f -> {
+                                String fn = f.getFileName().toString();
+                                return fn.endsWith(".class") && !fn.equals("module-info.class");
+                           }));
+        }
+    }
+
+    @Test
+    public void jdeps() throws IOException {
+        Stream<String> files = Arrays.stream(modules)
+                .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
+                .map(Path::toString);
+        jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new));
+    }
+
+    @Test
+    public void test() throws IOException {
+        Stream<String> files = Arrays.stream(modules)
+                .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
+                .map(Path::toString);
+
+        jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()),
+                            files)
+                    .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)));
+
+        // copy classes except the original module-info.class
+        Files.walk(MODS_DIR, Integer.MAX_VALUE)
+                .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);
+                    }
+                });
+
+        // compile new module-info.java
+        assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR, UNSUPPORTED,
+                        "-mp", NEW_MODS_DIR.toString(), "-verbose",
+                        "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED));
+        Arrays.asList("m1", "m2", "m3")
+              .forEach(mn -> assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR,
+                                        mn, "-mp", NEW_MODS_DIR.toString())));
+
+        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, () -> packages(MODS_DIR.resolve(mn))));
+            }
+        }
+    }
+
+    private void verify(ModuleDescriptor md1, ModuleDescriptor md2) {
+        System.out.println("verifying: " + md1.name());
+        assertEquals(md1.name(), md2.name());
+        assertEquals(md1.requires(), md2.requires());
+        // all packages are exported
+        assertEquals(md1.exports().stream()
+                                  .map(ModuleDescriptor.Exports::source)
+                                  .collect(Collectors.toSet()), md2.packages());
+    }
+
+    private Set<String> packages(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
+                        .distinct()
+                        .collect(Collectors.toSet());
+        } catch (IOException x) {
+            throw new UncheckedIOException(x);
+        }
+    }
+
+    private 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, '.');
+        } else {
+            return "";
+        }
+    }
+
+    /*
+     * Runs jdeps with the given arguments
+     */
+    public static String[] jdeps(String... args) {
+        String lineSep =     System.getProperty("line.separator");
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        System.err.println("jdeps " + Arrays.toString(args));
+        int rc = com.sun.tools.jdeps.Main.run(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+        if (rc != 0)
+            throw new Error("jdeps failed: rc=" + rc);
+        return out.split(lineSep);
+    }
+
+    /**
+     * Create a jar file using the list of files provided.
+     */
+    public static void createJar(Path jarfile, Path root, Stream<Path> files)
+            throws IOException {
+        try (JarOutputStream target = new JarOutputStream(
+                Files.newOutputStream(jarfile))) {
+           files.forEach(file -> add(root.relativize(file), file, target));
+        }
+    }
+
+    private static void add(Path path, Path source, JarOutputStream target) {
+        try {
+            String name = path.toString().replace(File.separatorChar, '/');
+            JarEntry entry = new JarEntry(name);
+            entry.setTime(source.toFile().lastModified());
+            target.putNextEntry(entry);
+            Files.copy(source, target);
+            target.closeEntry();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+}
diff --git a/langtools/test/tools/jdeps/modules/ModuleTest.java b/langtools/test/tools/jdeps/modules/ModuleTest.java
new file mode 100644
index 0000000..f9e6dd0
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/ModuleTest.java
@@ -0,0 +1,310 @@
+/*
+ * 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 -m and -mp options on named modules and unnamed modules
+ * @library ..
+ * @build CompilerUtils
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng ModuleTest
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+
+import java.util.stream.Collectors;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+public class ModuleTest {
+    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");
+
+    // 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};
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        CompilerUtils.cleanDir(MODS_DIR);
+        assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED,
+                                               "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED));
+        // m4 is not referenced
+        Arrays.asList("m1", "m2", "m3", "m4")
+              .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
+    }
+
+    @DataProvider(name = "modules")
+    public Object[][] expected() {
+        return new Object[][]{
+                { "m3", new Data("m3").requiresPublic("java.sql")
+                                      .requiresPublic("m2")
+                                      .requires("java.logging")
+                                      .requiresPublic("m1")
+                                      .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")
+                },
+                { "m2", new Data("m2").requiresPublic("m1")
+                                      .reference("p2", "java.lang", "java.base")
+                                      .reference("p2", "p1", "m1")
+                                      .reference("p2.internal", "java.lang", "java.base")
+                                      .reference("p2.internal", "java.io", "java.base")
+                },
+                { "m1", new Data("m1").requires("unsupported")
+                                      .reference("p1", "java.lang", "java.base")
+                                      .reference("p1.internal", "java.lang", "java.base")
+                                      .reference("p1.internal", "p1", "m1")
+                                      .reference("p1.internal", "q", "unsupported")
+                },
+                { "unsupported", new Data("unsupported")
+                                      .reference("q", "java.lang", "java.base")
+                                      .jdkInternal("q", "jdk.internal.perf", "(java.base)")
+                },
+        };
+    }
+
+    @Test(dataProvider = "modules")
+    public void modularTest(String name, Data data) {
+        // print only the specified module
+        String excludes = Arrays.stream(modules)
+                                .filter(mn -> !mn.endsWith(name))
+                                .collect(Collectors.joining(","));
+        String[] result = jdeps("-exclude-modules", excludes,
+                                "-mp", MODS_DIR.toString(),
+                                "-m", name);
+        assertTrue(data.check(result));
+    }
+
+    @DataProvider(name = "unnamed")
+    public Object[][] unnamed() {
+        return new Object[][]{
+                { "m3", new Data("m3", false)
+                            .depends("java.sql")
+                            .depends("java.logging")
+                            .depends("m1")
+                            .depends("m2")
+                            .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")
+                },
+                { "unsupported", new Data("unsupported", false)
+                            .reference("q", "java.lang", "java.base")
+                            .jdkInternal("q", "jdk.internal.perf", "(java.base)")
+                },
+        };
+    }
+
+    @Test(dataProvider = "unnamed")
+    public void unnamedTest(String name, Data data) {
+        String[] result = jdeps("-mp", MODS_DIR.toString(), MODS_DIR.resolve(name).toString());
+        assertTrue(data.check(result));
+    }
+
+    /*
+     * Runs jdeps with the given arguments
+     */
+    public static String[] jdeps(String... args) {
+        String lineSep =     System.getProperty("line.separator");
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        System.err.println("jdeps " + Arrays.toString(args));
+        int rc = com.sun.tools.jdeps.Main.run(args, pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+        if (rc != 0)
+            throw new Error("jdeps failed: rc=" + rc);
+        return out.split(lineSep);
+    }
+
+    static class Data {
+        static final String INTERNAL = "(internal)";
+        static final String QUALIFIED = "(qualified)";
+        static final String JDK_INTERNAL = "JDK internal API";
+
+        final String moduleName;
+        final boolean isNamed;
+        final Map<String, ModuleRequires> requires = new LinkedHashMap<>();
+        final Map<String, Dependence> references = new LinkedHashMap<>();
+        Data(String name) {
+            this(name, true);
+        }
+        Data(String name, boolean isNamed) {
+            this.moduleName = name;
+            this.isNamed = isNamed;
+            requires("java.base");  // implicit requires
+        }
+
+        Data requires(String name) {
+            requires.put(name, new ModuleRequires(name));
+            return this;
+        }
+        Data requiresPublic(String name) {
+            requires.put(name, new ModuleRequires(name, PUBLIC));
+            return this;
+        }
+        // for unnamed module
+        Data depends(String name) {
+            requires.put(name, new ModuleRequires(name));
+            return this;
+        }
+        Data reference(String origin, String target, String module) {
+            return dependence(origin, target, module, "");
+        }
+        Data internal(String origin, String target, String module) {
+            return dependence(origin, target, module, INTERNAL);
+        }
+        Data qualified(String origin, String target, String module) {
+            return dependence(origin, target, module, QUALIFIED);
+        }
+        Data jdkInternal(String origin, String target, String module) {
+            return dependence(origin, target, module, JDK_INTERNAL);
+        }
+        private Data dependence(String origin, String target, String module, String access) {
+            references.put(key(origin, target), new Dependence(origin, target, module, access));
+            return this;
+        }
+
+        String key(String origin, String target) {
+            return origin+":"+target;
+        }
+        boolean check(String[] lines) {
+            System.out.format("verifying module %s%s%n", moduleName, isNamed ? "" : " (unnamed module)");
+            for (String l : lines) {
+                String[] tokens = l.trim().split("\\s+");
+                System.out.println("  " + Arrays.stream(tokens).collect(Collectors.joining(" ")));
+                switch (tokens[0]) {
+                    case "module":
+                        assertEquals(tokens.length, 2);
+                        assertEquals(moduleName, tokens[1]);
+                        break;
+                    case "requires":
+                        String name = tokens.length == 2 ? tokens[1] : tokens[2];
+                        Modifier modifier = null;
+                        if (tokens.length == 3) {
+                            assertEquals("public", tokens[1]);
+                            modifier = PUBLIC;
+                        }
+                        checkRequires(name, modifier);
+                        break;
+                    default:
+                        if (tokens.length == 3) {
+                            // unnamed module requires
+                            assertFalse(isNamed);
+                            assertEquals(moduleName, tokens[0]);
+                            String mn = tokens[2];
+                            checkRequires(mn, null);
+                        } else {
+                            checkDependence(tokens);
+                        }
+                }
+            }
+            return true;
+        }
+
+        private void checkRequires(String name, Modifier modifier) {
+            assertTrue(requires.containsKey(name));
+            ModuleRequires req = requires.get(name);
+            assertEquals(req.mod, modifier);
+        }
+
+        private void checkDependence(String[] tokens) {
+            assertTrue(tokens.length >= 4);
+            String origin = tokens[0];
+            String target = tokens[2];
+            String module = tokens[3];
+            String key = key(origin, target);
+            assertTrue(references.containsKey(key));
+            Dependence dep = references.get(key);
+            if (tokens.length == 4) {
+                assertEquals(dep.access, "");
+            } else if (tokens.length == 5) {
+                assertEquals(dep.access, tokens[4]);
+            } else {
+                // JDK internal API
+                module = tokens[6];
+                assertEquals(tokens.length, 7);
+                assertEquals(tokens[3], "JDK");
+                assertEquals(tokens[4], "internal");
+                assertEquals(tokens[5], "API");
+            }
+            assertEquals(dep.module, module);
+        }
+
+        public static class ModuleRequires {
+            final String name;
+            final ModuleDescriptor.Requires.Modifier mod;
+
+            ModuleRequires(String name) {
+                this.name = name;
+                this.mod = null;
+            }
+
+            ModuleRequires(String name, ModuleDescriptor.Requires.Modifier mod) {
+                this.name = name;
+                this.mod = mod;
+            }
+        }
+
+        public static class Dependence {
+            final String origin;
+            final String target;
+            final String module;
+            final String access;
+
+            Dependence(String origin, String target, String module, String access) {
+                this.origin = origin;
+                this.target = target;
+                this.module = module;
+                this.access = access;
+            }
+        }
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/jdeps/modules/src/m1/module-info.java
new file mode 100644
index 0000000..9d2c8be
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m1/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+    requires unsupported;
+    exports p1;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/Goo.java b/langtools/test/tools/jdeps/modules/src/m1/p1/Goo.java
new file mode 100644
index 0000000..bb50d86
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m1/p1/Goo.java
@@ -0,0 +1,29 @@
+/*
+ * 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 p1;
+
+public class Goo  {
+    public void name() {
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/Lib.java b/langtools/test/tools/jdeps/modules/src/m1/p1/Lib.java
new file mode 100644
index 0000000..87deecc
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m1/p1/Lib.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 p1;
+
+public class Lib {
+    public static boolean isPresent() {
+        return true;
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/S.java b/langtools/test/tools/jdeps/modules/src/m1/p1/S.java
new file mode 100644
index 0000000..baa2fa4
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m1/p1/S.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 p1;
+
+public interface S {
+    String name();
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/internal/Impl.java b/langtools/test/tools/jdeps/modules/src/m1/p1/internal/Impl.java
new file mode 100644
index 0000000..e071f86
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m1/p1/internal/Impl.java
@@ -0,0 +1,36 @@
+/*
+ * 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 p1.internal;
+
+import p1.S;
+
+public class Impl implements S {
+    public Impl() {
+        q.Counter.create("impl.counter");
+    }
+
+    public String name() {
+        return Impl.class.getName();
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m2/module-info.java b/langtools/test/tools/jdeps/modules/src/m2/module-info.java
new file mode 100644
index 0000000..8a5d623
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m2/module-info.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m2 {
+    requires public m1;
+    exports p2;
+    exports p2.internal to m3;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m2/p2/Bar.java b/langtools/test/tools/jdeps/modules/src/m2/p2/Bar.java
new file mode 100644
index 0000000..5acf290
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m2/p2/Bar.java
@@ -0,0 +1,34 @@
+/*
+ * 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 p2;
+
+import p1.Goo;
+
+public class Bar {
+    public Bar() {}
+
+    public Goo toGoo() {
+        return new Goo();
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m2/p2/internal/T2.java b/langtools/test/tools/jdeps/modules/src/m2/p2/internal/T2.java
new file mode 100644
index 0000000..e6ac602
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m2/p2/internal/T2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 p2.internal;
+
+public class T2 {
+    public static void print() {
+        System.out.println("T2");
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m3/module-info.java b/langtools/test/tools/jdeps/modules/src/m3/module-info.java
new file mode 100644
index 0000000..dd7b530
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m3/module-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 {
+    requires public java.sql;
+    requires public m2;
+    requires java.logging;   // TODO: genmoduleinfo to do transitive reduction
+    requires public m1;
+    exports p3;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m3/p3/Foo.java b/langtools/test/tools/jdeps/modules/src/m3/p3/Foo.java
new file mode 100644
index 0000000..fcd7669
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m3/p3/Foo.java
@@ -0,0 +1,36 @@
+/*
+ * 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 java.sql.Driver;
+import p1.Goo;
+import p2.Bar;
+
+public class Foo {
+    public Goo get(Bar bar) {
+        return bar.toGoo();
+    }
+
+    public Driver getDriver() { return null; }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m3/p3/Main.java b/langtools/test/tools/jdeps/modules/src/m3/p3/Main.java
new file mode 100644
index 0000000..341c946
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m3/p3/Main.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p3;
+
+import p2.internal.T2;
+
+public class Main {
+    public void run() {
+        T2.print();
+    }
+
+    public static void main(String... args) throws Exception {
+        Foo foo = new Foo();
+        foo.getDriver().getParentLogger().config("test");
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m4/module-info.java b/langtools/test/tools/jdeps/modules/src/m4/module-info.java
new file mode 100644
index 0000000..ddca4f5
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m4/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m4 {
+    requires public java.compiler;
+    requires java.logging;
+    exports p4;
+    exports p4.internal to m1,m2,m3;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m4/p4/Lib.java b/langtools/test/tools/jdeps/modules/src/m4/p4/Lib.java
new file mode 100644
index 0000000..4e61ae3
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m4/p4/Lib.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 p4;
+
+public class Lib {
+    public static boolean isPresent() {
+        return true;
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java b/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java
new file mode 100644
index 0000000..ea2c548
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java
@@ -0,0 +1,31 @@
+/*
+ * 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 p4.internal;
+
+
+public class Impl {
+    public String name() {
+        return Impl.class.getName();
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/unsupported/module-info.java b/langtools/test/tools/jdeps/modules/src/unsupported/module-info.java
new file mode 100644
index 0000000..b543f6c
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/unsupported/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module unsupported {
+    exports q;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/unsupported/q/Counter.java b/langtools/test/tools/jdeps/modules/src/unsupported/q/Counter.java
new file mode 100644
index 0000000..1c32240
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/unsupported/q/Counter.java
@@ -0,0 +1,32 @@
+/*
+ * 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 q;
+
+import jdk.internal.perf.PerfCounter;;
+
+public class Counter {
+     public static void create(String name) {
+         PerfCounter.newPerfCounter(name);
+     }
+}
diff --git a/langtools/test/tools/jdeps/p/Bar.java b/langtools/test/tools/jdeps/p/Bar.java
index 77e20e6..82830a6 100644
--- a/langtools/test/tools/jdeps/p/Bar.java
+++ b/langtools/test/tools/jdeps/p/Bar.java
@@ -23,7 +23,7 @@
 
 package p;
 
-public class Bar extends javax.activity.NotCompactProfile {
+public class Bar {
     public String bar() {
         return "bar";
     }
diff --git a/langtools/test/tools/lib/ToolBox.java b/langtools/test/tools/lib/ToolBox.java
index 4193f6f..a76b66a 100644
--- a/langtools/test/tools/lib/ToolBox.java
+++ b/langtools/test/tools/lib/ToolBox.java
@@ -560,13 +560,17 @@
         }
 
         /**
-         * Returns the content of a named stream as a list of lines.
-         * @param outputKind the kind of the selected stream
-         * @return the content that was written to that stream when the tool
+         * Returns the content of named streams as a list of lines.
+         * @param outputKinds the kinds of the selected streams
+         * @return the content that was written to the given streams when the tool
          *  was executed.
          */
-        public List<String> getOutputLines(OutputKind outputKind) {
-            return Arrays.asList(outputMap.get(outputKind).split(lineSeparator));
+        public List<String> getOutputLines(OutputKind... outputKinds) {
+            List<String> result = new ArrayList<>();
+            for (OutputKind outputKind : outputKinds) {
+                result.addAll(Arrays.asList(outputMap.get(outputKind).split(lineSeparator)));
+            }
+            return result;
         }
 
         /**
@@ -1690,9 +1694,9 @@
         private final Pattern jrtEntry = Pattern.compile("/modules/([^/]+)/(.*)");
 
         /*
-         * A file: URL is of the form  file:/path/to/modules/<module>/<package>/<file>
+         * A file: URL is of the form  file:/path/to/{modules,patches}/<module>/<package>/<file>
          */
-        private final Pattern fileEntry = Pattern.compile(".*/modules/([^/]+)/(.*)");
+        private final Pattern fileEntry = Pattern.compile(".*/(?:modules|patches)/([^/]+)/(.*)");
 
         private String guessPath(FileObject fo) {
             URI u = fo.toUri();
@@ -1965,6 +1969,8 @@
             return source;
         }
 
+        private static Pattern modulePattern =
+                Pattern.compile("module\\s+((?:\\w+\\.)*)");
         private static Pattern packagePattern =
                 Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
         private static Pattern classPattern =
@@ -1978,7 +1984,11 @@
         static String getJavaFileNameFromSource(String source) {
             String packageName = null;
 
-            Matcher matcher = packagePattern.matcher(source);
+            Matcher matcher = modulePattern.matcher(source);
+            if (matcher.find())
+                return "module-info.java";
+
+            matcher = packagePattern.matcher(source);
             if (matcher.find())
                 packageName = matcher.group(1).replace(".", "/");
 
@@ -1986,6 +1996,8 @@
             if (matcher.find()) {
                 String className = matcher.group(1) + ".java";
                 return (packageName == null) ? className : packageName + "/" + className;
+            } else if (packageName != null) {
+                return packageName + "/package-info.java";
             } else {
                 throw new Error("Could not extract the java class " +
                         "name from the provided source");
diff --git a/langtools/test/tools/sjavac/ApiExtraction.java b/langtools/test/tools/sjavac/ApiExtraction.java
index 6ac3de5..d5c6a45 100644
--- a/langtools/test/tools/sjavac/ApiExtraction.java
+++ b/langtools/test/tools/sjavac/ApiExtraction.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper ApiExtraction
  */
diff --git a/langtools/test/tools/sjavac/ClasspathDependencies.java b/langtools/test/tools/sjavac/ClasspathDependencies.java
index 936d474..fcd34e2 100644
--- a/langtools/test/tools/sjavac/ClasspathDependencies.java
+++ b/langtools/test/tools/sjavac/ClasspathDependencies.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper ClasspathDependencies
  */
diff --git a/langtools/test/tools/sjavac/CompileCircularSources.java b/langtools/test/tools/sjavac/CompileCircularSources.java
index 13a4973..fcd31de 100644
--- a/langtools/test/tools/sjavac/CompileCircularSources.java
+++ b/langtools/test/tools/sjavac/CompileCircularSources.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper CompileCircularSources
  */
diff --git a/langtools/test/tools/sjavac/CompileExcludingDependency.java b/langtools/test/tools/sjavac/CompileExcludingDependency.java
index bb6efd6..4a88d73 100644
--- a/langtools/test/tools/sjavac/CompileExcludingDependency.java
+++ b/langtools/test/tools/sjavac/CompileExcludingDependency.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper CompileExcludingDependency
  */
diff --git a/langtools/test/tools/sjavac/CompileWithAtFile.java b/langtools/test/tools/sjavac/CompileWithAtFile.java
index 6c611af..ffbbc21 100644
--- a/langtools/test/tools/sjavac/CompileWithAtFile.java
+++ b/langtools/test/tools/sjavac/CompileWithAtFile.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper CompileWithAtFile
  */
diff --git a/langtools/test/tools/sjavac/CompileWithInvisibleSources.java b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java
index a6d8863..4739db7 100644
--- a/langtools/test/tools/sjavac/CompileWithInvisibleSources.java
+++ b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper CompileWithInvisibleSources
  */
diff --git a/langtools/test/tools/sjavac/CompileWithOverrideSources.java b/langtools/test/tools/sjavac/CompileWithOverrideSources.java
index 0ce15b3..cd12c2d 100644
--- a/langtools/test/tools/sjavac/CompileWithOverrideSources.java
+++ b/langtools/test/tools/sjavac/CompileWithOverrideSources.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper CompileWithOverrideSources
  */
diff --git a/langtools/test/tools/sjavac/HiddenFiles.java b/langtools/test/tools/sjavac/HiddenFiles.java
index 30f78ab..6ca7dae 100644
--- a/langtools/test/tools/sjavac/HiddenFiles.java
+++ b/langtools/test/tools/sjavac/HiddenFiles.java
@@ -30,6 +30,7 @@
  *          compilation)
  *
  * @modules jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  * @build Wrapper ToolBox
  * @run main Wrapper HiddenFiles
diff --git a/langtools/test/tools/sjavac/IncCompInheritance.java b/langtools/test/tools/sjavac/IncCompInheritance.java
index 20cd6ed..6c81c85 100644
--- a/langtools/test/tools/sjavac/IncCompInheritance.java
+++ b/langtools/test/tools/sjavac/IncCompInheritance.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompInheritance
  */
diff --git a/langtools/test/tools/sjavac/IncCompileChangeNative.java b/langtools/test/tools/sjavac/IncCompileChangeNative.java
index 809a97a..6fd61a4 100644
--- a/langtools/test/tools/sjavac/IncCompileChangeNative.java
+++ b/langtools/test/tools/sjavac/IncCompileChangeNative.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileChangeNative
  */
diff --git a/langtools/test/tools/sjavac/IncCompileDropClasses.java b/langtools/test/tools/sjavac/IncCompileDropClasses.java
index 62d351e..636c4c4 100644
--- a/langtools/test/tools/sjavac/IncCompileDropClasses.java
+++ b/langtools/test/tools/sjavac/IncCompileDropClasses.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileDropClasses
  */
diff --git a/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java b/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java
index ecdf261..617a998 100644
--- a/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java
+++ b/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java
@@ -33,6 +33,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileFullyQualifiedRef
  */
diff --git a/langtools/test/tools/sjavac/IncCompileNoChanges.java b/langtools/test/tools/sjavac/IncCompileNoChanges.java
index 3d25749..0dcc853 100644
--- a/langtools/test/tools/sjavac/IncCompileNoChanges.java
+++ b/langtools/test/tools/sjavac/IncCompileNoChanges.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileNoChanges
  */
diff --git a/langtools/test/tools/sjavac/IncCompileUpdateNative.java b/langtools/test/tools/sjavac/IncCompileUpdateNative.java
index 06f0fd8..021684b 100644
--- a/langtools/test/tools/sjavac/IncCompileUpdateNative.java
+++ b/langtools/test/tools/sjavac/IncCompileUpdateNative.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileUpdateNative
  */
diff --git a/langtools/test/tools/sjavac/IncCompileWithChanges.java b/langtools/test/tools/sjavac/IncCompileWithChanges.java
index ec1531c..901c900 100644
--- a/langtools/test/tools/sjavac/IncCompileWithChanges.java
+++ b/langtools/test/tools/sjavac/IncCompileWithChanges.java
@@ -33,6 +33,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper IncCompileWithChanges
  */
diff --git a/langtools/test/tools/sjavac/IncludeExcludePatterns.java b/langtools/test/tools/sjavac/IncludeExcludePatterns.java
index 19158d0..dd99062 100644
--- a/langtools/test/tools/sjavac/IncludeExcludePatterns.java
+++ b/langtools/test/tools/sjavac/IncludeExcludePatterns.java
@@ -27,6 +27,7 @@
  * @summary Ensures that sjavac can handle various exclusion patterns.
  *
  * @modules jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @library /tools/lib
  * @build Wrapper ToolBox
  * @run main Wrapper IncludeExcludePatterns
diff --git a/langtools/test/tools/sjavac/NoState.java b/langtools/test/tools/sjavac/NoState.java
index db60506..6c0541a 100644
--- a/langtools/test/tools/sjavac/NoState.java
+++ b/langtools/test/tools/sjavac/NoState.java
@@ -30,6 +30,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper NoState
  */
diff --git a/langtools/test/tools/sjavac/OverlappingSrcDst.java b/langtools/test/tools/sjavac/OverlappingSrcDst.java
index 516fb11..8c0dbda 100644
--- a/langtools/test/tools/sjavac/OverlappingSrcDst.java
+++ b/langtools/test/tools/sjavac/OverlappingSrcDst.java
@@ -33,6 +33,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper OverlappingSrcDst
  */
diff --git a/langtools/test/tools/sjavac/PackagePathMismatch.java b/langtools/test/tools/sjavac/PackagePathMismatch.java
index 443ce3d..a1e3425 100644
--- a/langtools/test/tools/sjavac/PackagePathMismatch.java
+++ b/langtools/test/tools/sjavac/PackagePathMismatch.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper PackagePathMismatch
  */
diff --git a/langtools/test/tools/sjavac/ParallelCompilations.java b/langtools/test/tools/sjavac/ParallelCompilations.java
index 1d104b3..532445e 100644
--- a/langtools/test/tools/sjavac/ParallelCompilations.java
+++ b/langtools/test/tools/sjavac/ParallelCompilations.java
@@ -31,6 +31,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper ParallelCompilations
  */
diff --git a/langtools/test/tools/sjavac/PermittedArtifact.java b/langtools/test/tools/sjavac/PermittedArtifact.java
index 9e7ea6c..e83c528 100644
--- a/langtools/test/tools/sjavac/PermittedArtifact.java
+++ b/langtools/test/tools/sjavac/PermittedArtifact.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper PermittedArtifact
  */
diff --git a/langtools/test/tools/sjavac/StateDir.java b/langtools/test/tools/sjavac/StateDir.java
index db25829..5ccfa73 100644
--- a/langtools/test/tools/sjavac/StateDir.java
+++ b/langtools/test/tools/sjavac/StateDir.java
@@ -32,6 +32,7 @@
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.sjavac
+ *          jdk.jdeps/com.sun.tools.javap
  * @build Wrapper ToolBox
  * @run main Wrapper StateDir
  */
diff --git a/make/CheckModules.gmk b/make/CheckModules.gmk
deleted file mode 100644
index 4872c91..0000000
--- a/make/CheckModules.gmk
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# Default target declared first
-default: all
-
-include $(SPEC)
-include MakeBase.gmk
-
-JDEPS_MODULES_XML := $(JDK_OUTPUTDIR)/modules/jdk.jdeps/com/sun/tools/jdeps/resources/jdeps-modules.xml
-
-#
-# Verify access across module boundaries
-#
-checkdeps:
-	$(ECHO) "Checking dependencies across JDK modules"
-	$(JAVA) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
-		-Djdeps.modules.xml=$(JDEPS_MODULES_XML) \
-		com.sun.tools.jdeps.Main \
-		-verify:access -mp $(JDK_OUTPUTDIR)/modules
-
-all: checkdeps
-
-.PHONY: all
diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk
index e8928e2..a2650d7 100644
--- a/make/CompileJavaModules.gmk
+++ b/make/CompileJavaModules.gmk
@@ -46,6 +46,9 @@
 java.base_COPY := .icu .dat .spp content-types.properties hijrah-config-islamic-umalqura.properties
 java.base_CLEAN := intrinsic.properties
 
+java.base_EXCLUDE_FILES += \
+  $(JDK_TOPDIR)/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
+
 java.base_EXCLUDES += java/lang/doc-files
 
 # Exclude BreakIterator classes that are just used in compile process to generate
@@ -359,8 +362,8 @@
 
 ################################################################################
 
-jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*' -XDstringConcat=inline
-jdk.compiler_COPY := javax.tools.JavaCompilerTool
+jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*' \
+    -XDstringConcat=inline
 jdk.compiler_CLEAN_FILES := $(wildcard \
     $(patsubst %, $(JDK_TOPDIR)/src/jdk.compiler/share/classes/%/*.properties, \
         sun/tools/serialver/resources))
@@ -480,31 +483,28 @@
 # source before static source and platform specific source before shared.
 #
 GENERATED_SRC_DIRS += \
-    $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE) \
-    $(SUPPORT_OUTPUTDIR)/gensrc_no_docs/$(MODULE) \
+    $(SUPPORT_OUTPUTDIR)/gensrc \
     #
 
-OS_SRC_DIRS += $(JDK_TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS)/classes
+TOP_SRC_DIRS += \
+    $(HOTSPOT_TOPDIR)/src \
+    $(CORBA_TOPDIR)/src \
+    $(JDK_TOPDIR)/src \
+    $(LANGTOOLS_TOPDIR)/src \
+    $(JAXP_TOPDIR)/src \
+    $(JAXWS_TOPDIR)/src \
+    $(NASHORN_TOPDIR)/src \
+    #
+
+SRC_SUBDIRS += $(OPENJDK_TARGET_OS)/classes
 ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE))
-  OS_TYPE_SRC_DIRS += $(JDK_TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/classes
+  SRC_SUBDIRS += $(OPENJDK_TARGET_OS_TYPE)/classes
 endif
+SRC_SUBDIRS += share/classes
 
-SHARE_SRC_DIRS += \
-    $(HOTSPOT_TOPDIR)/src/$(MODULE)/share/classes \
-    $(JDK_TOPDIR)/src/$(MODULE)/share/classes \
-    $(LANGTOOLS_TOPDIR)/src/$(MODULE)/share/classes \
-    $(CORBA_TOPDIR)/src/$(MODULE)/share/classes \
-    $(JAXP_TOPDIR)/src/$(MODULE)/share/classes \
-    $(JAXWS_TOPDIR)/src/$(MODULE)/share/classes \
-    $(NASHORN_TOPDIR)/src/$(MODULE)/share/classes \
-    #
-
-ALL_SRC_DIRS = \
-    $(GENERATED_SRC_DIRS) \
-    $(OS_SRC_DIRS) \
-    $(OS_TYPE_SRC_DIRS) \
-    $(SHARE_SRC_DIRS) \
-    #
+MODULE_SRC_DIRS := $(strip \
+    $(addsuffix /$(MODULE), $(GENERATED_SRC_DIRS) $(IMPORT_MODULES_SRC)) \
+    $(foreach sub, $(SRC_SUBDIRS), $(addsuffix /$(MODULE)/$(sub), $(TOP_SRC_DIRS))))
 
 # The JDK_USER_DEFINED_FILTER is a poor man's incremental build: by specifying
 # JDK_FILTER at the make command line, only a subset of the JDK java files will
@@ -512,32 +512,41 @@
 # space separated list.
 JDK_USER_DEFINED_FILTER := $(strip $(subst $(COMMA),$(SPACE), $(JDK_FILTER)))
 
-# Create an empty directory to set the bootclasspath to.
-EMPTY_DIR := $(SUPPORT_OUTPUTDIR)/empty-dir
-$(call MakeDir, $(EMPTY_DIR))
+# Rewrite the MODULE_SRC_DIRS with a wildcard for the module so that all module
+# source dirs are available on the path.
+MODULESOURCEPATH := $(subst $(SPACE),$(PATH_SEP),$(subst $(MODULE),*,$(MODULE_SRC_DIRS)))
 
-# Find the module dependencies by parsing modules.list file
-DEPS := $(call FindDepsForModule, $(MODULE))
+# Add imported modules to the moduleclasspath
+MODULECLASSPATH := $(subst $(SPACE),$(PATH_SEP), $(IMPORT_MODULES_CLASSES))
 
-CLASSPATH := $(foreach d, $(DEPS), $(if $($d_BIN), $($d_BIN), \
-    $(JDK_OUTPUTDIR)/modules/$d))
-  # When crypto classes are prebuilt, need to look for classes already in
-  # output dir.
-  ifneq ($(BUILD_CRYPTO), true)
-  CLASSPATH += $(JDK_OUTPUTDIR)/modules/$(MODULE)
-  endif
-JAVAC_FLAGS_BOOTCLASSPATH := -bootclasspath $(EMPTY_DIR) -extdirs $(EMPTY_DIR) \
-    -endorseddirs $(EMPTY_DIR) $($(MODULE)_ADD_JAVAC_FLAGS)
+ifeq ($(MODULE), jdk.vm.ci)
+  ## WORKAROUND jdk.vm.ci source structure issue
+  JVMCI_MODULESOURCEPATH := $(MODULESOURCEPATH) \
+      $(subst /$(MODULE)/,/*/, $(filter-out %processor/src, \
+          $(wildcard $(HOTSPOT_TOPDIR)/src/jdk.vm.ci/share/classes/*/src)))
+  MODULESOURCEPATH := $(subst $(SPACE),$(PATH_SEP), $(JVMCI_MODULESOURCEPATH))
+endif
+
+# Make sure the generated source base dirs exist. Not all modules have generated
+# source in all of these directories and because of timing, all of them might not
+# exist at the time this makefile gets called. Javac will complain if there are
+# missing directories in the moduleclasspath.
+$(call MakeDir, $(GENERATED_SRC_DIRS))
 
 $(eval $(call SetupJavaCompilation, $(MODULE), \
     SETUP := $(if $($(MODULE)_SETUP), $($(MODULE)_SETUP), GENERATE_JDKBYTECODE), \
-    SRC := $(if $($(MODULE)_SRC), $($(MODULE)_SRC), $(wildcard $(ALL_SRC_DIRS))), \
-      INCLUDES := $(JDK_USER_DEFINED_FILTER),\
-    BIN := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules/$(MODULE)), \
-    HEADERS := $(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \
-    CLASSPATH := $(CLASSPATH), \
-    ADD_JAVAC_FLAGS := $($(MODULE)_ADD_JAVAC_FLAGS) $(JAVAC_FLAGS_BOOTCLASSPATH) \
+    MODULE := $(MODULE), \
+    SRC := $(wildcard $(MODULE_SRC_DIRS)), \
+    INCLUDES := $(JDK_USER_DEFINED_FILTER),\
+    BIN := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules), \
+    HEADERS := $(SUPPORT_OUTPUTDIR)/headers, \
+    ADD_JAVAC_FLAGS := \
+        $($(MODULE)_ADD_JAVAC_FLAGS) \
+        -modulesourcepath "$(MODULESOURCEPATH)" \
+        $(if $(MODULECLASSPATH), -modulepath "$(MODULECLASSPATH)") \
+        -system none, \
 ))
+
 TARGETS += $($(MODULE)) $($(MODULE)_COPY_EXTRA)
 
 # Declare dependencies between java compilations of different modules.
@@ -545,7 +554,7 @@
 # use the macro to find the correct target file to depend on.
 # Only the javac compilation actually depends on other modules so limit
 # dependency declaration to that by using the *_COMPILE_TARGET variable.
-$($(MODULE)_COMPILE_TARGET): $(foreach d, $($(MODULE)_DEPS), \
+$($(MODULE)_COMPILE_TARGET): $(foreach d, $(call FindDepsForModule, $(MODULE)), \
     $(call SetupJavaCompilationCompileTarget, $d, \
         $(if $($d_BIN), $($d_BIN), $(JDK_OUTPUTDIR)/modules/$d)))
 
@@ -569,6 +578,29 @@
 endif
 
 ################################################################################
+# If this is an imported module, copy the pre built classes and resources into
+# the modules output dir
+
+ifneq ($(wildcard $(IMPORT_MODULES_CLASSES)/$(MODULE)), )
+  $(JDK_OUTPUTDIR)/modules/$(MODULE)/_imported.marker: \
+      $(call CacheFind, $(IMPORT_MODULES_CLASSES)/$(MODULE))
+	$(RM) -r $(@D)
+	$(MKDIR) -p $(@D)
+	$(CP) -R $(IMPORT_MODULES_CLASSES)/$(MODULE)/* $(@D)/
+	$(TOUCH) $@
+
+  TARGETS += $(JDK_OUTPUTDIR)/modules/$(MODULE)/_imported.marker
+
+  # Add this dependency to avoid a race between compiling module-info.java and
+  # importing the classes.
+  $($(MODULE)_COMPILE_TARGET): $(JDK_OUTPUTDIR)/modules/$(MODULE)/_imported.marker
+endif
+
+################################################################################
+
+$(eval $(call IncludeCustomExtension, , CompileJavaModules-post.gmk))
+
+################################################################################
 
 all: $(TARGETS)
 
diff --git a/make/CopyImportModules.gmk b/make/CopyImportModules.gmk
new file mode 100644
index 0000000..e792885
--- /dev/null
+++ b/make/CopyImportModules.gmk
@@ -0,0 +1,86 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# This makefile is called for every imported module to copy the non class
+# contents into the exploded jdk image.
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+LIBS_DIR := $(wildcard $(addsuffix /$(MODULE), $(IMPORT_MODULES_LIBS)))
+CMDS_DIR := $(wildcard $(addsuffix /$(MODULE), $(IMPORT_MODULES_CMDS)))
+CONF_DIR := $(wildcard $(addsuffix /$(MODULE), $(IMPORT_MODULES_CONF)))
+
+$(eval $(call FillCacheFind, $(LIBS_DIR) $(CMDS_DIR) $(CONF_DIR)))
+
+ifneq ($(LIBS_DIR), )
+  ifeq ($(OPENJDK_TARGET_OS), windows)
+    TO_BIN_FILTER := %$(SHARED_LIBRARY_SUFFIX) %.diz %.pdb %.map
+
+    $(eval $(call SetupCopyFiles,COPY_LIBS_TO_BIN, \
+        SRC := $(LIBS_DIR), \
+        DEST := $(JDK_OUTPUTDIR)/bin, \
+        FILES := $(filter $(TO_BIN_FILTER), \
+            $(call CacheFind, $(LIBS_DIR))) \
+    ))
+
+    $(eval $(call SetupCopyFiles,COPY_LIBS_TO_LIB, \
+        SRC := $(LIBS_DIR), \
+        DEST := $(JDK_OUTPUTDIR)/lib, \
+        FILES := $(filter-out $(TO_BIN_FILTER), \
+            $(call CacheFind, $(LIBS_DIR))) \
+    ))
+    TARGETS += $(COPY_LIBS_TO_BIN) $(COPY_LIBS_TO_LIB)
+  else
+    $(eval $(call SetupCopyFiles, COPY_LIBS, \
+        SRC := $(LIBS_DIR), \
+        DEST := $(JDK_OUTPUTDIR)/lib, \
+        FILES := $(call CacheFind, $(LIBS_DIR)), \
+    ))
+    TARGETS += $(COPY_LIBS)
+  endif
+endif
+
+ifneq ($(CMDS_DIR), )
+  $(eval $(call SetupCopyFiles, COPY_CMDS, \
+      SRC := $(CMDS_DIR), \
+      DEST := $(JDK_OUTPUTDIR)/bin, \
+      FILES := $(call CacheFind, $(CMDS_DIR)), \
+  ))
+  TARGETS += $(COPY_CMDS)
+endif
+
+ifneq ($(CONF_DIR), )
+  $(eval $(call SetupCopyFiles, COPY_CONF, \
+      SRC := $(CONF_DIR), \
+      DEST := $(JDK_OUTPUTDIR)/lib, \
+      FILES := $(call CacheFind, $(CONF_DIR)), \
+  ))
+  TARGETS += $(COPY_CONF)
+endif
+
+all: $(TARGETS)
diff --git a/make/CreateBuildJdkCopy.gmk b/make/CreateBuildJdkCopy.gmk
new file mode 100644
index 0000000..ca8b3e1
--- /dev/null
+++ b/make/CreateBuildJdkCopy.gmk
@@ -0,0 +1,86 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include Modules.gmk
+
+MODULES_TO_COPY := $(call FindTransitiveDepsForModule, jdk.jlink) jdk.jlink
+
+################################################################################
+# Copy the modules needed to run jlink and jmod. Use bulk copy instead of
+# SetupCopyFiles since there are so many files.
+
+COPY_CLASSES_TARGET := $(BUILDJDK_OUTPUTDIR)/jdk/modules/_buildjdk-copy-maker
+
+$(COPY_CLASSES_TARGET): $(call CacheFind, $(wildcard \
+    $(addprefix $(JDK_OUTPUTDIR)/modules/, $(MODULES_TO_COPY))))
+	$(ECHO) $(LOG_INFO) "Copying java modules to buildjdk: $(MODULES_TO_COPY)"
+	$(RM) -r $(BUILDJDK_OUTPUTDIR)/jdk/modules
+	$(MKDIR) -p $(BUILDJDK_OUTPUTDIR)/jdk/modules
+	$(foreach m, $(MODULES_TO_COPY), \
+	    $(CP) -R $(JDK_OUTPUTDIR)/modules/$m \
+	        $(BUILDJDK_OUTPUTDIR)/jdk/modules/ $(NEWLINE))
+	$(TOUCH) $@
+
+TARGETS += $(COPY_CLASSES_TARGET)
+
+#$(eval $(call SetupCopyFiles, COPY_JDK_MODULES, \
+    SRC := $(BUILD_OUTPUT), \
+    DEST := $(BUILDJDK_OUTPUTDIR), \
+    FILES := $(call DoubleDollar, $(call DoubleDollar, $(call CacheFind, $(wildcard \
+        $(addprefix $(JDK_OUTPUTDIR)/modules/, $(MODULES_TO_COPY)))))), \
+))
+
+#TARGETS += $(COPY_JDK_MODULES)
+
+################################################################################
+
+$(eval $(call SetupCopyFiles, COPY_SUPPORT_HEADERS, \
+    SRC := $(BUILD_OUTPUT), \
+    DEST := $(BUILDJDK_OUTPUTDIR), \
+    FILES := $(call CacheFind, $(wildcard \
+        $(addprefix $(SUPPORT_OUTPUTDIR)/headers/, $(MODULES_TO_COPY)))), \
+))
+
+TARGETS += $(COPY_SUPPORT_HEADERS)
+
+################################################################################
+
+$(eval $(call SetupCopyFiles, COPY_JDK_LIB_FILES, \
+    SRC := $(BUILD_OUTPUT), \
+    DEST := $(BUILDJDK_OUTPUTDIR), \
+    FILES := $(JDK_OUTPUTDIR)/lib/tzdb.dat, \
+))
+
+TARGETS += $(COPY_JDK_LIB_FILES)
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: default all
diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk
new file mode 100644
index 0000000..fdfb7dc
--- /dev/null
+++ b/make/CreateJmods.gmk
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include Modules.gmk
+
+ifeq ($(MODULE), )
+  $(error MODULE must be set when calling CreateJmods.gmk)
+endif
+
+################################################################################
+
+LIBS_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
+    $(SUPPORT_OUTPUTDIR)/modules_libs-stripped $(IMPORT_MODULES_LIBS))))
+CMDS_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
+    $(SUPPORT_OUTPUTDIR)/modules_cmds-stripped $(IMPORT_MODULES_CMDS))))
+CONF_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
+    $(SUPPORT_OUTPUTDIR)/modules_conf $(IMPORT_MODULES_CONF))))
+CLASSES_DIR := $(wildcard $(JDK_OUTPUTDIR)/modules/$(MODULE))
+
+$(eval $(call FillCacheFind, \
+    $(LIBS_DIR) $(CMDS_DIR) $(CONF_DIR) $(CLASSES_DIR) \
+))
+
+ifneq ($(LIBS_DIR), )
+  JMOD_FLAGS += --libs $(LIBS_DIR)
+  DEPS += $(call CacheFind, $(LIBS_DIR))
+endif
+ifneq ($(CMDS_DIR), )
+  JMOD_FLAGS += --cmds $(CMDS_DIR)
+  DEPS += $(call CacheFind, $(CMDS_DIR))
+endif
+ifneq ($(CONF_DIR), )
+  JMOD_FLAGS += --config $(CONF_DIR)
+  DEPS += $(call CacheFind, $(CONF_DIR))
+endif
+ifneq ($(CLASSES_DIR), )
+  JMOD_FLAGS += --class-path $(CLASSES_DIR)
+  DEPS += $(call CacheFind, $(CLASSES_DIR))
+endif
+
+# Add dependencies on other jmod files
+DEPS += $(patsubst %, $(IMAGES_OUTPUTDIR)/jmods/%.jmod, \
+    $(call FindDepsForModule, $(MODULE)))
+
+# TODO: What about headers?
+# Create jmods in a temp dir and then move them into place to keep the
+# module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times.
+$(IMAGES_OUTPUTDIR)/jmods/$(MODULE).jmod: $(DEPS)
+	$(call LogWarn, Creating $(notdir $@))
+	$(call MakeDir, $(@D) $(SUPPORT_OUTPUTDIR)/jmods)
+	$(RM) $@ $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
+	$(JMOD) create \
+            --module-version $(VERSION_SHORT) \
+            --os-name $(REQUIRED_OS_NAME) \
+            --os-arch $(OPENJDK_TARGET_CPU_LEGACY) \
+            --os-version $(REQUIRED_OS_VERSION) \
+	    --modulepath $(IMAGES_OUTPUTDIR)/jmods\
+            --hash-dependencies '.*' \
+            --exclude '**_the.*' \
+	    $(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
+	$(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@
+
+TARGETS += $(IMAGES_OUTPUTDIR)/jmods/$(MODULE).jmod
+
+################################################################################
+
+all: $(TARGETS)
+
+################################################################################
diff --git a/make/GenerateModuleDeps.gmk b/make/GenerateModuleDeps.gmk
deleted file mode 100644
index b5427dd..0000000
--- a/make/GenerateModuleDeps.gmk
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# This file is included from Main.gmk only.
-
-include $(SRC_ROOT)/make/common/JavaCompilation.gmk
-include $(SRC_ROOT)/make/common/SetupJavaCompilers.gmk
-
-################################################################################
-
-$(eval $(call SetupJavaCompilation, BUILD_GENMODULESLIST, \
-    SETUP := BOOT_JAVAC, \
-    SRC := $(JDK_TOPDIR)/make/src/classes, \
-    INCLUDES := build/tools/module, \
-    EXCLUDE_FILES := ImageBuilder.java ModuleArchive.java, \
-    BIN := $(MAKESUPPORT_OUTPUTDIR)/bt_classes_moduleslist, \
-    DISABLE_SJAVAC := true, \
-))
-
-TOOL_GENMODULESLIST = $(JAVA_SMALL) \
-    -cp "$(MAKESUPPORT_OUTPUTDIR)/bt_classes_moduleslist" \
-    build.tools.module.GenModulesList
-
-MODULES_LIST_FILE := $(MAKESUPPORT_OUTPUTDIR)/modules.list
-# The module deps makefile is used from make/common/Modules.gmk
-MODULE_DEPS_MAKEFILE := $(MAKESUPPORT_OUTPUTDIR)/module-deps.gmk
-
-$(MODULES_LIST_FILE): $(SRC_ROOT)/modules.xml $(BUILD_GENMODULESLIST)
-	$(TOOL_GENMODULESLIST) -o $@ $(filter %.xml, $^)
-
-$(MODULE_DEPS_MAKEFILE): $(MODULES_LIST_FILE)
-	$(CAT) $^ | $(SED) -e 's/^\([^:]*\):/DEPS_\1 :=/g' > $@
-
-TARGETS += $(MODULE_DEPS_MAKEFILE)
-
-################################################################################
-
-# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, , GenerateModuleDeps.gmk))
-
-# Trigger generation of this file and restart make if it changed.
--include $(MODULE_DEPS_MAKEFILE)
diff --git a/make/GensrcModuleInfo.gmk b/make/GensrcModuleInfo.gmk
new file mode 100644
index 0000000..b53fc5a
--- /dev/null
+++ b/make/GensrcModuleInfo.gmk
@@ -0,0 +1,154 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# This file makes modifications to module-info.java files based on the build
+# configuration.
+#
+# Depending on build platform, imported modules and optional parts of the build
+# being active, some modules need to have extra exports, provides or uses
+# declarations added to them. These optional extras are defined in .extra files:
+#
+# src/<module>/<share,platform>/classes/module-info.java.extra
+#
+# The contents of the .extra files are simply extra lines that could fit into
+# the module-info file.
+#
+# This makefile is called once for each from-module with the variable
+# MODULE naming the from-module.
+#
+# The modified module-info.java files are put in the gensrc directory where
+# they will automatically override the static versions in the src tree.
+#
+################################################################################
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include Modules.gmk
+#include TextFileProcessing.gmk
+
+################################################################################
+# Define this here since jdk/make/Tools.gmk cannot be included from the top
+# make directory. Should probably move some tools away from the jdk repo.
+TOOL_GENMODULEINFOSOURCE = $(JAVA_SMALL) \
+    $(INTERIM_LANGTOOLS_ARGS) \
+    -cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes" \
+    build.tools.module.GenModuleInfoSource
+
+################################################################################
+
+# Name of data file. Keep module-info.java.ext until javafx has changed.
+MOD_FILENAME := module-info.java.extra module-info.java.ext
+
+# List all the possible sub directories inside a module source directory where
+# data might be stored.
+CLASSES_SUBDIRS += $(OPENJDK_TARGET_OS)/classes
+ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE))
+  CLASSES_SUBDIRS += $(OPENJDK_TARGET_OS_TYPE)/classes
+endif
+CLASSES_SUBDIRS += share/classes
+
+# TODO: When the deploy build is better integrated, this will get added globally
+# but for now need to add it here.
+ifeq ($(BUILD_DEPLOY), true)
+  ALL_TOP_SRC_DIRS += $(DEPLOY_TOPDIR)/src
+endif
+
+# Construct all possible src directories for the module.
+MODULE_CLASSES_DIRS := $(strip \
+    $(foreach sub, $(CLASSES_SUBDIRS), \
+        $(addsuffix /$(MODULE)/$(sub), $(ALL_TOP_SRC_DIRS))) \
+    $(addsuffix /$(MODULE), $(IMPORT_MODULES_SRC)))
+
+# Find all the .extra files in the src dirs.
+MOD_FILES := $(wildcard $(foreach f, $(MOD_FILENAME), $(addsuffix /$(f), \
+    $(MODULE_CLASSES_DIRS))))
+
+ifneq ($(MOD_FILES), )
+  # 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 ".\*" $f | $(TR) ' ' '/')))
+
+  # Filter the contents for modules that are actually being built
+  MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES)))
+  MODULES_FILTER += provides%
+  MODIFICATIONS := $(filter $(MODULES_FILTER), $(MOD_FILE_CONTENTS))
+
+  # 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))) \
+    $(eval package := $(word 2, $(split_line))) \
+    $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \
+    $(eval ARGS += -$(command) $(package)/$(to_module)))
+
+  ifneq ($(ARGS), )
+    $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
+        $(firstword $(call FindAllModuleInfos, $(MODULE))) \
+        $(BUILD_TOOLS_JDK) \
+        $(call DependOnVariable, ARGS)
+		$(MKDIR) -p $(@D)
+		$(RM) $@ $@.tmp
+		$(TOOL_GENMODULEINFOSOURCE) $(ARGS) -o $@.tmp $<
+		$(MV) $@.tmp $@
+
+    TARGETS += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java
+  endif
+
+# This doesn't work because javac only accepts one single exports line per
+# exported package.
+  # Restore the modifications to separate lines with spaces
+#  MODIFICATIONS := $(subst /,$(SPACE),$(MODIFICATIONS))
+
+#  ifneq ($(MODIFICATIONS), )
+#    $(eval $(call SetupTextFileProcessing, PROCESS_MODULE_INFO, \
+#        SOURCE_FILES := $(firstword $(call FindAllModuleInfos, $(MODULE))), \
+#        OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java, \
+#        REPLACEMENTS := } => $(MODIFICATIONS) }, \
+#    ))
+
+#    TARGETS += $(PROCESS_MODULE_INFO)
+#  endif
+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), )
+  ifneq ($(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java), )
+    $(shell $(RM) $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java)
+  endif
+endif
+
+################################################################################
+
+all: $(TARGETS)
diff --git a/make/HotspotWrapper.gmk b/make/HotspotWrapper.gmk
index eec08d6..6632155 100644
--- a/make/HotspotWrapper.gmk
+++ b/make/HotspotWrapper.gmk
@@ -25,7 +25,10 @@
 
 # Include the legacy hotspot-spec.gmk (which in turns includes spec.gmk)
 BASE_SPEC:=$(SPEC)
-include $(dir $(SPEC))hotspot-spec.gmk
+# Assign to HOTSPOT_SPEC so that the variable HOTSPOT_SPEC can be
+# overridden when building the buildjdk.
+HOTSPOT_SPEC := $(dir $(SPEC))hotspot-spec.gmk
+include $(HOTSPOT_SPEC)
 include MakeBase.gmk
 
 # Inclusion of this pseudo-target will cause make to execute this file
@@ -45,7 +48,7 @@
 # not doing it breaks builds on msys.
 $(HOTSPOT_OUTPUTDIR)/_hotspot.timestamp: $(HOTSPOT_FILES)
 	@$(MKDIR) -p $(HOTSPOT_OUTPUTDIR)
-	@($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(HOTSPOT_MAKE_ARGS) \
+	($(CD) $(HOTSPOT_TOPDIR)/make && $(MAKE) $(HOTSPOT_MAKE_ARGS) \
 	    LOG_LEVEL=$(LOG_LEVEL) SPEC=$(HOTSPOT_SPEC) BASE_SPEC=$(BASE_SPEC))
 	$(TOUCH) $@
 
diff --git a/make/Images.gmk b/make/Images.gmk
index 7fc0637..3aa4173 100644
--- a/make/Images.gmk
+++ b/make/Images.gmk
@@ -38,7 +38,7 @@
 
 ############################################################################
 
-MAIN_MODULES += java.se java.smartcardio jdk.httpserver jdk.sctp \
+MAIN_MODULES += java.se.ee java.smartcardio jdk.httpserver jdk.sctp \
                jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \
                jdk.accessibility jdk.internal.le jdk.dynalink \
                jdk.scripting.nashorn jdk.scripting.nashorn.shell \
@@ -49,10 +49,10 @@
                jdk.localedata jdk.naming.dns jdk.naming.rmi jdk.zipfs
 
 # tools
-TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev \
+TOOLS_MODULES += jdk.attach jdk.compiler \
                jdk.javadoc jdk.jcmd jdk.jconsole jdk.hotspot.agent jdk.jartool \
-               jdk.jdeps jdk.jdi jdk.jdwp.agent jdk.jshell jdk.policytool jdk.rmic \
-               jdk.xml.bind jdk.xml.ws
+               jdk.jdeps jdk.jdi jdk.jdwp.agent jdk.jlink jdk.jshell \
+               jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws jdk.internal.opt
 
 ifeq ($(OPENJDK_TARGET_OS), windows)
   PROVIDER_MODULES += jdk.crypto.mscapi
@@ -65,104 +65,151 @@
 JRE_MODULES := $(filter-out $(MODULES_FILTER), $(MAIN_MODULES) $(PROVIDER_MODULES))
 JDK_MODULES := $(filter-out $(MODULES_FILTER), $(JRE_MODULES) $(TOOLS_MODULES))
 
-# compact3 builds have additional modules
-JDK_COMPACT3_MODULES := java.compact3 java.smartcardio jdk.httpserver jdk.naming.dns \
-                       jdk.naming.rmi jdk.sctp jdk.security.auth jdk.management
+# Param 1 - Name of module
+define ReadImportMetaData
+  ifneq ($$(wildcard $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties), )
+    include_in_jre :=
+    include_in_jdk :=
+    include $(IMPORT_MODULES_MAKE)/$$(strip $1)/build.properties
+    ifeq ($$(include_in_jre), true)
+      JRE_MODULES += $1
+    endif
+    ifeq ($$(include_in_jdk), true)
+      JDK_MODULES += $1
+    endif
+  else
+    # Default to include in all
+    JRE_MODULES += $1
+    JDK_MODULES += $1
+  endif
+endef
+
+IMPORTED_MODULES := $(call FindImportedModules)
+$(foreach m, $(IMPORTED_MODULES), $(eval $(call ReadImportMetaData, $m)))
+
+# Compact builds have additional modules
+COMPACT_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec
+JRE_COMPACT1_MODULES := $(COMPACT_EXTRA_MODULES) java.compact1
+JRE_COMPACT2_MODULES := $(JRE_COMPACT1_MODULES) java.compact2 jdk.xml.dom jdk.httpserver
+JRE_COMPACT3_MODULES := $(JRE_COMPACT2_MODULES) java.compact3 java.smartcardio jdk.management \
+                        jdk.naming.dns jdk.naming.rmi jdk.sctp jdk.security.auth
 
 # Replacing double-comma with a single comma is to workaround the issue
 # with some version of make on windows that doesn't substitute spaces
 # with one comma properly as with make 4.0
-define SubstComma
-  $(subst $(COMMA)$(COMMA),$(COMMA),$(subst $(SPACE),$(COMMA),$(strip $1)))
-endef
+SubstComma = \
+    $(strip \
+        $(subst $(COMMA)$(COMMA),$(COMMA),$(subst $(SPACE),$(COMMA),$(strip $1))) \
+    )
+
 JRE_MODULES_LIST := $(call SubstComma, $(JRE_MODULES))
 JDK_MODULES_LIST := $(call SubstComma, $(JDK_MODULES))
+JRE_COMPACT1_MODULES_LIST := $(call SubstComma, $(JRE_COMPACT1_MODULES))
+JRE_COMPACT2_MODULES_LIST := $(call SubstComma, $(JRE_COMPACT2_MODULES))
+JRE_COMPACT3_MODULES_LIST := $(call SubstComma, $(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
+  $(call info-file-item, "JAVA_VERSION", "$(VERSION_NUMBER)")
+  $(call info-file-item, "JAVA_FULL_VERSION", "$(VERSION_STRING)")
+  $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
+  $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
+  $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
+  $(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)
 
 ################################################################################
 
-JRE_SORTED_MODULES := $(SUPPORT_OUTPUTDIR)/jre-sorted-modules
-JDK_SORTED_MODULES := $(SUPPORT_OUTPUTDIR)/jdk-sorted-modules
-JRE_COMPACT1_SORTED_MODULES := $(SUPPORT_OUTPUTDIR)/compact1-sorted-modules
-JRE_COMPACT2_SORTED_MODULES := $(SUPPORT_OUTPUTDIR)/compact2-sorted-modules
-JRE_COMPACT3_SORTED_MODULES := $(SUPPORT_OUTPUTDIR)/compact3-sorted-modules
-
-
-MODULES_CMDS := $(SUPPORT_OUTPUTDIR)/modules_cmds-stripped
-MODULES_LIBS := $(SUPPORT_OUTPUTDIR)/modules_libs-stripped
-MODULES_CONF := $(SUPPORT_OUTPUTDIR)/modules_conf
-
-JIMAGE_TOOL := $(JAVA_SMALL) \
-    -Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes \
-    -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.module.ImageBuilder \
-    --cmds $(MODULES_CMDS) \
-    --libs $(MODULES_LIBS) \
-    --configs $(MODULES_CONF) \
-    --classes $(JDK_OUTPUTDIR)/modules \
-    --endian $(OPENJDK_TARGET_CPU_ENDIAN) \
-    #
-
-MODULES_XML += $(SRC_ROOT)/modules.xml
-DEPENDENCIES := $(call CacheFind, \
-    $(SUPPORT_OUTPUTDIR)/modules_cmds \
-    $(SUPPORT_OUTPUTDIR)/modules_conf \
-    $(SUPPORT_OUTPUTDIR)/modules_libs) \
-    $(wildcard $(JDK_OUTPUTDIR)/modules/*/_*) \
-    $(MODULES_XML)
-    #
+JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod)
 
 # Use this file inside the image as target for make rule
 JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX)
 
-$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
-    $(call DependOnVariable, JDK_MODULES_LIST)
+JLINK_TOOL := $(JLINK) --modulepath $(IMAGES_OUTPUTDIR)/jmods \
+              --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
+              --release-info $(BASE_RELEASE_FILE)
+
+ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true)
+  JLINK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods
+endif
+
+$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
+    $(call DependOnVariable, JDK_MODULES_LIST) $(BASE_RELEASE_FILE)
 	$(ECHO) Creating jdk jimage
-	$(RM) -r $(JDK_IMAGE_DIR) $(JDK_SORTED_MODULES)
-	$(JIMAGE_TOOL) --mods $(JDK_MODULES_LIST) --output $(JDK_IMAGE_DIR) \
-	    $(MODULES_XML) > $(JDK_SORTED_MODULES)
+	$(RM) -r $(JDK_IMAGE_DIR)
+	$(JLINK_TOOL) --output $(JDK_IMAGE_DIR) \
+	    --addmods $(JDK_MODULES_LIST) $(JLINK_EXTRA_OPTS)
 	$(TOUCH) $@
 
-$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
-    $(call DependOnVariable, JRE_MODULES_LIST)
+$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
+    $(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE)
 	$(ECHO) Creating jre jimage
-	$(RM) -r $(JRE_IMAGE_DIR) $(JRE_SORTED_MODULES)
-	$(JIMAGE_TOOL) --mods $(JRE_MODULES_LIST) --output $(JRE_IMAGE_DIR) \
-	    $(MODULES_XML) > $(JRE_SORTED_MODULES)
+	$(RM) -r $(JRE_IMAGE_DIR)
+	$(JLINK_TOOL) --output $(JRE_IMAGE_DIR) \
+	    --addmods $(JRE_MODULES_LIST)
 	$(TOUCH) $@
 
 JRE_COMPACT1_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact1
 JRE_COMPACT2_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact2
 JRE_COMPACT3_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact3
 
-COMPACT_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec
-
-$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
-    $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST)
+$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
+    $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE)
 	$(ECHO) Creating jre compact1 jimage
-	$(RM) -r $(JRE_COMPACT1_IMAGE_DIR) $(JRE_COMPACT1_SORTED_MODULES)
-	$(JIMAGE_TOOL) \
-	    --mods $(call SubstComma, java.compact1 $(COMPACT_EXTRA_MODULES)) \
-	    --output $(JRE_COMPACT1_IMAGE_DIR) \
-	    $(MODULES_XML) > $(JRE_COMPACT1_SORTED_MODULES)
+	$(RM) -r $(JRE_COMPACT1_IMAGE_DIR)
+	$(JLINK_TOOL) --addmods $(JRE_COMPACT1_MODULES_LIST) \
+	    --output $(JRE_COMPACT1_IMAGE_DIR)
 	$(TOUCH) $@
 
-$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
-    $(call DependOnVariable, JRE_COMPACT2_MODULES_LIST)
+$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
+    $(call DependOnVariable, JRE_COMPACT2_MODULES_LIST) $(BASE_RELEASE_FILE)
 	$(ECHO) Creating jre compact2 jimage
-	$(RM) -r $(JRE_COMPACT2_IMAGE_DIR) $(JRE_COMPACT2_SORTED_MODULES)
-	$(JIMAGE_TOOL) \
-	    --mods $(call SubstComma, java.compact2 $(COMPACT_EXTRA_MODULES)) \
-	    --output $(JRE_COMPACT2_IMAGE_DIR) \
-	    $(MODULES_XML) > $(JRE_COMPACT2_SORTED_MODULES)
+	$(RM) -r $(JRE_COMPACT2_IMAGE_DIR)
+	$(JLINK_TOOL) --addmods $(JRE_COMPACT2_MODULES_LIST) \
+	    --output $(JRE_COMPACT2_IMAGE_DIR)
 	$(TOUCH) $@
 
-$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
-    $(call DependOnVariable, JRE_COMPACT3_MODULES_LIST)
+$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
+    $(call DependOnVariable, JRE_COMPACT3_MODULES_LIST) $(BASE_RELEASE_FILE)
 	$(ECHO) Creating jre compact3 jimage
-	$(RM) -r $(JRE_COMPACT3_IMAGE_DIR) $(JRE_COMPACT3_SORTED_MODULES)
-	$(JIMAGE_TOOL) \
-	    --mods $(call SubstComma, $(JDK_COMPACT3_MODULES) $(COMPACT_EXTRA_MODULES)) \
-	    --output $(JRE_COMPACT3_IMAGE_DIR) \
-	    $(MODULES_XML) > $(JRE_COMPACT3_SORTED_MODULES)
+	$(RM) -r $(JRE_COMPACT3_IMAGE_DIR)
+	$(JLINK_TOOL) --addmods $(JRE_COMPACT3_MODULES_LIST) \
+	    --output $(JRE_COMPACT3_IMAGE_DIR)
 	$(TOUCH) $@
 
 TOOL_JRE_TARGETS := $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE)
@@ -346,79 +393,6 @@
 JDK_TARGETS += $(JDK_DOC_TARGETS)
 
 ################################################################################
-# Release file
-
-JRE_INFO_FILE := $(JRE_IMAGE_DIR)/release
-JDK_INFO_FILE := $(JDK_IMAGE_DIR)/release
-JRE_COMPACT1_INFO_FILE := $(JRE_COMPACT1_IMAGE_DIR)/release
-JRE_COMPACT2_INFO_FILE := $(JRE_COMPACT2_IMAGE_DIR)/release
-JRE_COMPACT3_INFO_FILE := $(JRE_COMPACT3_IMAGE_DIR)/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
-  $(call info-file-item, "JAVA_VERSION", "$(VERSION_NUMBER)")
-  $(call info-file-item, "JAVA_FULL_VERSION", "$(VERSION_STRING)")
-  $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
-  $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
-  $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
-  $(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))")
-  $(call info-file-item, "MODULES", "`$(CAT) $1`")
-endef
-
-# Param 1 - The file containing the MODULES list
-define prepare-info-file
-  $(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@))
-  $(MKDIR) -p $(@D)
-  $(RM) $@
-endef
-
-define info-file
-  $(call prepare-info-file, $1)
-  $(call create-info-file, $1)
-endef
-
-# Create a variable dependency file common for all release info files. The
-# sorted module list will only change if the image is regenerated, which will
-# trigger a rebuild of these files anyway.
-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)
-
-$(JRE_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call info-file, $(JRE_SORTED_MODULES))
-
-$(JDK_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call info-file, $(JDK_SORTED_MODULES))
-
-$(JRE_COMPACT1_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call info-file, $(JRE_COMPACT1_SORTED_MODULES))
-	$(call info-file-item, "JAVA_PROFILE", "compact1")
-
-$(JRE_COMPACT2_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call info-file, $(JRE_COMPACT2_SORTED_MODULES))
-	$(call info-file-item, "JAVA_PROFILE", "compact2")
-
-$(JRE_COMPACT3_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(call info-file, $(JRE_COMPACT3_SORTED_MODULES))
-	$(call info-file-item, "JAVA_PROFILE", "compact3")
-
-JRE_TARGETS += $(JRE_INFO_FILE)
-JDK_TARGETS += $(JDK_INFO_FILE)
-JRE_COMPACT1_TARGETS += $(JRE_COMPACT1_INFO_FILE)
-JRE_COMPACT2_TARGETS += $(JRE_COMPACT2_INFO_FILE)
-JRE_COMPACT3_TARGETS += $(JRE_COMPACT3_INFO_FILE)
-
-################################################################################
 # src.zip
 
 $(JDK_IMAGE_DIR)/src.zip: $(SUPPORT_OUTPUTDIR)/src.zip
@@ -435,7 +409,7 @@
       DEST := $(JDK_IMAGE_DIR)/demo, \
       FILES := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demos/image), \
           $(call DoubleDollar, $(call DoubleDollar, \
-          $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \
+      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \
           -type f -a ! \( -name "_the*" -o -name "javac_state" \) )))), \
   ))
 
@@ -445,7 +419,7 @@
 ################################################################################
 # /sample dir
 
-$(eval $(call SetupCopyFiles, COPY_SAMPLES, \
+$(eval $(call SetupCopyFiles,COPY_SAMPLES, \
     SRC := $(SUPPORT_OUTPUTDIR)/sample/image, \
     DEST := $(JDK_IMAGE_DIR)/sample, \
     FILES := $(if $(wildcard $(SUPPORT_OUTPUTDIR)/sample/image), \
diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk
index 0e0be3f..f0b1701 100644
--- a/make/Javadoc.gmk
+++ b/make/Javadoc.gmk
@@ -1,4 +1,4 @@
-# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -138,26 +138,48 @@
 # to $(PATH_SEP) being interpreted as an end of
 # command (newline or shell ; character)
 ALL_SOURCE_DIRS := $(wildcard \
-      $(JDK_TOPDIR)/src/*/share/classes \
+      $(SUPPORT_OUTPUTDIR)/gensrc/j* \
+      $(if $(IMPORT_MODULES_SRC), $(IMPORT_MODULES_SRC)/*) \
       $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS)/classes \
       $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS_TYPE)/classes \
+      $(JDK_TOPDIR)/src/*/share/classes \
+      $(HOTSPOT_TOPDIR)/src/*/share/classes \
       $(LANGTOOLS_TOPDIR)/src/*/share/classes \
       $(NASHORN_TOPDIR)/src/*/share/classes \
       $(CORBA_TOPDIR)/src/*/share/classes \
       $(JAXP_TOPDIR)/src/*/share/classes \
       $(JAXWS_TOPDIR)/src/*/share/classes \
-      $(SUPPORT_OUTPUTDIR)/gensrc/j* \
       $(SUPPORT_OUTPUTDIR)/rmic/j* \
       $(JDK_TOPDIR)/src/*/share/doc/stub \
       ) \
       #
 
+ALL_MODULE_SOURCE_DIRS := \
+      $(SUPPORT_OUTPUTDIR)/gensrc/* \
+      $(if $(IMPORT_MODULES_SRC), $(IMPORT_MODULES_SRC)/*) \
+      $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS)/classes \
+      $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS_TYPE)/classes \
+      $(JDK_TOPDIR)/src/*/share/classes \
+      $(HOTSPOT_TOPDIR)/src/*/share/classes \
+      $(LANGTOOLS_TOPDIR)/src/*/share/classes \
+      $(NASHORN_TOPDIR)/src/*/share/classes \
+      $(CORBA_TOPDIR)/src/*/share/classes \
+      $(JAXP_TOPDIR)/src/*/share/classes \
+      $(JAXWS_TOPDIR)/src/*/share/classes \
+      $(SUPPORT_OUTPUTDIR)/rmic/* \
+      $(JDK_TOPDIR)/src/*/share/doc/stub \
+      #
+
+
 # List with classpath separator between them
 EMPTY:=
 SPACE:= $(EMPTY) $(EMPTY)
 RELEASEDOCS_SOURCEPATH = \
     $(subst $(SPACE),$(PATH_SEP),$(strip $(ALL_SOURCE_DIRS)))
 
+RELEASEDOCS_MODULESOURCEPATH = \
+    $(subst $(SPACE),$(PATH_SEP),$(strip $(ALL_MODULE_SOURCE_DIRS)))
+
 define prep-target
 	$(MKDIR) -p $(@D)
 	$(RM) $@
@@ -372,6 +394,9 @@
 COREAPI_OPTIONS_FILE = $(DOCSTMPDIR)/coredocs.options
 COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages
 
+# The modules required to be documented
+COREAPI_MODULES = java.se.ee
+
 coredocs: $(COREAPI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -391,7 +416,9 @@
           $(call COMMON_JAVADOCTAGS) ; \
           $(call OptionOnly,-Xdoclint:reference) ; \
           $(call OptionOnly,-Xdoclint/package:-org.omg.*) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(COREAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ISO-8859-1) ; \
 	  $(call OptionOnly,-splitIndex) ; \
 	  $(call OptionPair,-overview,$(COREAPI_OVERVIEW)) ; \
@@ -431,6 +458,9 @@
 DOCLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/docletapi.options
 DOCLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/docletapi.packages
 
+# The modules required to be documented
+DOCLETAPI_MODULES = jdk.javadoc
+
 docletapidocs: $(DOCLETAPI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -449,7 +479,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(DOCLETAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-breakiterator) ; \
 	  $(call OptionPair,-doctitle,$(DOCLETAPI_DOCTITLE)) ; \
@@ -488,6 +520,9 @@
 OLD_DOCLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/old-docletapi.options
 OLD_DOCLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/old-docletapi.packages
 
+# The modules required to be documented
+OLD_DOCLETAPI_MODULES = jdk.javadoc
+
 olddocletapidocs: $(OLD_DOCLETAPI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -506,7 +541,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(OLD_DOCLETAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-breakiterator) ; \
 	  $(call OptionPair,-doctitle,$(OLD_DOCLETAPI_DOCTITLE)) ; \
@@ -541,6 +578,9 @@
 TAGLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/tagletapi.options
 TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages
 
+# The modules required to be documented
+TAGLETAPI_MODULES = jdk.javadoc
+
 tagletapidocs: $(TAGLETAPI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -564,7 +604,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(TAGLETAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nonavbar) ; \
 	  $(call OptionOnly,-noindex) ; \
@@ -599,6 +641,9 @@
 DOMAPI_OPTIONS_FILE = $(DOCSTMPDIR)/domapi.options
 DOMAPI_PACKAGES_FILE = $(DOCSTMPDIR)/domapi.packages
 
+# The modules required to be documented
+DOMAPI_MODULES = java.xml,jdk.xml.dom
+
 domapidocs: $(DOMAPI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -617,7 +662,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(DOMAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-splitIndex) ; \
 	  $(call OptionPair,-doctitle,$(DOMAPI_DOCTITLE)) ; \
@@ -663,6 +710,9 @@
 JDI_OPTIONS_FILE = $(DOCSTMPDIR)/jdi.options
 JDI_PACKAGES_FILE = $(DOCSTMPDIR)/jdi.packages
 
+# The modules required to be documented
+JDI_MODULES = jdk.jdi
+
 jdidocs: $(JDI_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -681,7 +731,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JDI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionPair,-overview,$(JDI_OVERVIEW)) ; \
 	  $(call OptionPair,-doctitle,$(JDI_DOCTITLE)) ; \
@@ -751,6 +803,9 @@
 JAAS_OPTIONS_FILE = $(DOCSTMPDIR)/jaas.options
 JAAS_PACKAGES_FILE = $(DOCSTMPDIR)/jaas.packages
 
+# The modules required to be documented
+JAAS_MODULES = jdk.security.auth
+
 jaasdocs: $(JAAS_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -769,7 +824,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JAAS_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionPair,-overview,$(JAAS_OVERVIEW)) ; \
 	  $(call OptionPair,-doctitle,$(JAAS_DOCTITLE)) ; \
@@ -805,6 +862,9 @@
 JGSS_OPTIONS_FILE = $(DOCSTMPDIR)/jgss.options
 JGSS_PACKAGES_FILE = $(DOCSTMPDIR)/jgss.packages
 
+# The modules required to be documented
+JGSS_MODULES = jdk.security.jgss
+
 jgssdocs: $(JGSS_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -823,7 +883,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JGSS_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-overview,$(JGSS_OVERVIEW)) ; \
@@ -859,6 +921,9 @@
 SMARTCARDIO_OPTIONS_FILE = $(DOCSTMPDIR)/smartcardio.options
 SMARTCARDIO_PACKAGES_FILE = $(DOCSTMPDIR)/smartcardio.packages
 
+# The modules required to be documented
+SMARTCARDIO_MODULES = java.smartcardio
+
 smartcardiodocs: $(SMARTCARDIO_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -877,7 +942,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(SMARTCARDIO_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(SMARTCARDIO_DOCTITLE)) ; \
@@ -911,6 +978,9 @@
 HTTPSERVER_OPTIONS_FILE = $(DOCSTMPDIR)/httpserver.options
 HTTPSERVER_PACKAGES_FILE = $(DOCSTMPDIR)/httpserver.packages
 
+# The modules required to be documented
+HTTPSERVER_MODULES = jdk.httpserver
+
 httpserverdocs: $(HTTPSERVER_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -929,7 +999,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(HTTPSERVER_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(HTTPSERVER_DOCTITLE)) ; \
@@ -967,6 +1039,9 @@
 MGMT_OPTIONS_FILE = $(DOCSTMPDIR)/mgmt.options
 MGMT_PACKAGES_FILE = $(DOCSTMPDIR)/mgmt.packages
 
+# The modules required to be documented
+MGMT_MODULES = jdk.management
+
 mgmtdocs: $(MGMT_INDEX_FILE)
 
 # Set relative location to core api document root
@@ -990,7 +1065,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(MGMT_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-overview,$(MGMT_OVERVIEW)) ; \
@@ -1025,6 +1102,9 @@
 ATTACH_OPTIONS_FILE = $(DOCSTMPDIR)/attach.options
 ATTACH_PACKAGES_FILE = $(DOCSTMPDIR)/attach.packages
 
+# The modules required to be documented
+ATTACH_MODULES = jdk.attach
+
 attachdocs: $(ATTACH_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1043,7 +1123,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(ATTACH_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(ATTACH_DOCTITLE)) ; \
@@ -1077,6 +1159,9 @@
 JCONSOLE_OPTIONS_FILE = $(DOCSTMPDIR)/jconsole.options
 JCONSOLE_PACKAGES_FILE = $(DOCSTMPDIR)/jconsole.packages
 
+# The modules required to be documented
+JCONSOLE_MODULES = jdk.jconsole
+
 jconsoledocs: $(JCONSOLE_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1095,7 +1180,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JCONSOLE_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(JCONSOLE_DOCTITLE)) ; \
@@ -1131,6 +1218,9 @@
 TREEAPI_OPTIONS_FILE = $(DOCSTMPDIR)/treeapi.options
 TREEAPI_PACKAGES_FILE = $(DOCSTMPDIR)/treeapi.packages
 
+# The modules required to be documented
+TREEAPI_MODULES = jdk.compiler
+
 treeapidocs: $(TREEAPI_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1149,7 +1239,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(TREEAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionPair,-doctitle,$(TREEAPI_DOCTITLE)) ; \
 	  $(call OptionPair,-windowtitle,$(TREEAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
@@ -1185,6 +1277,9 @@
 NASHORNAPI_OPTIONS_FILE = $(DOCSTMPDIR)/nashornapi.options
 NASHORNAPI_PACKAGES_FILE = $(DOCSTMPDIR)/nashornapi.packages
 
+# The modules required to be documented
+NASHORNAPI_MODULES = jdk.scripting.nashorn
+
 nashornapidocs: $(NASHORNAPI_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1203,7 +1298,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(NASHORNAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionPair,-doctitle,$(NASHORNAPI_DOCTITLE)) ; \
 	  $(call OptionPair,-windowtitle,$(NASHORNAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
@@ -1239,6 +1336,9 @@
 DYNALINKAPI_OPTIONS_FILE = $(DOCSTMPDIR)/dynalinkapi.options
 DYNALINKAPI_PACKAGES_FILE = $(DOCSTMPDIR)/dynalinkapi.packages
 
+# The modules required to be documented
+DYNALINKAPI_MODULES = jdk.dynalink
+
 dynalinkapidocs: $(DYNALINKAPI_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1257,7 +1357,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(DYNALINKAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionPair,-doctitle,$(DYNALINKAPI_DOCTITLE)) ; \
 	  $(call OptionPair,-windowtitle,$(DYNALINKAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
@@ -1291,6 +1393,9 @@
 SCTPAPI_OPTIONS_FILE = $(DOCSTMPDIR)/sctp.options
 SCTPAPI_PACKAGES_FILE = $(DOCSTMPDIR)/sctp.packages
 
+# The modules required to be documented
+SCTPAPI_MODULES = jdk.sctp
+
 sctpdocs: $(SCTPAPI_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1309,7 +1414,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(SCTPAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(SCTPAPI_DOCTITLE)) ; \
@@ -1343,6 +1450,9 @@
 JACCESSAPI_OPTIONS_FILE = $(DOCSTMPDIR)/jaccess.options
 JACCESSAPI_PACKAGES_FILE = $(DOCSTMPDIR)/jaccess.packages
 
+# The modules required to be documented
+JACCESSAPI_MODULES = jdk.accessibility
+
 jaccessdocs: $(JACCESSAPI_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1361,7 +1471,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
 	  $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:all) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JACCESSAPI_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(JACCESSAPI_DOCTITLE)) ; \
@@ -1395,6 +1507,9 @@
 JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options
 JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages
 
+# The modules required to be documented
+JDKNET_MODULES = java.base
+
 jdknetdocs: $(JDKNET_INDEX_HTML)
 
 # Set relative location to core api document root
@@ -1413,7 +1528,9 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
 	  $(call OptionOnly,-Xdoclint:none) ; \
-	  $(call OptionPair,-sourcepath,$(RELEASEDOCS_SOURCEPATH)) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JDKNET_MODULES)) ; \
 	  $(call OptionPair,-encoding,ascii) ; \
 	  $(call OptionOnly,-nodeprecatedlist) ; \
 	  $(call OptionPair,-doctitle,$(JDKNET_DOCTITLE)) ; \
@@ -1428,6 +1545,69 @@
 	$(prep-target)
 	$(call PackageFilter,$(JDKNET_PKGS))
 
+#############################################################
+#
+# jlink plugin API docs
+#
+# TODO: Need to decide when the plugin API is ready to publish as experimental API.
+# This target is temporarily added for internal use for now.
+#        
+
+ALL_OTHER_TARGETS += jlinkdocs
+
+JLINK_PLUGIN_FIRST_COPYRIGHT_YEAR = 2015
+JLINK_PLUGIN_DOCDIR := $(JDK_API_DOCSDIR)/jlink
+JLINK_PLUGIN2COREAPI := ../$(JDKJRE2COREAPI)
+JLINK_PLUGIN_DOCTITLE := JLink Plugin API - EXPERIMENTAL
+JLINK_PLUGIN_WINDOWTITLE := JLink Plugin API - EXPERIMENTAL
+JLINK_PLUGIN_HEADER := <strong>JLink Plugin API - EXPERIMENTAL</strong>
+JLINK_PLUGIN_BOTTOM := $(call CommonBottom,$(JLINK_PLUGIN_FIRST_COPYRIGHT_YEAR))
+JLINK_PLUGIN_PKGS = jdk.tools.jlink \
+    jdk.tools.jlink.builder \
+    jdk.tools.jlink.plugin
+
+JLINK_PLUGIN_INDEX_HTML = $(JLINK_PLUGIN_DOCDIR)/index.html
+JLINK_PLUGIN_OPTIONS_FILE = $(DOCSTMPDIR)/jlinkplugins.options
+JLINK_PLUGIN_PACKAGES_FILE = $(DOCSTMPDIR)/jlinkplugins.packages
+
+# The modules required to be documented
+JLINK_PLUGIN_MODULES = jdk.jlink
+
+jlinkdocs: $(JLINK_PLUGIN_INDEX_HTML)
+
+# Set relative location to core api document root
+$(JLINK_PLUGIN_INDEX_HTML): GET2DOCSDIR=$(JLINK_PLUGIN2COREAPI)/..
+
+# Run javadoc if the index file is out of date or missing
+$(JLINK_PLUGIN_INDEX_HTML): $(JLINK_PLUGIN_OPTIONS_FILE) $(JLINK_PLUGIN_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
+	$(prep-javadoc)
+	$(call JavadocSummary,$(JLINK_PLUGIN_OPTIONS_FILE),$(JLINK_PLUGIN_PACKAGES_FILE))
+	$(JAVADOC_CMD_SMALL) -d $(@D) \
+	    @$(JLINK_PLUGIN_OPTIONS_FILE) @$(JLINK_PLUGIN_PACKAGES_FILE)
+
+# Create file with javadoc options in it
+$(JLINK_PLUGIN_OPTIONS_FILE):
+	$(prep-target)
+	@($(call COMMON_JAVADOCFLAGS) ; \
+          $(call COMMON_JAVADOCTAGS) ; \
+	  $(call OptionOnly,-Xdoclint:none) ; \
+          $(call OptionPair,-system,none) ; \
+	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
+	  $(call OptionPair,-addmods,$(JLINK_PLUGIN_MODULES)) ; \
+	  $(call OptionPair,-encoding,ascii) ; \
+	  $(call OptionOnly,-nodeprecatedlist) ; \
+	  $(call OptionPair,-doctitle,$(JLINK_PLUGIN_DOCTITLE)) ; \
+	  $(call OptionPair,-windowtitle,$(JLINK_PLUGIN_WINDOWTITLE) $(DRAFT_WINTITLE)); \
+	  $(call OptionPair,-header,$(JLINK_PLUGIN_HEADER)$(DRAFT_HEADER)); \
+	  $(call OptionPair,-bottom,$(JLINK_PLUGIN_BOTTOM)$(DRAFT_BOTTOM)); \
+	  $(call OptionTrip,-linkoffline,$(JLINK_PLUGIN2COREAPI),$(COREAPI_DOCSDIR)/); \
+	) >> $@
+
+# Create a file with the package names in it
+$(JLINK_PLUGIN_PACKAGES_FILE): $(call PackageDependencies,$(JLINK_PLUGIN_PKGS))
+	$(prep-target)
+	$(call PackageFilter,$(JLINK_PLUGIN_PKGS))
+
 
 otherdocs: $(ALL_OTHER_TARGETS)
 
diff --git a/make/Jprt.gmk b/make/Jprt.gmk
index 892e46c..6b77829 100644
--- a/make/Jprt.gmk
+++ b/make/Jprt.gmk
@@ -36,6 +36,10 @@
     override JPRT_ARCHIVE_INSTALL_BUNDLE := \
         $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_INSTALL_BUNDLE))
   endif
+  ifdef JPRT_ARCHIVE_MODULES_BUNDLE
+    override JPRT_ARCHIVE_MODULES_BUNDLE := \
+        $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_MODULES_BUNDLE))
+  endif
   ifdef JPRT_ARCHIVE_TEST_BUNDLE
     override JPRT_ARCHIVE_TEST_BUNDLE := \
         $(shell $(CYGPATH) -u $(JPRT_ARCHIVE_TEST_BUNDLE))
@@ -54,6 +58,9 @@
 ifndef JPRT_ARCHIVE_INSTALL_BUNDLE
   JPRT_ARCHIVE_INSTALL_BUNDLE=/tmp/jprt_bundles/product-install.zip
 endif
+ifndef JPRT_ARCHIVE_MODULES_BUNDLE
+  JPRT_ARCHIVE_MODULES_BUNDLE=/tmp/jprt_bundles/modules.zip
+endif
 ifndef JPRT_ARCHIVE_TEST_BUNDLE
   JPRT_ARCHIVE_TEST_BUNDLE=/tmp/jprt_bundles/test-image.zip
 endif
@@ -66,7 +73,8 @@
 endif
 
 # This target must be called in the context of a SPEC file
-jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_TEST_BUNDLE)
+jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_TEST_BUNDLE) \
+    $(JPRT_ARCHIVE_MODULES_BUNDLE)
 
 ifeq ($(GCOV_ENABLED), true)
   jprt_bundle: $(JPRT_ARCHIVE_SYMBOLS_BUNDLE)
@@ -78,6 +86,11 @@
 	$(RM) $@
 	$(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@
 
+$(JPRT_ARCHIVE_MODULES_BUNDLE): bundles
+	$(MKDIR) -p $(@D)
+	$(RM) $@
+	$(CP) $(BUILD_OUTPUT)/bundles/modules.zip $@
+
 $(JPRT_ARCHIVE_TEST_BUNDLE): bundles
 	$(MKDIR) -p $(@D)
 	$(RM) $@
@@ -104,6 +117,8 @@
 	    $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip .
 	$(CD) $(SRC_TEST_IMAGE_DIR) && $(ZIP) -y -q -r \
 	    $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip .
+	$(CD) $(IMAGES_OUTPUTDIR)/jmods && $(ZIP) -y -q -r \
+	    $(BUILD_OUTPUT)/bundles/modules.zip .
 	if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \
 	  $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -y -q -r \
 	      $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \
diff --git a/make/JrtfsJar.gmk b/make/JrtfsJar.gmk
index 2f8931a..ce5d5be 100644
--- a/make/JrtfsJar.gmk
+++ b/make/JrtfsJar.gmk
@@ -28,6 +28,7 @@
 include $(SPEC)
 include MakeBase.gmk
 include JarArchive.gmk
+include SetupJavaCompilers.gmk
 include TextFileProcessing.gmk
 
 # This rule will be depended on due to the MANIFEST line
@@ -40,10 +41,32 @@
       @@COMPANY_NAME@@ => $(COMPANY_NAME) , \
 ))
 
-$(eval $(call SetupJarArchive, JRTFS_JAR, \
-    SRCS := $(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes, \
+JIMAGE_PKGS := \
+    jdk/internal/jimage \
+    jdk/internal/jrtfs \
+    #
+
+$(eval $(call SetupJavaCompilation,BUILD_JRTFS, \
+    SETUP := GENERATE_OLDBYTECODE, \
+    SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
+    EXCLUDE_FILES := module-info.java, \
+    INCLUDES := $(JIMAGE_PKGS), \
+    BIN := $(SUPPORT_OUTPUTDIR)/jrtfs_classes))
+
+# Because of the explicit INCLUDES in the compilation setup above, the service provider
+# file will not be copied unless META-INF/services would also be added to the INCLUDES.
+# Adding META-INF/services would include all files in that directory when only the one
+# is needed, which is why this explicit copy is defined instead.
+$(eval $(call SetupCopyFiles,COPY_JIMAGE_SERVICE_PROVIDER, \
+    SRC := $(JDK_TOPDIR)/src/java.base/share/classes, \
+    DEST := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
+    FILES := META-INF/services/java.nio.file.spi.FileSystemProvider))
+
+$(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
+    DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
+    SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
     JAR := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar, \
     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
 ))
 
-all: $(JRTFS_JAR)
+all: $(BUILD_JRTFS_JAR)
diff --git a/make/Main.gmk b/make/Main.gmk
index 66509dd..5d8137f 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -42,8 +42,6 @@
 
 # Load the vital tools for all the makefiles.
 include $(SRC_ROOT)/make/common/MakeBase.gmk
-# Explicitly generate module deps makefile data
-include $(SRC_ROOT)/make/GenerateModuleDeps.gmk
 include $(SRC_ROOT)/make/common/Modules.gmk
 
 # Declare ALL_TARGETS as an immediate variable. This variable is a list of all
@@ -113,6 +111,24 @@
 CORBA_GENSRC_TARGETS := $(filter %-gensrc-corba, $(GENSRC_TARGETS))
 HOTSPOT_GENSRC_TARGETS := $(filter %-gensrc-hotspot, $(GENSRC_TARGETS))
 
+GENSRC_MODULEINFO_MODULES := $(ALL_MODULES)
+GENSRC_MODULEINFO_TARGETS := $(addsuffix -gensrc-moduleinfo, \
+    $(GENSRC_MODULEINFO_MODULES))
+
+GENSRC_MODULES := $(GENSRC_MODULEINFO_MODULES)
+GENSRC_TARGETS += $(sort $(GENSRC_MODULEINFO_TARGETS) \
+    $(addsuffix -gensrc, $(GENSRC_MODULES)))
+
+define DeclareModuleInfoRecipe
+  $1-gensrc-moduleinfo:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) \
+	    -f GensrcModuleInfo.gmk MODULE=$1)
+
+  $1-gensrc: $1-gensrc-moduleinfo
+endef
+
+$(foreach m, $(GENSRC_MODULEINFO_MODULES), $(eval $(call DeclareModuleInfoRecipe,$m)))
+
 ALL_TARGETS += $(GENSRC_TARGETS)
 
 ################################################################################
@@ -136,11 +152,27 @@
     USE_WRAPPER := true, \
     MULTIPLE_MAKEFILES := true))
 
-ALL_TARGETS += $(COPY_TARGETS)
+ALL_COPY_MODULES += $(COPY_MODULES)
+ALL_COPY_TARGETS += $(COPY_TARGETS)
+
+IMPORT_COPY_MODULES := $(call FindImportedModules)
+IMPORT_COPY_TARGETS := $(addsuffix -copy, $(IMPORT_COPY_MODULES))
+ALL_COPY_MODULES += $(IMPORT_COPY_MODULES)
+ALL_COPY_TARGETS += $(IMPORT_COPY_TARGETS)
+
+define DeclareImportCopyRecipe
+  $1-copy:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) \
+	    -f CopyImportModules.gmk MODULE=$1)
+endef
+
+$(foreach m, $(IMPORT_COPY_MODULES), $(eval $(call DeclareImportCopyRecipe,$m)))
+
+ALL_TARGETS += $(ALL_COPY_TARGETS)
 
 ################################################################################
 # Targets for compiling all java modules. Nashorn is treated separately.
-JAVA_MODULES := $(call FindJavaModules)
+JAVA_MODULES := $(ALL_MODULES)
 JAVA_TARGETS := $(addsuffix -java, $(JAVA_MODULES))
 
 define DeclareCompileJavaRecipe
@@ -214,7 +246,48 @@
 ALL_TARGETS += demos-jdk samples-jdk
 
 ################################################################################
-# Image targets
+# Jigsaw specific data and analysis targets.
+
+generate-summary:
+	+($(CD) $(JDK_TOPDIR)/make && $(MAKE) -f GenerateModuleSummary.gmk)
+
+ALL_TARGETS += generate-summary
+
+################################################################################
+# Strip binaries targets
+
+STRIP_MODULES := $(sort $(LIBS_MODULES) $(LAUNCHER_MODULES) $(COPY_MODULES) \
+    $(GENDATA_MODULES))
+STRIP_TARGETS := $(addsuffix -strip, $(STRIP_MODULES))
+
+define DeclareStripRecipe
+  $1-strip:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f StripBinaries.gmk \
+	    MODULE=$1)
+endef
+
+$(foreach m, $(STRIP_MODULES), $(eval $(call DeclareStripRecipe,$m)))
+
+ALL_TARGETS += $(STRIP_TARGETS)
+
+################################################################################
+# Jmod targets
+
+JMOD_MODULES := $(ALL_MODULES)
+JMOD_TARGETS := $(addsuffix -jmod, $(JMOD_MODULES))
+
+define DeclareJmodRecipe
+  $1-jmod:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CreateJmods.gmk \
+	    MODULE=$1)
+endef
+
+$(foreach m, $(JMOD_MODULES), $(eval $(call DeclareJmodRecipe,$m)))
+
+ALL_TARGETS += $(JMOD_TARGETS)
+
+################################################################################
+# 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.
@@ -236,9 +309,6 @@
 zip-source:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f ZipSource.gmk)
 
-strip-binaries:
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f StripBinaries.gmk)
-
 jrtfs-jar:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f JrtfsJar.gmk)
 
@@ -251,7 +321,7 @@
 mac-bundles-jdk:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f MacBundles.gmk)
 
-ALL_TARGETS += source-tips bootcycle-images zip-security zip-source strip-binaries \
+ALL_TARGETS += source-tips bootcycle-images zip-security zip-source \
     jrtfs-jar jimages profiles mac-bundles-jdk
 
 ################################################################################
@@ -266,6 +336,28 @@
 ALL_TARGETS += docs-javadoc docs-jvmtidoc
 
 ################################################################################
+# Cross compilation support
+
+ifeq ($(CREATE_BUILDJDK), true)
+  # This target is only called by the recursive call below.
+  create-buildjdk-compile-hotspot-helper: hotspot
+  create-buildjdk-compile-modules-helper: jdk.jlink-launchers java.base-copy
+endif
+
+create-buildjdk-copy:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CreateBuildJdkCopy.gmk)
+
+create-buildjdk-compile-hotspot create-buildjdk-compile-modules:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Main.gmk \
+	    $@-helper \
+	    SPEC=$(dir $(SPEC))buildjdk-spec.gmk \
+	    HOTSPOT_SPEC=$(dir $(SPEC))buildjdk-spec.gmk \
+	    CREATING_BUILDJDK=true)
+
+ALL_TARGETS += create-buildjdk-copy create-buildjdk-compile-hotspot \
+    create-buildjdk-compile-modules
+
+################################################################################
 # Build tests
 #
 
@@ -322,16 +414,6 @@
     test-hotspot-internal test-jdk-jtreg-native test-make
 
 ################################################################################
-# Verification targets
-
-verify-modules:
-	@$(call TargetEnter)
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CheckModules.gmk)
-	@$(call TargetExit)
-
-ALL_TARGETS += verify-modules
-
-################################################################################
 # Install targets
 
 install:
@@ -370,6 +452,8 @@
 
   $(JDK_GENSRC_TARGETS): interim-langtools buildtools-jdk
 
+  $(GENSRC_MODULEINFO_TARGETS): buildtools-jdk
+
   $(GENDATA_TARGETS): interim-langtools buildtools-jdk
 
   interim-rmic: interim-langtools
@@ -407,8 +491,11 @@
   $(foreach m, $(RMIC_MODULES), $(eval $m-rmic: $m-java))
 
   # Declare dependencies from <module>-lib to <module>-java
-  # Skip modules that do not have java source.
+  # Skip modules that do not have java source. When creating a BUILD_JDK, the
+  # java compilation has already been done by the normal build and copied in.
+  ifneq ($(CREATING_BUILDJDK), true)
   $(foreach m, $(filter $(JAVA_MODULES), $(LIBS_MODULES)), $(eval $m-libs: $m-java))
+  endif
 
   # Declare dependencies from all other <module>-lib to java.base-lib
   $(foreach t, $(filter-out java.base-libs, $(LIBS_TARGETS)), \
@@ -438,31 +525,57 @@
 
   jdk.jdeps-gendata: java rmic
 
+  # Declare dependencies from <module>-strip to libs, launchers, gendata and copy
+  $(foreach m, $(LIBS_MODULES), $(eval $m-strip: $m-libs))
+  $(foreach m, $(LAUNCHER_MODULES), $(eval $m-strip: $m-launchers))
+  $(foreach m, $(GENDATA_MODULES), $(eval $m-strip: $m-gendata))
+  $(foreach m, $(COPY_MODULES), $(eval $m-strip: $m-copy))
+
+  # Declare dependencies between jmod targets
+  $(foreach m, $(JMOD_MODULES), \
+      $(eval $m-jmod: $(addsuffix -jmod, $(call FindDepsForModule,$m))))
+
+  # Declare dependencies from <module>-jmod to all other module targets
+  $(foreach m, $(STRIP_MODULES), $(eval $m-jmod: $m-strip))
+  $(foreach m, $(JAVA_MODULES), $(eval $m-jmod: $m-java))
+  $(foreach m, $(GENDATA_MODULES), $(eval $m-jmod: $m-gendata))
+  $(foreach m, $(RMIC_MODULES), $(eval $m-jmod: $m-rmic))
+  $(foreach m, $(LIBS_MODULES), $(eval $m-jmod: $m-libs))
+  $(foreach m, $(LAUNCHER_MODULES), $(eval $m-jmod: $m-launchers))
+  $(foreach m, $(COPY_MODULES), $(eval $m-jmod: $m-copy))
+
+  # Jmods cannot be created until we have the jlink tool ready to run, which requires
+  # all java modules to be compiled and jdk.jlink-launchers.
+  $(JMOD_TARGETS): java java.base-libs jdk.jlink-launchers
+
+  ifeq ($(CREATE_BUILDJDK), true)
+    $(JMOD_TARGETS): create-buildjdk
+  endif
+
   zip-security: java.base-java java.security.jgss-java java.security.jgss-libs \
       $(filter jdk.crypto%, $(JAVA_TARGETS))
 
   zip-source: gensrc rmic
 
-  strip-binaries: libs launchers gendata copy
+  jrtfs-jar: interim-langtools
 
-  jrtfs-jar: buildtools-jdk
+  jimages: jmods zip-source source-tips demos samples jrtfs-jar
 
-  jimages: exploded-image zip-source strip-binaries source-tips demos samples \
-      jrtfs-jar
-
-  profiles: exploded-image strip-binaries source-tips
+  profiles: jmods zip-source source-tips jrtfs-jar
 
   mac-bundles-jdk: jimages
 
   bootcycle-images: jimages
 
-  docs-javadoc: gensrc rmic
+  docs-javadoc: $(GENSRC_TARGETS) rmic
 
   docs-jvmtidoc: hotspot
 
   test: jimages test-image
 
-  verify-modules: exploded-image
+  create-buildjdk-copy: jdk.jlink-java java.base-gendata
+
+  create-buildjdk-compile-modules: create-buildjdk-copy create-buildjdk-compile-hotspot
 
   test-make: clean-test-make
 
@@ -482,6 +595,8 @@
 
   install: product-images
 
+  generate-summary: jmods
+
 endif
 
 ################################################################################
@@ -494,7 +609,7 @@
 
 gendata: $(GENDATA_TARGETS)
 
-copy: $(COPY_TARGETS)
+copy: $(ALL_COPY_TARGETS)
 
 java: $(JAVA_TARGETS)
 
@@ -504,6 +619,10 @@
 
 launchers: $(LAUNCHER_TARGETS)
 
+jmods: $(JMOD_TARGETS)
+
+strip-binaries: $(STRIP_TARGETS)
+
 # Explicitly declare dependency for virtual target jdk.jdwp.agent-gensrc which
 # is actually handled by jdk.jdi-gensrc
 jdk.jdwp.agent-gensrc: jdk.jdi-gensrc
@@ -516,8 +635,7 @@
 $(foreach m, $(RMIC_MODULES), $(eval $m: $m-rmic))
 $(foreach m, $(LIBS_MODULES), $(eval $m: $m-libs))
 $(foreach m, $(LAUNCHER_MODULES), $(eval $m: $m-launchers))
-$(foreach m, $(COPY_MODULES), $(eval $m: $m-copy))
-
+$(foreach m, $(ALL_COPY_MODULES), $(eval $m: $m-copy))
 demos: demos-jdk
 
 samples: samples-jdk
@@ -525,6 +643,9 @@
 # The "exploded image" is a locally runnable JDK in $(BUILD_OUTPUT)/jdk.
 exploded-image: $(ALL_MODULES)
 
+create-buildjdk: create-buildjdk-compile-modules create-buildjdk-copy \
+    create-buildjdk-compile-hotspot
+
 mac-bundles: mac-bundles-jdk
 
 # The $(BUILD_OUTPUT)/images directory contain the resulting deliverables,
@@ -532,7 +653,13 @@
 
 # This target builds the product images, e.g. the JRE and JDK image
 # (and possibly other, more specific versions)
-product-images: jimages demos samples zip-security verify-modules
+product-images: jimages demos samples zip-security exploded-image
+
+# When cross compiling and building a partial BUILDJDK for the build host,
+# the summary generation cannot be run.
+ifneq ($(CREATE_BUILDJDK), true)
+  product-images: generate-summary
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
   product-images: mac-bundles
@@ -548,9 +675,9 @@
 # all-images is the top-most target, it builds all our deliverables ("images").
 all-images: product-images test-image docs-image
 
-ALL_TARGETS += buildtools gensrc gendata copy java rmic libs launchers \
+ALL_TARGETS += buildtools gensrc gendata copy java rmic libs launchers jmods \
     jdk.jdwp.agent-gensrc $(ALL_MODULES) demos samples exploded-image \
-    mac-bundles product-images docs-image test-image all-images
+    create-buildjdk mac-bundles product-images docs-image test-image all-images
 
 ################################################################################
 
@@ -575,7 +702,7 @@
 # file.
 
 CLEAN_DIRS += hotspot jdk bootcycle-build test buildtools support \
-    images make-support test-make bundles
+    images make-support test-make bundles buildjdk
 CLEAN_DIR_TARGETS := $(addprefix clean-, $(CLEAN_DIRS))
 CLEAN_SUPPORT_DIRS += demos
 CLEAN_SUPPORT_DIR_TARGETS := $(addprefix clean-, $(CLEAN_SUPPORT_DIRS))
diff --git a/make/MainSupport.gmk b/make/MainSupport.gmk
index be697f6..9d5865d 100644
--- a/make/MainSupport.gmk
+++ b/make/MainSupport.gmk
@@ -67,7 +67,6 @@
 	@$(PRINTF) "Cleaning gensrc $(if $1,for $(strip $1) )..."
 	@$(PRINTF) "\n" $(LOG_DEBUG)
 	$(RM) -r $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1)
-	$(RM) -r $(SUPPORT_OUTPUTDIR)/gensrc_no_docs/$(strip $1)
 	@$(PRINTF) " done\n"
 endef
 
diff --git a/make/StripBinaries.gmk b/make/StripBinaries.gmk
index 07669bf..26b3ee9 100644
--- a/make/StripBinaries.gmk
+++ b/make/StripBinaries.gmk
@@ -57,25 +57,29 @@
 NO_STRIP_CMDS_FILTER += %.cgi
 
 # Don't include debug info for executables.
+ifneq ($(wildcard $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)), )
+  # OS X stores symbol information in a .dylib file inside a .dSYM directory -
+  # that file should not be stripped, so we prune the tree at the .dSYM directory.
+  ALL_CMDS_SRC := $(filter-out %.bc %.debuginfo %.diz %.map %.pdb, \
+      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE) \( -type f -o -type l \) \
+      -print -o -name "*.dSYM" -prune))
+  COPY_CMDS_SRC := $(filter $(NO_STRIP_CMDS_FILTER), $(ALL_CMDS_SRC))
+  STRIP_CMDS_SRC := $(filter-out $(NO_STRIP_CMDS_FILTER), $(ALL_CMDS_SRC))
+endif
 
-# OS X stores symbol information in a .dylib file inside a .dSYM directory -
-# that file should not be stripped, so we prune the tree at the .dSYM directory.
-ALL_CMDS_SRC := $(filter-out %.bc %.debuginfo %.diz %.map %.pdb, \
-    $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_cmds \( -type f -o -type l \) \
-    -print -o -name "*.dSYM" -prune))
-COPY_CMDS_SRC := $(filter $(NO_STRIP_CMDS_FILTER), $(ALL_CMDS_SRC))
-STRIP_CMDS_SRC := $(filter-out $(NO_STRIP_CMDS_FILTER), $(ALL_CMDS_SRC))
-
-# OS X stores symbol information in a .dylib file inside a .dSYM directory -
-# that file should not be stripped, so we prune the tree at the .dSYM directory.
-# Example: support/modules_libs/java.base/libjsig.dylib.dSYM/Contents/Resources/DWARF/libjsig.dylib
-STRIP_LIBS_SRC := \
-    $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs \
+ifneq ($(wildcard $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)), )
+  # OS X stores symbol information in a .dylib file inside a .dSYM directory -
+  # that file should not be stripped, so we prune the tree at the .dSYM directory.
+  # Example: support/modules_libs/java.base/libjsig.dylib.dSYM/Contents/Resources/DWARF/libjsig.dylib
+  STRIP_LIBS_SRC := \
+      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE) \
         -name '*$(SHARED_LIBRARY_SUFFIX)' -type f -print -o -name "*.dSYM" -prune)
-# Make sure symbolic links are copied and not stripped.
-COPY_LIBS_SRC := \
-    $(filter-out $(STRIP_LIBS_SRC), \
-    $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs -type f -o -type l))
+
+  # Make sure symbolic links are copied and not stripped.
+  COPY_LIBS_SRC := \
+      $(filter-out $(STRIP_LIBS_SRC), \
+      $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE) -type f -o -type l))
+endif
 
 $(eval $(call SetupCopyFiles,STRIP_MODULES_CMDS, \
     SRC := $(SUPPORT_OUTPUTDIR)/modules_cmds, \
diff --git a/make/common/CORE_PKGS.gmk b/make/common/CORE_PKGS.gmk
index eb6ac3d..8500733 100644
--- a/make/common/CORE_PKGS.gmk
+++ b/make/common/CORE_PKGS.gmk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -99,6 +99,7 @@
     java.lang.instrument \
     java.lang.invoke \
     java.lang.management \
+    java.lang.module \
     java.lang.ref \
     java.lang.reflect \
     java.math \
diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk
index 29442c2..22e9d90 100644
--- a/make/common/JavaCompilation.gmk
+++ b/make/common/JavaCompilation.gmk
@@ -75,13 +75,13 @@
   ifneq ($$($1_COPY_$$($2_TARGET)), 1)
     $1_COPY_$$($2_TARGET) := 1
     # Now we can setup the dependency that will trigger the copying.
-    $$($1_BIN)$$($2_TARGET) : $2
+    $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET) : $2
 	$(MKDIR) -p $$(@D)
 	$(CP) $$< $$@
 	$(CHMOD) -f ug+w $$@
 
     # And do not forget this target
-    $1_ALL_COPY_TARGETS += $$($1_BIN)$$($2_TARGET)
+    $1_ALL_COPY_TARGETS += $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET)
   endif
 endef
 
@@ -133,7 +133,7 @@
 	$(CHMOD) -f ug+w $$@
 
     # And do not forget this target
-    $1_ALL_COPY_CLEAN_TARGETS += $$($1_BIN)$$($2_TARGET)
+    $1_ALL_COPY_CLEAN_TARGETS += $$($1_BIN)$$($1_MODULE_SUBDIR)$$($2_TARGET)
   endif
 endef
 
@@ -154,6 +154,7 @@
 #   SRC:=one or more directories to search for sources. The order of the source roots
 #        is significant. The first found file of a certain name has priority.
 #   BIN:=store classes here
+#   MODULE:=Name of module being compiled. If set, classes are put in BIN/MODULE.
 #   CLASSPATH:=a list of additional entries to set as classpath to javac
 #   INCLUDES:=myapp.foo means will only compile java files in myapp.foo or any of its sub-packages.
 #   EXCLUDES:=myapp.foo means will do not compile java files in myapp.foo or any of its sub-packages.
@@ -190,6 +191,10 @@
   $1_SJAVAC_PORTFILE := $$($$($1_SETUP)_SJAVAC_PORTFILE)
   $1_SERVER_JVM := $$($$($1_SETUP)_SERVER_JVM)
   $1_DISABLE_SJAVAC := $$($$($1_SETUP)_DISABLE_SJAVAC)
+ 
+  ifneq ($$($1_MODULE), )
+    $1_MODULE_SUBDIR := /$$($1_MODULE)
+  endif
 
   # Make sure the dirs exist.
   $$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupJavaCompilation $1 contains missing directory >$$d<)))
@@ -303,7 +308,7 @@
   $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst \
       $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
 
-  $1_COMPILE_TARGET := $$($1_BIN)/_the.$1_batch
+  $1_COMPILE_TARGET := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_batch
 
   ifeq ($$($1_DISABLE_SJAVAC)x$$(ENABLE_SJAVAC),xyes)
     # Using sjavac to compile.
@@ -336,7 +341,8 @@
     $1_VARDEPS := $$($1_JVM) $$($1_SJAVAC) $$($1_SJAVAC_ARGS_STRING) $$($1_FLAGS) \
         $$($1_HEADERS_ARG) $$($1_BIN) $$($1_EXCLUDES) $$($1_INCLUDES) \
         $$($1_EXCLUDE_FILES) $$($1_INCLUDE_FILES)
-    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+        $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.vardeps)
 
     $$($1_COMPILE_TARGET): $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
 	$$(call MakeDir, $$(@D) $$(dir $$($1_SJAVAC_PORTFILE)))
@@ -345,7 +351,7 @@
 	  $$(eval $$(call ListPathsSafely,$1_SJAVAC_ARGS_STRING, $$($1_SJAVAC_ARGS_FILE)))
         endif
 	$$(call LogWarn, Compiling $1)
-	$$(call ExecuteWithLog, $$($1_BIN)/_the.$$($1_SAFE_NAME)_batch, \
+	$$(call ExecuteWithLog, $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)_batch, \
 	    $$($1_JVM) $$($1_SJAVAC) \
 	        $$($1_REMOTE) \
 	        -j 1 \
@@ -353,7 +359,7 @@
 	        --permit-sources-without-package \
 	        --compare-found-sources $$@.tmp \
 	        --log=$(LOG_LEVEL) \
-	        --state-dir=$$($1_BIN) \
+	        --state-dir=$$($1_BIN)$$($1_MODULE_SUBDIR) \
 	        $$($1_SJAVAC_ARGS) \
 	        $$($1_FLAGS) \
 	        $$($1_HEADERS_ARG) \
@@ -362,11 +368,13 @@
         # Create a pubapi file that only changes when the pubapi changes. Dependent
         # compilations can use this file to only get recompiled when pubapi has changed.
         # Grep returns 1 if no matching lines are found. Do not fail for this.
-	$(GREP) -e "^I" $$($1_BIN)/javac_state > $$($1_BIN)/_the.$1_pubapi.tmp \
+	$(GREP) -e "^I" $$($1_BIN)$$($1_MODULE_SUBDIR)/javac_state > $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi.tmp \
 	    || test "$$$$?" = "1"
-	if [ ! -f $$($1_BIN)/_the.$1_pubapi ] \
-	    || [ "`$(DIFF) $$($1_BIN)/_the.$1_pubapi $$($1_BIN)/_the.$1_pubapi.tmp`" != "" ]; then \
-	  $(MV) $$($1_BIN)/_the.$1_pubapi.tmp $$($1_BIN)/_the.$1_pubapi; \
+	if [ ! -f $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi ] \
+	    || [ "`$(DIFF) $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi \
+	        $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi.tmp`" != "" ]; then \
+	  $(MV) $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi.tmp \
+	      $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1_pubapi; \
 	fi
 
   else
@@ -380,11 +388,12 @@
       $$($1_HEADERS)/_the.$1_headers: $$($1_COMPILE_TARGET)
 		$(MKDIR) -p $$(@D)
 		if [ -d "$$($1_HEADERS).$1.tmp" ]; then \
-		  for f in `ls $$($1_HEADERS).$1.tmp`; do \
+		  for f in `$(CD) $$($1_HEADERS).$1.tmp && $(FIND) . -type f`; do \
 		    if [ ! -f "$$($1_HEADERS)/$$$$f" ] \
 		        || [ "`$(DIFF) $$($1_HEADERS)/$$$$f $$($1_HEADERS).$1.tmp/$$$$f`" != "" ]; then \
-		    $(CP) -f $$($1_HEADERS).$1.tmp/$$$$f $$($1_HEADERS)/$$$$f; \
-		  fi; \
+		      $(MKDIR) -p `$(DIRNAME) $$($1_HEADERS)/$$$$f`; \
+		      $(CP) -f $$($1_HEADERS).$1.tmp/$$$$f $$($1_HEADERS)/$$$$f; \
+		    fi; \
 		  done; \
 		fi
 		$(RM) -r $$($1_HEADERS).$1.tmp
@@ -396,7 +405,8 @@
     $1_VARDEPS := $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) $$($1_BIN) \
         $$($1_HEADERS_ARG) $$($1_EXCLUDES) $$($1_INCLUDES) \
         $$($1_EXCLUDE_FILES) $$($1_INCLUDE_FILES)
-    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+    $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+        $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.vardeps)
 
     ifeq ($$($1_DISABLE_SJAVAC)x$(ENABLE_JAVAC_SERVER), xyes)
       $1_JAVAC_CMD := $$($1_SJAVAC) $$($1_REMOTE)
@@ -409,7 +419,7 @@
 	$$(call MakeDir, $$(@D))
 	$$(eval $$(call ListPathsSafely,$1_SRCS, $$@.tmp))
 	$$(call LogWarn, Compiling $$(words $$($1_SRCS)) files for $1)
-	$$(call ExecuteWithLog, $$($1_BIN)/_the.$$($1_SAFE_NAME)_batch, \
+	$$(call ExecuteWithLog, $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)_batch, \
 	    $$($1_JVM) $$($1_JAVAC_CMD) $$($1_FLAGS) \
 	        -implicit:none \
 		-d $$($1_BIN) $$($1_HEADERS_ARG) @$$@.tmp) && \
@@ -431,7 +441,7 @@
 
     $$(eval $$(call SetupJarArchive, ARCHIVE_$1, \
         DEPENDENCIES:=$$($1), \
-        SRCS:=$$($1_BIN), \
+        SRCS:=$$($1_BIN)$$($1_MODULE_SUBDIR), \
         SUFFIXES:=$$($1_SUFFIXES), \
         EXCLUDE:=$$($1_EXCLUDES), \
         INCLUDES:=$$($1_INCLUDES), \
diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk
index 6200851..7ed5213 100644
--- a/make/common/MakeBase.gmk
+++ b/make/common/MakeBase.gmk
@@ -247,7 +247,7 @@
             $(HG_SEARCH:%/REPO=%/$(HGTIP_FILENAME)) \
         2> /dev/null)))))
 
-# Emit the repo:tip pairs to $@
+# Emit the repo:tip pairs to $@, but only if they changed since last time
 define GetSourceTips
 	$(CD) $(SRC_ROOT) ; \
 	for i in $(REPO_LIST) IGNORE ; do \
@@ -260,8 +260,13 @@
 	    $(PRINTF) " %s:%s" \
 	        "$${i}" `$(CAT) $${i}/$(HGTIP_FILENAME)` ; \
 	  fi; \
-	done >> $@
-	$(PRINTF) "\n" >> $@
+	done > $@.tmp
+	$(PRINTF) "\n" >> $@.tmp
+	if [ ! -f $@ ] || [ "`$(CAT) $@`" != "`$(CAT) $@.tmp`" ]; then \
+	  $(MV) $@.tmp $@ ; \
+	else \
+	  $(RM) $@.tmp ; \
+	fi
 endef
 
 # Create the HGTIP_FILENAME file. Called from closed/make/SourceBundles.gmk
@@ -644,10 +649,10 @@
 
 # Defines the sub directory structure to store variable value file in
 DependOnVariableDirName = \
-    $(strip $(subst $(SRC_ROOT)/,,\
-        $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \
+    $(strip $(addsuffix $(if $(MODULE),/$(MODULE)), \
+        $(subst $(SRC_ROOT)/,, $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \
           $(firstword $(MAKEFILE_LIST)), \
-          $(CURDIR)/$(firstword $(MAKEFILE_LIST)))))
+          $(CURDIR)/$(firstword $(MAKEFILE_LIST))))))
 
 # Defines the name of the file to store variable value in. Generates a name
 # unless parameter 2 is given.
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
index 54f7a2b..b3478f2 100644
--- a/make/common/Modules.gmk
+++ b/make/common/Modules.gmk
@@ -26,6 +26,9 @@
 ifndef _MODULES_GMK
 _MODULES_GMK := 1
 
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, , common/Modules.gmk))
+
 ################################################################################
 # Some platforms don't have the serviceability agent
 ifeq ($(INCLUDE_SA), false)
@@ -35,7 +38,9 @@
 ################################################################################
 # Module list macros
 
-ALL_TOP_SRC_DIRS := \
+# Use append so that the custom extension may add to this variable
+
+ALL_TOP_SRC_DIRS += \
     $(HOTSPOT_TOPDIR)/src \
     $(JDK_TOPDIR)/src \
     $(LANGTOOLS_TOPDIR)/src \
@@ -45,37 +50,74 @@
     $(NASHORN_TOPDIR)/src \
     #
 
-# Find all modules with java sources by looking in the source dirs
-define FindJavaModules
-  $(filter-out $(MODULES_FILTER), $(sort $(notdir \
-      $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir \
-      $(wildcard $(patsubst %,%/*/share/classes/*, $(ALL_TOP_SRC_DIRS)) \
-          $(patsubst %,%/*/$(OPENJDK_TARGET_OS)/classes/*, $(ALL_TOP_SRC_DIRS)) \
-          $(patsubst %,%/*/$(OPENJDK_TARGET_OS_TYPE)/classes/*, $(ALL_TOP_SRC_DIRS))))))))))))
-endef
+# Find all module-info.java files for the current build target platform and
+# configuration.
+# Param 1 - Module to find for, set to * for finding all
+FindAllModuleInfos = \
+    $(wildcard \
+        $(patsubst %,%/$(strip $1)/$(OPENJDK_TARGET_OS)/classes/module-info.java, $(ALL_TOP_SRC_DIRS)) \
+        $(patsubst %,%/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/classes/module-info.java, $(ALL_TOP_SRC_DIRS)) \
+        $(patsubst %,%/$(strip $1)/share/classes/module-info.java, $(ALL_TOP_SRC_DIRS)) \
+        $(patsubst %,%/$(strip $1)/module-info.java, $(IMPORT_MODULES_SRC)))
 
-# Find all modules with source for the target platform.
-define FindAllModules
-  $(sort $(filter-out $(MODULES_FILTER) closed demo sample, \
-      $(notdir $(patsubst %/,%, $(dir \
-      $(wildcard $(patsubst %, %/*/share, $(ALL_TOP_SRC_DIRS)) \
-      $(patsubst %, %/*/$(OPENJDK_TARGET_OS), $(ALL_TOP_SRC_DIRS)) \
-      $(patsubst %, %/*/$(OPENJDK_TARGET_OS_TYPE), $(ALL_TOP_SRC_DIRS))))))))
-endef
+# Extract the module names from the paths of module-info.java files. The
+# position of the module directory differs depending on if this is an imported
+# src dir or not.
+GetModuleNameFromModuleInfo = \
+    $(strip $(foreach mi, $1, \
+      $(if $(filter $(addsuffix %, $(IMPORT_MODULES_SRC)), $(mi)), \
+        $(notdir $(patsubst %/,%, $(dir $(mi)))), \
+        $(notdir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(patsubst %/,%, $(dir $(mi)))))))))))
+
+# Find all modules by looking for module-info.java files and looking at parent
+# directories.
+FindAllModules = \
+    $(sort $(filter-out $(MODULES_FILTER), \
+    $(call GetModuleNameFromModuleInfo, $(MODULE_INFOS))))
+
+FindImportedModules = \
+    $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*)))
 
 ################################################################################
-# The module deps makefile is generated in make/GenerateModuleDeps.gmk
+# Extract module dependencies from module-info.java files.
+
 MODULE_DEPS_MAKEFILE := $(MAKESUPPORT_OUTPUTDIR)/module-deps.gmk
+
+MODULE_INFOS := $(call FindAllModuleInfos, *)
+
+$(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \
+    $(call DependOnVariable, MODULE_INFOS, $(MAKESUPPORT_OUTPUTDIR)/MODULE_INFOS.vardeps)
+	$(MKDIR) -p $(@D)
+	$(RM) $@
+	$(foreach m, $(MODULE_INFOS), \
+	    ( $(PRINTF) "DEPS_$(call GetModuleNameFromModuleInfo, $m) :=" && \
+	      $(NAWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\
+	          BEGIN      { if (MODULE != "java.base") printf(" java.base"); } \
+	          /requires/ { sub(/;/, ""); \
+	                       sub(/requires/, ""); \
+	                       sub(/public/, ""); \
+	                       sub(/\/\/.*/, ""); \
+	                       sub(/\/\*.*\*\//, ""); \
+	                       gsub(/ /, ""); \
+	                       printf(" %s", $$0) } \
+	          END        { printf("\n") }' $m \
+	    ) >> $@ $(NEWLINE))
+
 -include $(MODULE_DEPS_MAKEFILE)
 
 # Param 1: Module to find deps for
-define FindDepsForModule
+FindDepsForModule = \
   $(DEPS_$(strip $1))
-endef
+
+# Finds transitive dependencies in 3 levels.
+# Param 1: Module to find transitive deps for
+FindTransitiveDepsForModule = \
+    $(sort $(call FindDepsForModule, $1) \
+        $(foreach m, $(call FindDepsForModule, $1), \
+            $(call FindDepsForModule, $m) \
+            $(foreach n, $(call FindDepsForModule, $m), \
+                 $(call FindDepsForModule, $n))))
 
 ################################################################################
 
-# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, , common/Modules.gmk))
-
 endif # _MODULES_GMK
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index f675790..2ddd376 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -74,6 +74,7 @@
 #   AS - Assembler
 #   MT - Windows MT tool
 #   RC - Windows RC tool
+#   OBJCOPY - The objcopy tool for debug symbol handling
 #   STRIP - The tool to use for stripping debug symbols
 #   SYSROOT_CFLAGS - Compiler flags for using the specific sysroot
 #   SYSROOT_LDFLAGS - Linker flags for using the specific sysroot
@@ -90,6 +91,7 @@
     $$(call SetIfEmpty, $1_AS, $$($$($1_EXTENDS)_AS))
     $$(call SetIfEmpty, $1_MT, $$($$($1_EXTENDS)_MT))
     $$(call SetIfEmpty, $1_RC, $$($$($1_EXTENDS)_RC))
+    $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_EXTENDS)_OBJCOPY))
     $$(call SetIfEmpty, $1_STRIP, $$($$($1_EXTENDS)_STRIP))
     $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_EXTENDS)_SYSROOT_CFLAGS))
     $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_EXTENDS)_SYSROOT_LDFLAGS))
@@ -105,6 +107,7 @@
     AS := $(AS), \
     MT := $(MT), \
     RC := $(RC), \
+    OBJCOPY := $(OBJCOPY), \
     STRIP := $(STRIP), \
     SYSROOT_CFLAGS := $(SYSROOT_CFLAGS), \
     SYSROOT_LDFLAGS := $(SYSROOT_LDFLAGS), \
@@ -118,13 +121,14 @@
 
 # Create a toolchain with the BUILD compiler, used for build tools that
 # are to be run during the build.
-# The BUILD_SYSROOT_*FLAGS variables are empty for now.
 $(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD, \
     CC := $(BUILD_CC), \
     CXX := $(BUILD_CXX), \
     LD := $(BUILD_LD), \
     AR := $(BUILD_AR), \
     AS := $(BUILD_AS), \
+    OBJCOPY := $(BUILD_OBJCOPY), \
+    STRIP := $(BUILD_STRIP), \
     SYSROOT_CFLAGS := $(BUILD_SYSROOT_CFLAGS), \
     SYSROOT_LDFLAGS := $(BUILD_SYSROOT_LDFLAGS), \
 ))
@@ -437,6 +441,7 @@
   $$(call SetIfEmpty, $1_AS, $$($$($1_TOOLCHAIN)_AS))
   $$(call SetIfEmpty, $1_MT, $$($$($1_TOOLCHAIN)_MT))
   $$(call SetIfEmpty, $1_RC, $$($$($1_TOOLCHAIN)_RC))
+  $$(call SetIfEmpty, $1_OBJCOPY, $$($$($1_TOOLCHAIN)_OBJCOPY))
   $$(call SetIfEmpty, $1_STRIP, $$($$($1_TOOLCHAIN)_STRIP))
   $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_CFLAGS))
   $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_LDFLAGS))
@@ -720,9 +725,9 @@
           # Setup the command line creating debuginfo files, to be run after linking.
           # It cannot be run separately since it updates the original target file
           $1_CREATE_DEBUGINFO_CMDS := \
-              $(OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) \
-              $(CD) $$($1_OUTPUT_DIR) && \
-                  $(OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
+            $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) \
+            $(CD) $$($1_OUTPUT_DIR) && \
+                $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
 
         else ifeq ($(OPENJDK_TARGET_OS), macosx)
           $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_BASENAME).dSYM
diff --git a/make/common/SetupJavaCompilers.gmk b/make/common/SetupJavaCompilers.gmk
index a381d1c..8100cdb 100644
--- a/make/common/SetupJavaCompilers.gmk
+++ b/make/common/SetupJavaCompilers.gmk
@@ -38,7 +38,8 @@
 # and the interim javac, to be run by the boot jdk.
 $(eval $(call SetupJavaCompiler,BOOT_JAVAC, \
     JAVAC := $(JAVAC), \
-    FLAGS := -XDignore.symbol.file=true -g -Xlint:all$(COMMA)-deprecation -Werror, \
+    FLAGS := $(BOOT_JDK_SOURCETARGET) -XDignore.symbol.file=true -g \
+        -Xlint:all$(COMMA)-deprecation$(COMMA)-options -Werror, \
     DISABLE_SJAVAC := true, \
 ))
 
@@ -80,9 +81,6 @@
     SERVER_DIR := $(SJAVAC_SERVER_DIR), \
     SERVER_JVM := $(SJAVAC_SERVER_JAVA)))
 
-JDK_BOOTCLASSPATH := $(call PathList, \
-    $(filter-out $(JDK_OUTPUTDIR)/modules/_%, $(wildcard $(JDK_OUTPUTDIR)/modules/*)))
-
 # After the jdk is built, we want to build demos using only the recently
 # generated jdk classes and nothing else, no jdk source, etc etc.
 # I.e. the rt.jar, but since rt.jar has not yet been generated
@@ -90,7 +88,7 @@
 $(eval $(call SetupJavaCompiler,GENERATE_USINGJDKBYTECODE, \
     JVM := $(JAVA_SMALL), \
     JAVAC := $(NEW_JAVAC), \
-    FLAGS := -bootclasspath $(JDK_BOOTCLASSPATH) $(DISABLE_WARNINGS), \
+    FLAGS := -upgrademodulepath $(JDK_OUTPUTDIR)/modules -system none $(DISABLE_WARNINGS), \
     SERVER_DIR := $(SJAVAC_SERVER_DIR), \
     SERVER_JVM := $(SJAVAC_SERVER_JAVA)))
 
diff --git a/modules.xml b/modules.xml
deleted file mode 100644
index 7061f523..0000000
--- a/modules.xml
+++ /dev/null
@@ -1,2139 +0,0 @@
-<?xml version="1.0" encoding="us-ascii"?>
-
-<!--
-
-   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
-   under the terms of the GNU General Public License version 2 only, as
-   published by the Free Software Foundation.  Oracle designates this
-   particular file as subject to the "Classpath" exception as provided
-   by Oracle in the LICENSE file that accompanied this code.
-
-   This code is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-   version 2 for more details (a copy is included in the LICENSE file that
-   accompanied this code).
-
-   You should have received a copy of the GNU General Public License version
-   2 along with this work; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-   or visit www.oracle.com if you need additional information or have any
-   questions.
-
-  -->
-
-<!--
-
-   This document defines the modular structure of the JDK as described
-   in JEP 200: The Modular JDK (http://openjdk.java.net/jeps/200).
-
-   Changes to this file must be reviewed by a Project Jigsaw Committer
-   (http://openjdk.java.net/census#jigsaw).
-
-  -->
-
-<modules>
-  <module>
-    <name>java.activation</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.datatransfer</depend>
-    <depend>java.desktop</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>javax.activation</name>
-    </export>
-  </module>
-  <module>
-    <name>java.annotations.common</name>
-    <depend>java.base</depend>
-    <export>
-      <name>javax.annotation</name>
-    </export>
-  </module>
-  <module>
-    <name>java.base</name>
-    <export>
-      <name>java.io</name>
-    </export>
-    <export>
-      <name>java.lang</name>
-    </export>
-    <export>
-      <name>java.lang.annotation</name>
-    </export>
-    <export>
-      <name>java.lang.invoke</name>
-    </export>
-    <export>
-      <name>java.lang.ref</name>
-    </export>
-    <export>
-      <name>java.lang.reflect</name>
-    </export>
-    <export>
-      <name>java.math</name>
-    </export>
-    <export>
-      <name>java.net</name>
-    </export>
-    <export>
-      <name>java.nio</name>
-    </export>
-    <export>
-      <name>java.nio.channels</name>
-    </export>
-    <export>
-      <name>java.nio.channels.spi</name>
-    </export>
-    <export>
-      <name>java.nio.charset</name>
-    </export>
-    <export>
-      <name>java.nio.charset.spi</name>
-    </export>
-    <export>
-      <name>java.nio.file</name>
-    </export>
-    <export>
-      <name>java.nio.file.attribute</name>
-    </export>
-    <export>
-      <name>java.nio.file.spi</name>
-    </export>
-    <export>
-      <name>java.security</name>
-    </export>
-    <export>
-      <name>java.security.acl</name>
-    </export>
-    <export>
-      <name>java.security.cert</name>
-    </export>
-    <export>
-      <name>java.security.interfaces</name>
-    </export>
-    <export>
-      <name>java.security.spec</name>
-    </export>
-    <export>
-      <name>java.text</name>
-    </export>
-    <export>
-      <name>java.text.spi</name>
-    </export>
-    <export>
-      <name>java.time</name>
-    </export>
-    <export>
-      <name>java.time.chrono</name>
-    </export>
-    <export>
-      <name>java.time.format</name>
-    </export>
-    <export>
-      <name>java.time.temporal</name>
-    </export>
-    <export>
-      <name>java.time.zone</name>
-    </export>
-    <export>
-      <name>java.util</name>
-    </export>
-    <export>
-      <name>java.util.concurrent</name>
-    </export>
-    <export>
-      <name>java.util.concurrent.atomic</name>
-    </export>
-    <export>
-      <name>java.util.concurrent.locks</name>
-    </export>
-    <export>
-      <name>java.util.function</name>
-    </export>
-    <export>
-      <name>java.util.jar</name>
-    </export>
-    <export>
-      <name>java.util.regex</name>
-    </export>
-    <export>
-      <name>java.util.spi</name>
-    </export>
-    <export>
-      <name>java.util.stream</name>
-    </export>
-    <export>
-      <name>java.util.zip</name>
-    </export>
-    <export>
-      <name>javax.crypto</name>
-    </export>
-    <export>
-      <name>javax.crypto.interfaces</name>
-    </export>
-    <export>
-      <name>javax.crypto.spec</name>
-    </export>
-    <export>
-      <name>javax.net</name>
-    </export>
-    <export>
-      <name>javax.net.ssl</name>
-    </export>
-    <export>
-      <name>javax.security.auth</name>
-    </export>
-    <export>
-      <name>javax.security.auth.callback</name>
-    </export>
-    <export>
-      <name>javax.security.auth.login</name>
-    </export>
-    <export>
-      <name>javax.security.auth.spi</name>
-    </export>
-    <export>
-      <name>javax.security.auth.x500</name>
-    </export>
-    <export>
-      <name>javax.security.cert</name>
-    </export>
-    <export>
-      <name>jdk</name>
-    </export>
-    <export>
-      <name>jdk.net</name>
-    </export>
-    <export>
-      <name>com.sun.security.ntlm</name>
-      <to>java.security.sasl</to>
-    </export>
-    <export>
-      <name>jdk.internal.jimage</name>
-      <to>jdk.dev</to>
-    </export>
-    <export>
-      <name>jdk.internal.jimage.decompressor</name>
-      <to>jdk.dev</to>
-    </export>
-    <export>
-      <name>jdk.internal.math</name>
-      <to>java.desktop</to>
-    </export>
-    <export>
-      <name>jdk.internal.misc</name>
-      <to>java.corba</to>
-      <to>java.desktop</to>
-      <to>java.logging</to>
-      <to>java.management</to>
-      <to>java.naming</to>
-      <to>java.rmi</to>
-      <to>java.security.jgss</to>
-      <to>java.sql</to>
-      <to>java.xml</to>
-      <to>jdk.charsets</to>
-      <to>jdk.management.resource</to>
-      <to>jdk.jfr</to>
-      <to>jdk.net</to>
-      <to>jdk.scripting.nashorn</to>
-      <to>jdk.vm.ci</to>
-    </export>
-    <export>
-      <name>jdk.internal.perf</name>
-      <to>java.desktop</to>
-      <to>java.management</to>
-      <to>jdk.jvmstat</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.xml.sax</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.xml.sax.helpers</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.internal.util.xml</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.internal.util.xml.impl</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.objectweb.asm</name>
-      <to>java.instrument</to>
-      <to>jdk.jfr</to>
-      <to>jdk.scripting.nashorn</to>
-      <to>jdk.vm.ci</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.objectweb.asm.commons</name>
-      <to>java.instrument</to>
-      <to>jdk.jfr</to>
-      <to>jdk.scripting.nashorn</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.objectweb.asm.signature</name>
-      <to>jdk.scripting.nashorn</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.objectweb.asm.tree</name>
-      <to>java.instrument</to>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.internal.org.objectweb.asm.util</name>
-      <to>java.instrument</to>
-      <to>jdk.jfr</to>
-      <to>jdk.scripting.nashorn</to>
-    </export>
-    <export>
-      <name>jdk.internal.ref</name>
-      <to>java.desktop</to>
-    </export>
-    <export>
-      <name>jdk.internal</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>sun.misc</name>
-      <to>java.corba</to>
-      <to>java.desktop</to>
-      <to>java.instrument</to>
-      <to>java.logging</to>
-      <to>java.management</to>
-      <to>java.naming</to>
-      <to>java.prefs</to>
-      <to>java.rmi</to>
-      <to>java.security.jgss</to>
-      <to>java.security.sasl</to>
-      <to>java.xml</to>
-      <to>jdk.charsets</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.httpserver</to>
-      <to>jdk.jartool</to>
-      <to>jdk.jconsole</to>
-      <to>jdk.jvmstat</to>
-      <to>jdk.management.resource</to>
-      <to>jdk.pack200</to>
-      <to>jdk.scripting.nashorn</to>
-      <to>jdk.security.auth</to>
-      <to>jdk.security.jgss</to>
-      <to>jdk.snmp</to>
-      <to>jdk.vm.ci</to>
-      <to>jdk.zipfs</to>
-      <to>java.instrument</to>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>sun.net</name>
-      <to>java.httpclient</to>
-    </export>
-    <export>
-      <name>sun.net.dns</name>
-      <to>java.security.jgss</to>
-      <to>jdk.naming.dns</to>
-    </export>
-    <export>
-      <name>sun.net.sdp</name>
-      <to>jdk.net</to>
-    </export>
-    <export>
-      <name>sun.net.spi.nameservice</name>
-      <to>jdk.naming.dns</to>
-    </export>
-    <export>
-      <name>sun.net.util</name>
-      <to>java.desktop</to>
-      <to>jdk.jconsole</to>
-      <to>jdk.naming.dns</to>
-    </export>
-    <export>
-      <name>sun.net.www</name>
-      <to>java.desktop</to>
-      <to>jdk.compiler</to>
-      <to>jdk.jartool</to>
-    </export>
-    <export>
-      <name>sun.net.www.protocol.http</name>
-      <to>java.security.jgss</to>
-    </export>
-    <export>
-      <name>sun.nio.ch</name>
-      <to>java.management</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.crypto.ucrypto</to>
-      <to>jdk.management.resource</to>
-      <to>jdk.net</to>
-      <to>jdk.sctp</to>
-    </export>
-    <export>
-      <name>sun.nio.cs</name>
-      <to>java.desktop</to>
-      <to>jdk.charsets</to>
-    </export>
-    <export>
-      <name>sun.reflect</name>
-      <to>java.corba</to>
-      <to>java.instrument</to>
-      <to>java.logging</to>
-      <to>java.sql</to>
-      <to>java.sql.rowset</to>
-      <to>jdk.dynalink</to>
-      <to>jdk.scripting.nashorn</to>
-      <to>jdk.vm.cds</to>
-    </export>
-    <export>
-      <name>sun.reflect.annotation</name>
-      <to>jdk.compiler</to>
-    </export>
-    <export>
-      <name>sun.reflect.generics.reflectiveObjects</name>
-      <to>java.desktop</to>
-    </export>
-    <export>
-      <name>sun.reflect.misc</name>
-      <to>java.corba</to>
-      <to>java.datatransfer</to>
-      <to>java.desktop</to>
-      <to>java.management</to>
-      <to>java.rmi</to>
-      <to>java.sql.rowset</to>
-      <to>java.xml</to>
-    </export>
-    <export>
-      <name>sun.security.action</name>
-      <to>java.desktop</to>
-      <to>java.security.jgss</to>
-      <to>jdk.crypto.ec</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.crypto.ucrypto</to>
-    </export>
-    <export>
-      <name>sun.security.internal.interfaces</name>
-      <to>jdk.crypto.pkcs11</to>
-    </export>
-    <export>
-      <name>sun.security.internal.spec</name>
-      <to>jdk.crypto.mscapi</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.crypto.ucrypto</to>
-    </export>
-    <export>
-      <name>sun.security.jca</name>
-      <to>java.smartcardio</to>
-      <to>java.xml.crypto</to>
-      <to>jdk.crypto.ec</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.crypto.ucrypto</to>
-      <to>jdk.naming.dns</to>
-    </export>
-    <export>
-      <name>sun.security.pkcs</name>
-      <to>jdk.crypto.ec</to>
-      <to>jdk.jartool</to>
-    </export>
-    <export>
-      <name>sun.security.provider</name>
-      <to>java.rmi</to>
-      <to>java.security.jgss</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.jartool</to>
-      <to>jdk.policytool</to>
-      <to>jdk.security.auth</to>
-    </export>
-    <export>
-      <name>sun.security.provider.certpath</name>
-      <to>java.naming</to>
-    </export>
-    <export>
-      <name>sun.security.rsa</name>
-      <to>jdk.crypto.mscapi</to>
-      <to>jdk.crypto.pkcs11</to>
-    </export>
-    <export>
-      <name>sun.security.ssl</name>
-      <to>java.security.jgss</to>
-    </export>
-    <export>
-      <name>sun.security.tools</name>
-      <to>jdk.jartool</to>
-    </export>
-    <export>
-      <name>sun.security.util</name>
-      <to>java.desktop</to>
-      <to>java.naming</to>
-      <to>java.rmi</to>
-      <to>java.security.jgss</to>
-      <to>java.security.sasl</to>
-      <to>java.smartcardio</to>
-      <to>jdk.crypto.ec</to>
-      <to>jdk.crypto.mscapi</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.crypto.ucrypto</to>
-      <to>jdk.jartool</to>
-      <to>jdk.policytool</to>
-      <to>jdk.security.auth</to>
-      <to>jdk.security.jgss</to>
-    </export>
-    <export>
-      <name>sun.security.x509</name>
-      <to>java.naming</to>
-      <to>jdk.crypto.ec</to>
-      <to>jdk.crypto.pkcs11</to>
-      <to>jdk.jartool</to>
-      <to>jdk.security.auth</to>
-    </export>
-    <export>
-      <name>sun.text</name>
-      <to>java.desktop</to>
-    </export>
-    <export>
-      <name>sun.util</name>
-      <to>java.desktop</to>
-    </export>
-    <export>
-      <name>sun.util.locale.provider</name>
-      <to>java.desktop</to>
-      <to>jdk.localedata</to>
-    </export>
-    <export>
-      <name>jdk.internal.logger</name>
-      <to>java.logging</to>
-    </export>
-    <export>
-      <name>sun.util.logging</name>
-      <to>java.desktop</to>
-      <to>java.logging</to>
-      <to>java.management</to>
-      <to>java.prefs</to>
-      <to>java.httpclient</to>
-    </export>
-    <export>
-      <name>sun.util.resources</name>
-      <to>jdk.localedata</to>
-    </export>
-  </module>
-  <module>
-    <name>java.compact1</name>
-    <depend re-exports="true">java.base</depend>
-    <depend re-exports="true">java.logging</depend>
-    <depend re-exports="true">java.scripting</depend>
-  </module>
-  <module>
-    <name>java.compact2</name>
-    <depend re-exports="true">java.compact1</depend>
-    <depend re-exports="true">java.rmi</depend>
-    <depend re-exports="true">java.sql</depend>
-    <depend re-exports="true">java.xml</depend>
-  </module>
-  <module>
-    <name>java.compact3</name>
-    <depend re-exports="true">java.compact2</depend>
-    <depend re-exports="true">java.compiler</depend>
-    <depend re-exports="true">java.instrument</depend>
-    <depend re-exports="true">java.httpclient</depend>
-    <depend re-exports="true">java.management</depend>
-    <depend re-exports="true">java.naming</depend>
-    <depend re-exports="true">java.prefs</depend>
-    <depend re-exports="true">java.security.jgss</depend>
-    <depend re-exports="true">java.security.sasl</depend>
-    <depend re-exports="true">java.sql.rowset</depend>
-    <depend re-exports="true">java.xml.crypto</depend>
-  </module>
-  <module>
-    <name>java.compiler</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>javax.annotation.processing</name>
-    </export>
-    <export>
-      <name>javax.lang.model</name>
-    </export>
-    <export>
-      <name>javax.lang.model.element</name>
-    </export>
-    <export>
-      <name>javax.lang.model.type</name>
-    </export>
-    <export>
-      <name>javax.lang.model.util</name>
-    </export>
-    <export>
-      <name>javax.tools</name>
-    </export>
-  </module>
-  <module>
-    <name>java.corba</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend>java.naming</depend>
-    <depend re-exports="true">java.rmi</depend>
-    <depend>java.transaction</depend>
-    <export>
-      <name>javax.activity</name>
-    </export>
-    <export>
-      <name>javax.rmi</name>
-    </export>
-    <export>
-      <name>javax.rmi.CORBA</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA.DynAnyPackage</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA.ORBPackage</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA.TypeCodePackage</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA.portable</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA_2_3</name>
-    </export>
-    <export>
-      <name>org.omg.CORBA_2_3.portable</name>
-    </export>
-    <export>
-      <name>org.omg.CosNaming</name>
-    </export>
-    <export>
-      <name>org.omg.CosNaming.NamingContextExtPackage</name>
-    </export>
-    <export>
-      <name>org.omg.CosNaming.NamingContextPackage</name>
-    </export>
-    <export>
-      <name>org.omg.Dynamic</name>
-    </export>
-    <export>
-      <name>org.omg.DynamicAny</name>
-    </export>
-    <export>
-      <name>org.omg.DynamicAny.DynAnyFactoryPackage</name>
-    </export>
-    <export>
-      <name>org.omg.DynamicAny.DynAnyPackage</name>
-    </export>
-    <export>
-      <name>org.omg.IOP</name>
-    </export>
-    <export>
-      <name>org.omg.IOP.CodecFactoryPackage</name>
-    </export>
-    <export>
-      <name>org.omg.IOP.CodecPackage</name>
-    </export>
-    <export>
-      <name>org.omg.Messaging</name>
-    </export>
-    <export>
-      <name>org.omg.PortableInterceptor</name>
-    </export>
-    <export>
-      <name>org.omg.PortableInterceptor.ORBInitInfoPackage</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer.CurrentPackage</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer.POAManagerPackage</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer.POAPackage</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer.ServantLocatorPackage</name>
-    </export>
-    <export>
-      <name>org.omg.PortableServer.portable</name>
-    </export>
-    <export>
-      <name>org.omg.SendingContext</name>
-    </export>
-    <export>
-      <name>org.omg.stub.java.rmi</name>
-    </export>
-    <export>
-      <name>com.sun.corba.se.impl.util</name>
-      <to>jdk.rmic</to>
-    </export>
-  </module>
-  <module>
-    <name>java.datatransfer</name>
-    <depend>java.base</depend>
-    <export>
-      <name>java.awt.datatransfer</name>
-    </export>
-    <export>
-      <name>sun.datatransfer</name>
-      <to>java.desktop</to>
-    </export>
-  </module>
-  <module>
-    <name>java.desktop</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <depend>java.prefs</depend>
-    <depend re-exports="true">java.xml</depend>
-    <depend re-exports="true">java.datatransfer</depend>
-    <export>
-      <name>java.applet</name>
-    </export>
-    <export>
-      <name>java.awt</name>
-    </export>
-    <export>
-      <name>java.awt.color</name>
-    </export>
-    <export>
-      <name>java.awt.dnd</name>
-    </export>
-    <export>
-      <name>java.awt.event</name>
-    </export>
-    <export>
-      <name>java.awt.font</name>
-    </export>
-    <export>
-      <name>java.awt.geom</name>
-    </export>
-    <export>
-      <name>java.awt.im</name>
-    </export>
-    <export>
-      <name>java.awt.im.spi</name>
-    </export>
-    <export>
-      <name>java.awt.image</name>
-    </export>
-    <export>
-      <name>java.awt.image.renderable</name>
-    </export>
-    <export>
-      <name>java.awt.print</name>
-    </export>
-    <export>
-      <name>java.beans</name>
-    </export>
-    <export>
-      <name>java.beans.beancontext</name>
-    </export>
-    <export>
-      <name>javax.accessibility</name>
-    </export>
-    <export>
-      <name>javax.imageio</name>
-    </export>
-    <export>
-      <name>javax.imageio.event</name>
-    </export>
-    <export>
-      <name>javax.imageio.metadata</name>
-    </export>
-    <export>
-      <name>javax.imageio.plugins.bmp</name>
-    </export>
-    <export>
-      <name>javax.imageio.plugins.jpeg</name>
-    </export>
-    <export>
-      <name>javax.imageio.spi</name>
-    </export>
-    <export>
-      <name>javax.imageio.stream</name>
-    </export>
-    <export>
-      <name>javax.print</name>
-    </export>
-    <export>
-      <name>javax.print.attribute</name>
-    </export>
-    <export>
-      <name>javax.print.attribute.standard</name>
-    </export>
-    <export>
-      <name>javax.print.event</name>
-    </export>
-    <export>
-      <name>javax.sound.midi</name>
-    </export>
-    <export>
-      <name>javax.sound.midi.spi</name>
-    </export>
-    <export>
-      <name>javax.sound.sampled</name>
-    </export>
-    <export>
-      <name>javax.sound.sampled.spi</name>
-    </export>
-    <export>
-      <name>javax.swing</name>
-    </export>
-    <export>
-      <name>javax.swing.border</name>
-    </export>
-    <export>
-      <name>javax.swing.colorchooser</name>
-    </export>
-    <export>
-      <name>javax.swing.event</name>
-    </export>
-    <export>
-      <name>javax.swing.filechooser</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf.basic</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf.metal</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf.multi</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf.nimbus</name>
-    </export>
-    <export>
-      <name>javax.swing.plaf.synth</name>
-    </export>
-    <export>
-      <name>javax.swing.table</name>
-    </export>
-    <export>
-      <name>javax.swing.text</name>
-    </export>
-    <export>
-      <name>javax.swing.text.html</name>
-    </export>
-    <export>
-      <name>javax.swing.text.html.parser</name>
-    </export>
-    <export>
-      <name>javax.swing.text.rtf</name>
-    </export>
-    <export>
-      <name>javax.swing.tree</name>
-    </export>
-    <export>
-      <name>javax.swing.undo</name>
-    </export>
-    <export>
-      <name>sun.awt</name>
-      <to>jdk.accessibility</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jshell</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.compiler</depend>
-    <depend>jdk.compiler</depend>
-    <depend>java.desktop</depend>
-    <depend>java.prefs</depend>
-    <depend>jdk.jdi</depend>
-    <depend>jdk.internal.le</depend>
-    <export>
-      <name>jdk.jshell</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jsobject</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.desktop</depend>
-    <export>
-      <name>netscape.javascript</name>
-    </export>
-    <export>
-      <name>jdk.internal.netscape.javascript.spi</name>
-      <to>jdk.plugin</to>
-    </export>
-  </module>
-  <module>
-    <name>java.httpclient</name>
-    <depend>java.base</depend>
-    <export>
-      <name>java.net.http</name>
-    </export>
-  </module>
-  <module>
-    <name>java.instrument</name>
-    <depend>java.base</depend>
-    <export>
-      <name>java.lang.instrument</name>
-    </export>
-    <export>
-      <name>jdk.internal.instrumentation</name>
-      <to>jdk.jfr</to>
-      <to>jdk.management.resource</to>
-    </export>
-  </module>
-  <module>
-    <name>java.logging</name>
-    <depend>java.base</depend>
-    <export>
-      <name>java.util.logging</name>
-    </export>
-  </module>
-  <module>
-    <name>java.management</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <depend>java.naming</depend>
-    <depend re-exports="true">java.rmi</depend>
-    <export>
-      <name>java.lang.management</name>
-    </export>
-    <export>
-      <name>javax.management</name>
-    </export>
-    <export>
-      <name>javax.management.loading</name>
-    </export>
-    <export>
-      <name>javax.management.modelmbean</name>
-    </export>
-    <export>
-      <name>javax.management.monitor</name>
-    </export>
-    <export>
-      <name>javax.management.openmbean</name>
-    </export>
-    <export>
-      <name>javax.management.relation</name>
-    </export>
-    <export>
-      <name>javax.management.remote</name>
-    </export>
-    <export>
-      <name>javax.management.remote.rmi</name>
-    </export>
-    <export>
-      <name>javax.management.timer</name>
-    </export>
-    <export>
-      <name>sun.management</name>
-      <to>jdk.jconsole</to>
-      <to>jdk.management</to>
-    </export>
-    <export>
-      <name>sun.management.spi</name>
-      <to>jdk.management</to>
-      <to>jdk.management.cmm</to>
-      <to>jdk.management.jfr</to>
-    </export>
-  </module>
-  <module>
-    <name>java.naming</name>
-    <depend>java.base</depend>
-    <depend>java.security.sasl</depend>
-    <export>
-      <name>javax.naming</name>
-    </export>
-    <export>
-      <name>javax.naming.directory</name>
-    </export>
-    <export>
-      <name>javax.naming.event</name>
-    </export>
-    <export>
-      <name>javax.naming.ldap</name>
-    </export>
-    <export>
-      <name>javax.naming.spi</name>
-    </export>
-    <export>
-      <name>com.sun.jndi.toolkit.ctx</name>
-      <to>jdk.naming.dns</to>
-    </export>
-    <export>
-      <name>com.sun.jndi.toolkit.url</name>
-      <to>java.corba</to>
-      <to>jdk.naming.dns</to>
-      <to>jdk.naming.rmi</to>
-    </export>
-  </module>
-  <module>
-    <name>java.prefs</name>
-    <depend>java.base</depend>
-    <depend>java.xml</depend>
-    <export>
-      <name>java.util.prefs</name>
-    </export>
-  </module>
-  <module>
-    <name>java.rmi</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>java.rmi</name>
-    </export>
-    <export>
-      <name>java.rmi.activation</name>
-    </export>
-    <export>
-      <name>java.rmi.dgc</name>
-    </export>
-    <export>
-      <name>java.rmi.registry</name>
-    </export>
-    <export>
-      <name>java.rmi.server</name>
-    </export>
-    <export>
-      <name>javax.rmi.ssl</name>
-    </export>
-    <export>
-      <name>sun.rmi.registry</name>
-      <to>java.management</to>
-    </export>
-    <export>
-      <name>sun.rmi.server</name>
-      <to>java.management</to>
-      <to>jdk.jconsole</to>
-    </export>
-    <export>
-      <name>sun.rmi.transport</name>
-      <to>java.management</to>
-      <to>jdk.jconsole</to>
-    </export>
-  </module>
-  <module>
-    <name>java.scripting</name>
-    <depend>java.base</depend>
-    <export>
-      <name>javax.script</name>
-    </export>
-  </module>
-  <module>
-    <name>java.se</name>
-    <depend re-exports="true">java.activation</depend>
-    <depend re-exports="true">java.compact3</depend>
-    <depend re-exports="true">java.corba</depend>
-    <depend re-exports="true">java.datatransfer</depend>
-    <depend re-exports="true">java.desktop</depend>
-    <depend re-exports="true">java.transaction</depend>
-    <depend re-exports="true">java.xml.bind</depend>
-    <depend re-exports="true">java.xml.ws</depend>
-  </module>
-  <module>
-    <name>java.security.jgss</name>
-    <depend>java.base</depend>
-    <depend>java.naming</depend>
-    <export>
-      <name>javax.security.auth.kerberos</name>
-    </export>
-    <export>
-      <name>org.ietf.jgss</name>
-    </export>
-    <export>
-      <name>sun.security.jgss.krb5</name>
-      <to>jdk.security.auth</to>
-    </export>
-    <export>
-      <name>sun.security.krb5</name>
-      <to>jdk.security.auth</to>
-    </export>
-    <export>
-      <name>sun.security.krb5.internal.ktab</name>
-      <to>jdk.security.auth</to>
-    </export>
-    <export>
-      <name>sun.security.jgss</name>
-      <to>jdk.security.jgss</to>
-    </export>
-    <export>
-      <name>sun.security.krb5.internal</name>
-      <to>jdk.security.jgss</to>
-    </export>
-  </module>
-  <module>
-    <name>java.security.sasl</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>javax.security.sasl</name>
-    </export>
-    <export>
-      <name>com.sun.security.sasl.util</name>
-      <to>jdk.security.jgss</to>
-    </export>
-  </module>
-  <module>
-    <name>java.smartcardio</name>
-    <depend>java.base</depend>
-    <export>
-      <name>javax.smartcardio</name>
-    </export>
-  </module>
-  <module>
-    <name>java.sql</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.logging</depend>
-    <depend re-exports="true">java.xml</depend>
-    <export>
-      <name>java.sql</name>
-    </export>
-    <export>
-      <name>javax.sql</name>
-    </export>
-    <export>
-      <name>javax.transaction.xa</name>
-    </export>
-  </module>
-  <module>
-    <name>java.sql.rowset</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.logging</depend>
-    <depend re-exports="true">java.naming</depend>
-    <depend re-exports="true">java.sql</depend>
-    <depend>java.xml</depend>
-    <export>
-      <name>javax.sql.rowset</name>
-    </export>
-    <export>
-      <name>javax.sql.rowset.serial</name>
-    </export>
-    <export>
-      <name>javax.sql.rowset.spi</name>
-    </export>
-  </module>
-  <module>
-    <name>java.transaction</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.rmi</depend>
-    <export>
-      <name>javax.transaction</name>
-    </export>
-  </module>
-  <module>
-    <name>java.xml</name>
-    <depend>java.base</depend>
-    <export>
-      <name>javax.xml</name>
-    </export>
-    <export>
-      <name>javax.xml.catalog</name>
-    </export>
-    <export>
-      <name>javax.xml.datatype</name>
-    </export>
-    <export>
-      <name>javax.xml.namespace</name>
-    </export>
-    <export>
-      <name>javax.xml.parsers</name>
-    </export>
-    <export>
-      <name>javax.xml.stream</name>
-    </export>
-    <export>
-      <name>javax.xml.stream.events</name>
-    </export>
-    <export>
-      <name>javax.xml.stream.util</name>
-    </export>
-    <export>
-      <name>javax.xml.transform</name>
-    </export>
-    <export>
-      <name>javax.xml.transform.dom</name>
-    </export>
-    <export>
-      <name>javax.xml.transform.sax</name>
-    </export>
-    <export>
-      <name>javax.xml.transform.stax</name>
-    </export>
-    <export>
-      <name>javax.xml.transform.stream</name>
-    </export>
-    <export>
-      <name>javax.xml.validation</name>
-    </export>
-    <export>
-      <name>javax.xml.xpath</name>
-    </export>
-    <export>
-      <name>org.w3c.dom</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.bootstrap</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.events</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.ls</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.ranges</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.traversal</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.views</name>
-    </export>
-    <export>
-      <name>org.xml.sax</name>
-    </export>
-    <export>
-      <name>org.xml.sax.ext</name>
-    </export>
-    <export>
-      <name>org.xml.sax.helpers</name>
-    </export>
-     <export>
-       <name>com.sun.org.apache.xerces.internal.dom</name>
-       <to>java.xml.ws</to>
-     </export>
-     <export>
-       <name>com.sun.org.apache.xerces.internal.jaxp</name>
-       <to>java.xml.ws</to>
-     </export>
-     <export>
-       <name>com.sun.org.apache.xerces.internal.util</name>
-       <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xml.internal.dtm</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xml.internal.resolver</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xml.internal.resolver.tools</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xml.internal.utils</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xpath.internal</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xpath.internal.compiler</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xpath.internal.functions</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xpath.internal.objects</name>
-      <to>java.xml.crypto</to>
-    </export>
-    <export>
-      <name>com.sun.org.apache.xpath.internal.res</name>
-      <to>java.xml.crypto</to>
-    </export>
-  </module>
-  <module>
-    <name>java.xml.bind</name>
-    <depend re-exports="true">java.activation</depend>
-    <depend>java.base</depend>
-    <depend>java.compiler</depend>
-    <depend>java.datatransfer</depend>
-    <depend>java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend re-exports="true">java.xml</depend>
-    <export>
-      <name>javax.xml.bind</name>
-    </export>
-    <export>
-      <name>javax.xml.bind.annotation</name>
-    </export>
-    <export>
-      <name>javax.xml.bind.annotation.adapters</name>
-    </export>
-    <export>
-      <name>javax.xml.bind.attachment</name>
-    </export>
-    <export>
-      <name>javax.xml.bind.helpers</name>
-    </export>
-    <export>
-      <name>javax.xml.bind.util</name>
-    </export>
-    <export>
-      <name>com.sun.istack.internal</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.istack.internal.localization</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.istack.internal.logging</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.annotation</name>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.api</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.api.impl</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.marshaller</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.unmarshaller</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.util</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.annotation</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.core</name>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.impl</name>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.nav</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.runtime</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.model.util</name>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.runtime</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.runtime.unmarshaller</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.schemagen</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.schemagen.episode</name>
-      <to>jdk.xml.bind</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.schemagen.xmlschema</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.bind.v2.util</name>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.fastinfoset.stax</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.fastinfoset.vocab</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.org.jvnet.fastinfoset</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.org.jvnet.mimepull</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.org.jvnet.staxex</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.org.jvnet.staxex.util</name>
-      <to>java.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.txw2</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.txw2.annotation</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.txw2.output</name>
-      <to>java.xml.ws</to>
-      <to>jdk.xml.bind</to>
-      <to>jdk.xml.ws</to>
-    </export>
-  </module>
-  <module>
-    <name>java.xml.crypto</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <depend re-exports="true">java.xml</depend>
-    <export>
-      <name>javax.xml.crypto</name>
-    </export>
-    <export>
-      <name>javax.xml.crypto.dom</name>
-    </export>
-    <export>
-      <name>javax.xml.crypto.dsig</name>
-    </export>
-    <export>
-      <name>javax.xml.crypto.dsig.dom</name>
-    </export>
-    <export>
-      <name>javax.xml.crypto.dsig.keyinfo</name>
-    </export>
-    <export>
-      <name>javax.xml.crypto.dsig.spec</name>
-    </export>
-  </module>
-  <module>
-    <name>java.xml.ws</name>
-    <depend>java.annotations.common</depend>
-    <depend>java.base</depend>
-    <depend>java.datatransfer</depend>
-    <depend>java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend>java.management</depend>
-    <depend>java.rmi</depend>
-    <depend re-exports="true">java.activation</depend>
-    <depend re-exports="true">java.xml</depend>
-    <depend re-exports="true">java.xml.bind</depend>
-    <depend>jdk.httpserver</depend>
-    <export>
-      <name>javax.jws</name>
-    </export>
-    <export>
-      <name>javax.jws.soap</name>
-    </export>
-    <export>
-      <name>javax.xml.soap</name>
-    </export>
-    <export>
-      <name>javax.xml.ws</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.handler</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.handler.soap</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.http</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.soap</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.spi</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.spi.http</name>
-    </export>
-    <export>
-      <name>javax.xml.ws.wsaddressing</name>
-    </export>
-    <export>
-      <name>com.oracle.webservices.internal.api.databinding</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.addressing</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.addressing.v200408</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.addressing</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.databinding</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.model</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.server</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.streaming</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.wsdl.parser</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.api.wsdl.writer</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.binding</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.db</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.model</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.policy.sourcemodel.wspolicy</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.spi.db</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.streaming</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.util</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.util.exception</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.util.xml</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.wsdl.parser</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.ws.wsdl.writer</name>
-      <to>jdk.xml.ws</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.attach</name>
-    <depend>java.base</depend>
-    <depend>jdk.jvmstat</depend>
-    <export>
-      <name>com.sun.tools.attach</name>
-    </export>
-    <export>
-      <name>com.sun.tools.attach.spi</name>
-    </export>
-    <export>
-      <name>sun.tools.attach</name>
-      <to>jdk.jcmd</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.charsets</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.compiler</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.compiler</depend>
-    <export>
-      <name>com.sun.source.doctree</name>
-    </export>
-    <export>
-      <name>com.sun.source.tree</name>
-    </export>
-    <export>
-      <name>com.sun.source.util</name>
-    </export>
-    <export>
-      <name>com.sun.tools.javac</name>
-    </export>
-    <export>
-      <name>com.sun.tools.doclint</name>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.api</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.code</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.comp</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.file</name>
-      <to>jdk.javadoc</to>
-      <to>jdk.jdeps</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.jvm</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.main</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.nio</name>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.parser</name>
-      <to>jdk.jshell</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.platform</name>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.sym</name>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.tree</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.util</name>
-      <to>jdk.jshell</to>
-      <to>jdk.javadoc</to>
-      <to>jdk.jdeps</to>
-    </export>
-    <export>
-      <name>com.sun.tools.javac.model</name>
-      <to>jdk.javadoc</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.crypto.ec</name>
-    <depend>java.base</depend>
-    <export>
-      <name>sun.security.ec</name>
-      <to>jdk.crypto.pkcs11</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.crypto.mscapi</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.crypto.pkcs11</name>
-    <depend>java.base</depend>
-    <depend>jdk.crypto.ec</depend>
-  </module>
-  <module>
-    <name>jdk.crypto.ucrypto</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.dev</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.dynalink</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>jdk.dynalink</name>
-    </export>
-    <export>
-      <name>jdk.dynalink.beans</name>
-    </export>
-    <export>
-      <name>jdk.dynalink.linker</name>
-    </export>
-    <export>
-      <name>jdk.dynalink.linker.support</name>
-    </export>
-    <export>
-      <name>jdk.dynalink.support</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.hotspot.agent</name>
-    <depend>java.base</depend>
-    <depend>java.datatransfer</depend>
-    <depend>java.desktop</depend>
-    <depend>java.rmi</depend>
-    <depend>java.scripting</depend>
-    <depend>jdk.jdi</depend>
-  </module>
-  <module>
-    <name>jdk.httpserver</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <export>
-      <name>com.sun.net.httpserver</name>
-    </export>
-    <export>
-      <name>com.sun.net.httpserver.spi</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.internal.le</name>
-    <depend>java.base</depend>
-    <export>
-      <name>jdk.internal.jline</name>
-      <to>jdk.jshell</to>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.internal.jline.console</name>
-      <to>jdk.jshell</to>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.internal.jline.console.completer</name>
-      <to>jdk.jshell</to>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.internal.jline.console.history</name>
-      <to>jdk.jshell</to>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.internal.jline.internal</name>
-      <to>jdk.jshell</to>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.internal.opt</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.jartool</name>
-    <depend>java.base</depend>
-    <export>
-      <name>com.sun.jarsigner</name>
-    </export>
-    <export>
-      <name>jdk.security.jarsigner</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.javadoc</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.compiler</depend>
-    <depend>java.xml</depend>
-    <depend re-exports="true">jdk.compiler</depend>
-    <export>
-      <name>com.sun.javadoc</name>
-    </export>
-    <export>
-      <name>com.sun.tools.doclets</name>
-    </export>
-    <export>
-      <name>com.sun.tools.javadoc</name>
-    </export>
-    <export>
-      <name>jdk.javadoc.doclet</name>
-    </export>
-    <export>
-      <name>jdk.javadoc.doclet.taglet</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jcmd</name>
-    <depend>java.base</depend>
-    <depend>jdk.attach</depend>
-    <depend>jdk.jvmstat</depend>
-  </module>
-  <module>
-    <name>jdk.jconsole</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend re-exports="true">java.management</depend>
-    <depend>java.rmi</depend>
-    <depend>jdk.attach</depend>
-    <depend>jdk.jvmstat</depend>
-    <depend>jdk.management</depend>
-    <export>
-      <name>com.sun.tools.jconsole</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jdeps</name>
-    <depend>java.base</depend>
-    <depend>java.compiler</depend>
-    <depend>java.xml</depend>
-    <depend>jdk.compiler</depend>
-  </module>
-  <module>
-    <name>jdk.jdi</name>
-    <depend>java.base</depend>
-    <depend>jdk.attach</depend>
-    <export>
-      <name>com.sun.jdi</name>
-    </export>
-    <export>
-      <name>com.sun.jdi.connect</name>
-    </export>
-    <export>
-      <name>com.sun.jdi.connect.spi</name>
-    </export>
-    <export>
-      <name>com.sun.jdi.event</name>
-    </export>
-    <export>
-      <name>com.sun.jdi.request</name>
-    </export>
-    <export>
-      <name>com.sun.tools.jdi</name>
-      <to>jdk.hotspot.agent</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jdwp.agent</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.jvmstat</name>
-    <depend>java.base</depend>
-    <export>
-      <name>sun.jvmstat.monitor</name>
-      <to>jdk.attach</to>
-      <to>jdk.jcmd</to>
-      <to>jdk.jconsole</to>
-      <to>jdk.jvmstat.rmi</to>
-    </export>
-    <export>
-      <name>sun.jvmstat.monitor.event</name>
-      <to>jdk.jcmd</to>
-      <to>jdk.jvmstat.rmi</to>
-    </export>
-    <export>
-      <name>sun.jvmstat.perfdata.monitor</name>
-      <to>jdk.jvmstat.rmi</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.jvmstat.rmi</name>
-    <depend>java.base</depend>
-    <depend>java.rmi</depend>
-    <depend>jdk.jvmstat</depend>
-    <export>
-      <name>sun.jvmstat.monitor.remote</name>
-      <to>java.rmi</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.localedata</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.management</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.management</depend>
-    <export>
-      <name>com.sun.management</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.naming.dns</name>
-    <depend>java.base</depend>
-    <depend>java.naming</depend>
-  </module>
-  <module>
-    <name>jdk.naming.rmi</name>
-    <depend>java.base</depend>
-    <depend>java.naming</depend>
-    <depend>java.rmi</depend>
-  </module>
-  <module>
-    <name>jdk.pack200</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.policytool</name>
-    <depend>java.base</depend>
-    <depend>java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend>java.management</depend>
-    <depend>java.security.jgss</depend>
-    <depend>java.sql</depend>
-    <depend>jdk.security.jgss</depend>
-  </module>
-  <module>
-    <name>jdk.rmic</name>
-    <depend>java.base</depend>
-    <depend>java.corba</depend>
-    <depend>jdk.compiler</depend>
-    <depend>jdk.javadoc</depend>
-  </module>
-  <module>
-    <name>jdk.scripting.nashorn</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <depend>jdk.dynalink</depend>
-    <depend re-exports="true">java.scripting</depend>
-    <export>
-      <name>jdk.nashorn.internal.runtime</name>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.nashorn.internal.objects</name>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.nashorn.tools</name>
-      <to>jdk.scripting.nashorn.shell</to>
-    </export>
-    <export>
-      <name>jdk.nashorn.api.scripting</name>
-    </export>
-    <export>
-      <name>jdk.nashorn.api.tree</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.scripting.nashorn.shell</name>
-    <depend>java.base</depend>
-    <depend>jdk.scripting.nashorn</depend>
-    <depend>jdk.internal.le</depend> <!-- jline -->
-    <depend>java.desktop</depend> <!-- EditPad -->
-    <depend>java.compiler</depend> <!-- java package completion -->
-  </module>
-  <module>
-    <name>jdk.sctp</name>
-    <depend>java.base</depend>
-    <export>
-      <name>com.sun.nio.sctp</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.security.auth</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.naming</depend>
-    <depend>java.security.jgss</depend>
-    <export>
-      <name>com.sun.security.auth</name>
-    </export>
-    <export>
-      <name>com.sun.security.auth.callback</name>
-    </export>
-    <export>
-      <name>com.sun.security.auth.login</name>
-    </export>
-    <export>
-      <name>com.sun.security.auth.module</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.security.jgss</name>
-    <depend>java.base</depend>
-    <depend>java.logging</depend>
-    <depend re-exports="true">java.security.jgss</depend>
-    <depend>java.security.sasl</depend>
-    <export>
-      <name>com.sun.security.jgss</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.vm.ci</name>
-    <depend>java.base</depend>
-    <export>
-      <name>jdk.vm.ci.hotspot</name>
-      <to>jdk.jfr</to>
-    </export>
-    <export>
-      <name>jdk.vm.ci.hotspot.events</name>
-      <to>jdk.jfr</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.xml.bind</name>
-    <depend>java.activation</depend>
-    <depend>java.base</depend>
-    <depend>java.compiler</depend>
-    <depend>java.datatransfer</depend>
-    <depend>java.desktop</depend>
-    <depend>java.logging</depend>
-    <depend>java.xml</depend>
-    <depend>java.xml.bind</depend>
-    <depend>jdk.compiler</depend>
-    <export>
-      <name>com.sun.codemodel.internal</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.codemodel.internal.writer</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.istack.internal.tools</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.jxc.ap</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.jxc.model.nav</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc.api</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc.api.util</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc.reader</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc.reader.internalizer</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.tools.internal.xjc.util</name>
-      <to>jdk.xml.ws</to>
-    </export>
-    <export>
-      <name>com.sun.xml.internal.xsom.parser</name>
-      <to>jdk.xml.ws</to>
-    </export>
-  </module>
-  <module>
-    <name>jdk.xml.dom</name>
-    <depend>java.base</depend>
-    <depend re-exports="true">java.xml</depend>
-    <export>
-      <name>org.w3c.dom.css</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.html</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.stylesheets</name>
-    </export>
-    <export>
-      <name>org.w3c.dom.xpath</name>
-    </export>
-  </module>
-  <module>
-    <name>jdk.xml.ws</name>
-    <depend>java.base</depend>
-    <depend>java.compiler</depend>
-    <depend>java.logging</depend>
-    <depend>java.rmi</depend>
-    <depend>java.xml</depend>
-    <depend>java.xml.bind</depend>
-    <depend>java.xml.ws</depend>
-    <depend>jdk.xml.bind</depend>
-  </module>
-  <module>
-    <name>jdk.zipfs</name>
-    <depend>java.base</depend>
-  </module>
-  <module>
-    <name>jdk.accessibility</name>
-    <depend>java.base</depend>
-    <depend>java.desktop</depend>
-  </module>
-</modules>
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 98a913b..2e01fc0 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -343,3 +343,4 @@
 8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107
 58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108
 70f0c397021116d7dbd79b01c6711c5d2e68dab4 jdk-9+109
+9937077e48f19e98af07c4954790fe09b94ca510 jdk-9+110
diff --git a/nashorn/buildtools/nasgen/build.xml b/nashorn/buildtools/nasgen/build.xml
index 6032143..d05b485 100644
--- a/nashorn/buildtools/nasgen/build.xml
+++ b/nashorn/buildtools/nasgen/build.xml
@@ -40,10 +40,9 @@
   <target name="compile" depends="prepare" description="Compiles the nasgen sources">
     <javac srcdir="${src.dir}"
            destdir="${build.classes.dir}"
-           classpath="${javac.classpath}"
            debug="${javac.debug}"
            includeantruntime="false" fork="true">
-      <compilerarg value="-J-Xbootclasspath/p:${javac.classpath}"/>
+      <compilerarg value="-XaddExports:${nasgen.module.imports}"/>
       <compilerarg value="-Xlint:unchecked"/>
       <compilerarg value="-Xlint:deprecation"/>
       <compilerarg value="-XDignore.symbol.file"/>
diff --git a/nashorn/buildtools/nasgen/project.properties b/nashorn/buildtools/nasgen/project.properties
index 5963f68..794bda8 100644
--- a/nashorn/buildtools/nasgen/project.properties
+++ b/nashorn/buildtools/nasgen/project.properties
@@ -37,12 +37,11 @@
 dist.jar=${dist.dir}/nasgen.jar
 dist.javadoc.dir=${dist.dir}/javadoc
 
-nashorn.dir=../../
-
 javac.debug=true
 
-javac.classpath=\
-    ${nashorn.dir}/build/classes
+nasgen.module.imports=\
+    java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED,\
+    java.base/jdk.internal.org.objectweb.asm.util=ALL-UNNAMED
 
 meta.inf.dir=${src.dir}/META-INF
 run.classpath=\
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index f01a1d1..9eb9f47 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -143,6 +143,9 @@
                 try {
                     return super.getCommonSuperClass(type1, type2);
                 } catch (final RuntimeException | LinkageError e) {
+                    if (MemberInfo.isScriptObject(type1) && MemberInfo.isScriptObject(type2)) {
+                        return StringConstants.SCRIPTOBJECT_TYPE;
+                    }
                     return StringConstants.OBJECT_TYPE;
                 }
             }
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 388ab9a..9324788 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
@@ -26,14 +26,15 @@
 
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
+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;
 
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.annotations.Where;
-import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
  * Details about a Java method or field annotated with any of the field/method
@@ -460,6 +461,40 @@
         }
     }
 
+    /**
+     * Returns if the given (internal) name of a class represents a ScriptObject subtype.
+     */
+    public static boolean isScriptObject(final String name) {
+        // very crude check for ScriptObject subtype!
+        if (name.startsWith(OBJ_PKG + "Native") ||
+            name.equals(OBJ_PKG + "Global") ||
+            name.equals(OBJ_PKG + "ArrayBufferView")) {
+            return true;
+        }
+
+        if (name.startsWith(RUNTIME_PKG)) {
+            final String simpleName = name.substring(name.lastIndexOf('/') + 1);
+            switch (simpleName) {
+                case "ScriptObject":
+                case "ScriptFunction":
+                case "NativeJavaPackage":
+                case "Scope":
+                    return true;
+            }
+        }
+
+        if (name.startsWith(SCRIPTS_PKG)) {
+            final String simpleName = name.substring(name.lastIndexOf('/') + 1);
+            switch (simpleName) {
+                case "JD":
+                case "JO":
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
     private static boolean isValidJSType(final Type type) {
         return isJSPrimitiveType(type) || isJSObjectType(type);
     }
@@ -488,20 +523,11 @@
     }
 
     private static boolean isScriptObject(final Type type) {
-        if (type.getDescriptor().equals(SCRIPTOBJECT_DESC)) {
-            return true;
+        if (type.getSort() != Type.OBJECT) {
+            return false;
         }
 
-        if (type.getSort() == Type.OBJECT) {
-            try {
-                final Class<?> clazz = Class.forName(type.getClassName(), false, MY_LOADER);
-                return ScriptObject.class.isAssignableFrom(clazz);
-            } catch (final ClassNotFoundException cnfe) {
-                return false;
-            }
-        }
-
-        return false;
+        return isScriptObject(type.getInternalName());
     }
 
     private void error(final String msg) {
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 1a99d82..a4a906b 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
@@ -77,6 +77,7 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
 import static jdk.internal.org.objectweb.asm.Opcodes.SWAP;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJ_ANNO_PKG;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT2;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_INIT3;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SPECIALIZATION_TYPE;
@@ -85,7 +86,6 @@
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
 
 /**
  * Base class for all method generating classes.
@@ -98,7 +98,7 @@
     private final Type returnType;
     private final Type[] argumentTypes;
 
-    static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType(LinkLogic.getEmptyLinkLogicClass());
+    static final Type EMPTY_LINK_LOGIC_TYPE = Type.getType("L" + OBJ_ANNO_PKG + "SpecializedFunction$LinkLogic$Empty;");
 
     MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) {
         super(Main.ASM_VERSION, mv);
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
index ca9a325..deeea33 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
@@ -31,33 +31,31 @@
 import java.util.List;
 import java.util.Map;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.annotations.Constructor;
-import jdk.nashorn.internal.objects.annotations.Function;
-import jdk.nashorn.internal.objects.annotations.Getter;
-import jdk.nashorn.internal.objects.annotations.Property;
-import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.Setter;
-import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
-import jdk.nashorn.internal.objects.annotations.SpecializedFunction.LinkLogic;
-import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
 
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJ_ANNO_PKG;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.RUNTIME_PKG;
+
 /**
  * All annotation information from a class that is annotated with
  * the annotation com.sun.oracle.objects.annotations.ScriptClass.
  *
  */
 public final class ScriptClassInfo {
+    private static String getTypeDescriptor(String pkg, String name) {
+        return "L" + pkg + name + ";";
+    }
+
     // descriptors for various annotations
-    static final String SCRIPT_CLASS_ANNO_DESC  = Type.getDescriptor(ScriptClass.class);
-    static final String CONSTRUCTOR_ANNO_DESC   = Type.getDescriptor(Constructor.class);
-    static final String FUNCTION_ANNO_DESC      = Type.getDescriptor(Function.class);
-    static final String GETTER_ANNO_DESC        = Type.getDescriptor(Getter.class);
-    static final String SETTER_ANNO_DESC        = Type.getDescriptor(Setter.class);
-    static final String PROPERTY_ANNO_DESC      = Type.getDescriptor(Property.class);
-    static final String WHERE_ENUM_DESC         = Type.getDescriptor(Where.class);
-    static final String LINK_LOGIC_DESC         = Type.getDescriptor(LinkLogic.class);
-    static final String SPECIALIZED_FUNCTION    = Type.getDescriptor(SpecializedFunction.class);
+    static final String SCRIPT_CLASS_ANNO_DESC  = getTypeDescriptor(OBJ_ANNO_PKG, "ScriptClass");
+    static final String CONSTRUCTOR_ANNO_DESC   = getTypeDescriptor(OBJ_ANNO_PKG, "Constructor");
+    static final String FUNCTION_ANNO_DESC      = getTypeDescriptor(OBJ_ANNO_PKG, "Function");
+    static final String GETTER_ANNO_DESC        = getTypeDescriptor(OBJ_ANNO_PKG, "Getter");
+    static final String SETTER_ANNO_DESC        = getTypeDescriptor(OBJ_ANNO_PKG, "Setter");
+    static final String PROPERTY_ANNO_DESC      = getTypeDescriptor(OBJ_ANNO_PKG, "Property");
+    static final String WHERE_ENUM_DESC         = getTypeDescriptor(OBJ_ANNO_PKG, "Where");
+    static final String LINK_LOGIC_DESC         = getTypeDescriptor(OBJ_ANNO_PKG, "SpecializedFunction$LinkLogic");
+    static final String SPECIALIZED_FUNCTION    = getTypeDescriptor(OBJ_ANNO_PKG, "SpecializedFunction");
 
     static final Map<String, Kind> annotations = new HashMap<>();
 
@@ -276,6 +274,7 @@
             try {
                 memInfo.verify();
             } catch (final Exception e) {
+                e.printStackTrace();
                 error(e.getMessage());
             }
         }
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 97deda8..4a14d80 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
@@ -41,7 +41,6 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
 
 /**
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
index 7f699fd..4bdb358 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
@@ -50,7 +50,6 @@
 import jdk.internal.org.objectweb.asm.FieldVisitor;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
-import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind;
 
 /**
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 233b4f9..428cece 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
@@ -31,25 +31,23 @@
 import java.util.Collections;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.NativeSymbol;
-import jdk.nashorn.internal.runtime.AccessorProperty;
-import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.PrototypeObject;
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.Specialization;
-import jdk.nashorn.internal.runtime.Symbol;
 
 /**
  * String constants used for code generation/instrumentation.
  */
 @SuppressWarnings("javadoc")
 public interface StringConstants {
+    static final String NASHORN_INTERNAL = "jdk/nashorn/internal/";
+    static final String OBJ_PKG = NASHORN_INTERNAL + "objects/";
+    static final String OBJ_ANNO_PKG = OBJ_PKG + "annotations/";
+    static final String RUNTIME_PKG = NASHORN_INTERNAL + "runtime/";
+    static final String SCRIPTS_PKG = NASHORN_INTERNAL + "scripts/";
+
     // 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(Specialization.class);
-    static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType(Specialization[].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);
     static final Type TYPE_STRING               = Type.getType(String.class);
     static final Type TYPE_CLASS                = Type.getType(Class.class);
@@ -85,13 +83,13 @@
     static final String LIST_DESC = TYPE_LIST.getDescriptor();
 
     // Nashorn types, methods
-    static final Type TYPE_ACCESSORPROPERTY   = Type.getType(AccessorProperty.class);
-    static final Type TYPE_PROPERTYMAP        = Type.getType(PropertyMap.class);
-    static final Type TYPE_PROTOTYPEOBJECT    = Type.getType(PrototypeObject.class);
-    static final Type TYPE_SCRIPTFUNCTION     = Type.getType(ScriptFunction.class);
-    static final Type TYPE_SCRIPTOBJECT       = Type.getType(ScriptObject.class);
-    static final Type TYPE_NATIVESYMBOL       = Type.getType(NativeSymbol.class);
-    static final Type TYPE_SYMBOL             = Type.getType(Symbol.class);
+    static final Type TYPE_ACCESSORPROPERTY   = Type.getType("L" + RUNTIME_PKG + "AccessorProperty;");
+    static final Type TYPE_PROPERTYMAP        = Type.getType("L" + RUNTIME_PKG + "PropertyMap;");
+    static final Type TYPE_PROTOTYPEOBJECT    = Type.getType("L" + RUNTIME_PKG + "PrototypeObject;");
+    static final Type TYPE_SCRIPTFUNCTION     = Type.getType("L" + RUNTIME_PKG + "ScriptFunction;");
+    static final Type TYPE_SCRIPTOBJECT       = Type.getType("L" + RUNTIME_PKG + "ScriptObject;");
+    static final Type TYPE_NATIVESYMBOL       = Type.getType("L" + OBJ_PKG + "NativeSymbol;");
+    static final Type TYPE_SYMBOL             = Type.getType("L" + RUNTIME_PKG + "Symbol;");
 
     static final String PROTOTYPE_SUFFIX = "$Prototype";
     static final String CONSTRUCTOR_SUFFIX = "$Constructor";
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Where.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Where.java
new file mode 100644
index 0000000..daaa2bc
--- /dev/null
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Where.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.tools.nasgen;
+
+/**
+ * Enum to tell where a Function or Property belongs.
+ * Note: keep this in sync. with jdk.nashorn.internal.objects.annotations.Where.
+ */
+public enum Where {
+    /** this means that the item belongs in the Constructor of an object */
+    CONSTRUCTOR,
+    /** this means that the item belongs in the Prototype of an object */
+    PROTOTYPE,
+    /** this means that the item belongs in the Instance of an object */
+    INSTANCE
+}
diff --git a/nashorn/make/BuildNashorn.gmk b/nashorn/make/BuildNashorn.gmk
index f4dcf39..2d9a68e 100644
--- a/nashorn/make/BuildNashorn.gmk
+++ b/nashorn/make/BuildNashorn.gmk
@@ -38,11 +38,14 @@
 
 NASHORN_JAR := $(IMAGES_OUTPUTDIR)/nashorn.jar
 
+MODULESOURCEPATH := $(NASHORN_TOPDIR)/src/*/share/classes
+
 # Need to use source and target 8 for nasgen to work.
 $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG, \
     JVM := $(JAVA), \
     JAVAC := $(NEW_JAVAC), \
-    FLAGS := -g -source 8 -target 8 -bootclasspath $(JDK_CLASSES), \
+    FLAGS := -g -source 9 -target 9 -upgrademodulepath "$(JDK_OUTPUTDIR)/modules/" \
+         -system none -modulesourcepath "$(MODULESOURCEPATH)", \
     SERVER_DIR := $(SJAVAC_SERVER_DIR), \
     SERVER_JVM := $(SJAVAC_SERVER_JAVA)))
 
@@ -52,10 +55,11 @@
 # seamlessly.
 $(eval $(call SetupJavaCompilation,jdk.scripting.nashorn, \
     SETUP := GENERATE_NEWBYTECODE_DEBUG, \
+    MODULE := jdk.scripting.nashorn, \
     SRC := $(NASHORN_TOPDIR)/src/jdk.scripting.nashorn/share/classes, \
     EXCLUDE_FILES := META-INF/MANIFEST.MF, \
     COPY := .properties .js, \
-    BIN := $(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/classes))
+    BIN := $(SUPPORT_OUTPUTDIR)/special_classes))
 
 NASGEN_SRC := $(NASHORN_TOPDIR)/buildtools/nasgen/src
 ASM_SRC := $(JDK_TOPDIR)/src/java.base/share/classes/jdk/internal/org/objectweb/asm
@@ -64,24 +68,31 @@
 $(eval $(call SetupJavaCompilation,BUILD_NASGEN, \
     SETUP := GENERATE_OLDBYTECODE, \
     SRC := $(NASGEN_SRC) $(ASM_SRC), \
-    BIN := $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes, \
-    ADD_JAVAC_FLAGS := -Xbootclasspath/p:"$(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/classes"))
-
-# Nasgen needs nashorn classes
-$(BUILD_NASGEN): $(jdk.scripting.nashorn)
+    BIN := $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes))
 
 NASHORN_CLASSES_DIR := $(JDK_OUTPUTDIR)/modules/jdk.scripting.nashorn
 NASGEN_RUN_FILE := $(NASHORN_CLASSES_DIR)/_the.nasgen.run
 
+ifeq ($(BOOT_JDK_MODULAR), true)
+  NASGEN_OPTIONS := \
+      -cp $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \
+      -Xpatch:$(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \
+      -XaddExports:$(subst $(SPACE),$(COMMA),$(strip \
+          java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
+          java.base/jdk.internal.org.objectweb.asm.util=ALL-UNNAMED \
+      ))
+else
+  NASGEN_OPTIONS := \
+      -Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/nasgen_classes
+endif
+
 # Copy classes to final classes dir and run nasgen to modify classes in jdk.nashorn.internal.objects package
-$(NASGEN_RUN_FILE): $(BUILD_NASGEN)
+$(NASGEN_RUN_FILE): $(BUILD_NASGEN) $(jdk.scripting.nashorn)
 	$(ECHO) Running nasgen
 	$(MKDIR) -p $(@D)
 	$(RM) -rf $(@D)/jdk $(@D)/netscape
-	$(CP) -R -p $(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/classes/* $(@D)/
-	$(FIXPATH) $(JAVA) \
-	    -Xbootclasspath/p:$(call PathList, $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes \
-            $(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/classes) \
+	$(CP) -R -p $(SUPPORT_OUTPUTDIR)/special_classes/jdk.scripting.nashorn/* $(@D)/
+	$(JAVA) $(NASGEN_OPTIONS) \
 	    jdk.nashorn.internal.tools.nasgen.Main $(@D) jdk.nashorn.internal.objects $(@D)
 	$(TOUCH) $@
 
diff --git a/nashorn/make/build-nasgen.xml b/nashorn/make/build-nasgen.xml
index 0032011..5c8eccf 100644
--- a/nashorn/make/build-nasgen.xml
+++ b/nashorn/make/build-nasgen.xml
@@ -35,13 +35,11 @@
             <classpath>
                 <pathelement location="${basedir}/jcov2/lib/jcov_j2se_rt.jar"/>
                 <pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/>
-                <pathelement location="${dist.dir}/nasgen.jar"/>
-                <pathelement path="${build.dir}/classes"/>
             </classpath>
-            <jvmarg value="-Xbootclasspath/p:${basedir}/build/classes"/>
-            <arg value="${build.dir}/classes"/>
+            <jvmarg value="-XaddExports:${nasgen.module.imports}"/>
+            <arg value="${nashorn.module.classes.dir}"/>
             <arg value="jdk.nashorn.internal.objects"/>
-            <arg value="${build.dir}/classes"/>
+            <arg value="${nashorn.module.classes.dir}"/>
         </java>
     </target>
 
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index dff7478..d48765f 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -32,13 +32,10 @@
     <property file="${user.home}/.nashorn.project.local.properties"/>
 
     <loadproperties srcFile="make/project.properties"/>
-    <path id="dist.path">
-         <pathelement location="${dist.dir}"/>
+    <path id="nashorn.jar.path">
+         <pathelement location="${nashorn.jar}"/>
     </path>
-    <path id="nashorn.boot.prefix.path">
-      <pathelement location="${dist.jar}"/>
-    </path>
-    <property name="boot.class.path" value="-Xbootclasspath/p:${toString:nashorn.boot.prefix.path}"/>
+    <property name="nashorn.override.option" value="-Xpatch:${build.classes.dir}"/>
     <condition property="svn.executable" value="/usr/local/bin/svn" else="svn">
       <available file="/usr/local/bin/svn"/>
     </condition>
@@ -136,7 +133,10 @@
   <target name="prepare" depends="init">
     <mkdir dir="${build.dir}"/>
     <mkdir dir="${build.classes.dir}"/>
-    <mkdir dir="${build.classes.dir}/META-INF/services"/>
+    <mkdir dir="${nashorn.module.classes.dir}"/>
+    <mkdir dir="${dynalink.module.classes.dir}"/>
+    <mkdir dir="${nashorn.shell.module.classes.dir}"/>
+    <mkdir dir="${nashorn.module.classes.dir}/META-INF/services"/>
     <mkdir dir="${build.test.classes.dir}"/>
     <mkdir dir="${dist.dir}"/>
     <mkdir dir="${dist.javadoc.dir}"/>
@@ -150,9 +150,8 @@
   </target>
 
   <target name="compile" depends="prepare" description="Compiles nashorn">
-    <javac srcdir="${src.dir}"
-           destdir="${build.classes.dir}"
-           classpath="${javac.classpath}"
+    <javac srcdir="${dynalink.module.src.dir}"
+           destdir="${dynalink.module.classes.dir}"
            source="${javac.source}"
            target="${javac.target}"
            debug="${javac.debug}"
@@ -163,36 +162,59 @@
       <compilerarg value="-Xdiags:verbose"/>
       <compilerarg value="-parameters"/>
     </javac>
-    <copy todir="${build.classes.dir}/META-INF/services">
-       <fileset dir="${meta.inf.dir}/services/"/>
-    </copy>
-     <copy todir="${build.classes.dir}/jdk/nashorn/api/scripting/resources">
+    <javac srcdir="${nashorn.module.src.dir}"
+           destdir="${nashorn.module.classes.dir}"
+           source="${javac.source}"
+           target="${javac.target}"
+           debug="${javac.debug}"
+           encoding="${javac.encoding}"
+           includeantruntime="false" fork="true">
+      <compilerarg value="-Xlint:all"/>
+      <compilerarg value="-XDignore.symbol.file"/>
+      <compilerarg value="-Xdiags:verbose"/>
+      <compilerarg value="-parameters"/>
+      <compilerarg value="${nashorn.override.option}"/>
+    </javac>
+    <javac srcdir="${nashorn.shell.module.src.dir}"
+           destdir="${nashorn.shell.module.classes.dir}"
+           source="${javac.source}"
+           target="${javac.target}"
+           debug="${javac.debug}"
+           encoding="${javac.encoding}"
+           includeantruntime="false" fork="true">
+      <compilerarg value="-Xlint:all"/>
+      <compilerarg value="-XDignore.symbol.file"/>
+      <compilerarg value="-Xdiags:verbose"/>
+      <compilerarg value="-parameters"/>
+      <compilerarg value="${nashorn.override.option}"/>
+    </javac>
+    <!-- -Xpatch does not like module-info.class files! -->
+    <delete>
+      <fileset dir="${build.classes.dir}" includes="**/module-info.class"/>
+    </delete>
+     <copy todir="${nashorn.module.classes.dir}/jdk/nashorn/api/scripting/resources">
        <fileset dir="${nashorn.module.src.dir}/jdk/nashorn/api/scripting/resources/"/>
     </copy>
-    <copy todir="${build.classes.dir}/jdk/nashorn/internal/runtime/resources">
+    <copy todir="${nashorn.module.classes.dir}/jdk/nashorn/internal/runtime/resources">
        <fileset dir="${nashorn.module.src.dir}/jdk/nashorn/internal/runtime/resources/"/>
     </copy>
-    <copy todir="${build.classes.dir}/jdk/nashorn/tools/resources">
+    <copy todir="${nashorn.module.classes.dir}/jdk/nashorn/tools/resources">
        <fileset dir="${nashorn.module.src.dir}/jdk/nashorn/tools/resources/"/>
     </copy>
-    <copy file="${dynalink.module.src.dir}/jdk/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/dynalink/support"/>
-    <copy file="${nashorn.module.src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${build.classes.dir}/jdk/nashorn/internal/codegen"/>
+    <copy file="${dynalink.module.src.dir}/jdk/dynalink/support/messages.properties" todir="${dynalink.module.classes.dir}/jdk/dynalink/support"/>
+    <copy file="${nashorn.module.src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${nashorn.module.classes.dir}/jdk/nashorn/internal/codegen"/>
 
-    <echo message="version_string=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
-    <echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
-    <echo message="version_short=${nashorn.version}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true"/>
+    <echo message="version_string=${nashorn.fullversion}" file="${nashorn.module.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
+    <echo file="${nashorn.module.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
+    <echo message="version_short=${nashorn.version}" file="${nashorn.module.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true"/>
   </target>
 
   <target name="jar" depends="compile, run-nasgen, generate-cc-template" description="Creates nashorn.jar" unless="compile.suppress.jar">
-    <jar jarfile="${dist.jar}" manifest="${meta.inf.dir}/MANIFEST.MF" index="true" filesetmanifest="merge">
-      <!-- 
-        Exclude jjs classes from nashorn.jar to avoid desktop dependency.
-        We have a test to make sure basic nashorn code has only "compact1"
-        dependency - except for jjs shell code which has desktop dependency.
-      -->
-      <fileset dir="${build.classes.dir}">
-          <exclude name="**/jdk/nashorn/tools/jjs/*"/>
-      </fileset>
+    <jar jarfile="${dynalink.jar}">
+      <fileset dir="${dynalink.module.classes.dir}"/>
+    </jar>
+    <jar jarfile="${nashorn.jar}" index="true" filesetmanifest="merge">
+      <fileset dir="${nashorn.module.classes.dir}"/>
       <manifest>
         <attribute name="Archiver-Version" value="n/a"/>
         <attribute name="Build-Jdk" value="${java.runtime.version}"/>
@@ -204,6 +226,9 @@
         </section>
       </manifest>
     </jar>
+    <jar jarfile="${jjs.jar}">
+      <fileset dir="${nashorn.shell.module.classes.dir}"/>
+    </jar>
   </target>
 
   <target name="use-promoted-nashorn" depends="init">
@@ -212,35 +237,10 @@
     <property name="compile.suppress.jar" value="defined"/>
   </target>
 
-  <target name="build-fxshell" depends="jar">
-    <description>Builds the javafx shell.</description>
-    <mkdir dir="${fxshell.classes.dir}"/>
-    <javac srcdir="${fxshell.dir}"
-           destdir="${fxshell.classes.dir}"
-           classpath="${dist.jar}${path.separator}${javac.classpath}"
-           debug="${javac.debug}"
-           encoding="${javac.encoding}"
-           includeantruntime="false">
-    </javac>
-    <jar jarfile="${fxshell.jar}" manifest="${meta.inf.dir}/MANIFEST.MF" index="true" filesetmanifest="merge">
-      <fileset dir="${fxshell.classes.dir}"/>
-      <manifest>
-        <attribute name="Archiver-Version" value="n/a"/>
-        <attribute name="Build-Jdk" value="${java.runtime.version}"/>
-        <attribute name="Built-By" value="n/a"/>
-        <attribute name="Created-By" value="Ant jar task"/>
-        <section name="jdk/nashorn/">
-          <attribute name="Implementation-Title" value="Oracle Nashorn FXShell"/>
-          <attribute name="Implementation-Version" value="${nashorn.version}"/>
-        </section>
-      </manifest>
-    </jar>
-  </target>
-
   <!-- generate javadoc for all Nashorn and ASM classes -->
   <target name="javadoc" depends="jar">
     <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
-        extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
+        windowtitle="${nashorn.product.name} ${nashorn.version}"
         additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <arg value="${javadoc.option}"/>
       <classpath>
@@ -260,7 +260,7 @@
   <!-- generate javadoc for Nashorn classes -->
   <target name="javadocnh" depends="jar">
     <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
-        extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
+        windowtitle="${nashorn.product.name} ${nashorn.version}"
         additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <arg value="${javadoc.option}"/>
       <classpath>
@@ -304,7 +304,7 @@
   <!-- generate shell.html for shell tool documentation -->
   <target name="shelldoc" depends="jar">
     <java classname="${nashorn.shell.tool}" dir="${basedir}" output="${dist.dir}/shell.html" failonerror="true" fork="true">
-      <jvmarg line="${boot.class.path}"/>
+      <jvmarg line="${nashorn.override.option}"/>
       <arg value="-scripting"/>
       <arg value="docs/genshelldoc.js"/>
     </java>
@@ -334,10 +334,11 @@
            debug="${javac.debug}"
            encoding="${javac.encoding}"
            includeantruntime="false" fork="true">
-        <compilerarg value="${boot.class.path}"/>
+        <compilerarg value="${nashorn.override.option}"/>
         <compilerarg value="-Xlint:unchecked"/>
         <compilerarg value="-Xlint:deprecation"/>
         <compilerarg value="-Xdiags:verbose"/>
+        <compilerarg value="-XaddExports:${test.module.imports}"/>
     </javac>
 
     <copy todir="${build.test.classes.dir}/META-INF/services">
@@ -379,7 +380,11 @@
   <target name="generate-policy-file" depends="prepare">
     <echo file="${build.dir}/nashorn.policy">
 
-grant codeBase "file:/${toString:dist.path}/nashorn.jar" {
+grant codeBase "file:/${basedir}/${dynalink.module.classes.dir}" {
+    permission java.security.AllPermission;
+};
+
+grant codeBase "file:/${basedir}/${nashorn.module.classes.dir}" {
     permission java.security.AllPermission;
 };
 
@@ -530,7 +535,6 @@
     </fileset>
     <testng outputdir="${build.nosecurity.test.results.dir}/${testResultsSubDir}" classfilesetref="test.nosecurity.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
       <sysproperty key="nashorn.jar" value="${dist.dir}/nashorn.jar"/>
       <propertyset>
@@ -553,7 +557,6 @@
     <property name="debug.test.jvmargs" value=""/>
     <testng outputdir="${build.test.results.dir}/${testResultsSubDir}" classfilesetref="test.classes"
             verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <jvmarg line="${debug.test.jvmargs}"/>
       <propertyset>
@@ -571,7 +574,7 @@
     </testng>
   </target>
 
-  <target name="test" depends="prepare, javadocnh, test-pessimistic, test-optimistic"/>
+  <target name="test" depends="prepare, test-pessimistic, test-optimistic"/>
 
   <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <echo message="Running test suite in OPTIMISTIC mode..."/>
@@ -616,7 +619,6 @@
 
     <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
       <propertyset>
         <propertyref prefix="testjfx-test-sys-prop."/>
@@ -636,7 +638,6 @@
 
     <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <propertyset>
         <propertyref prefix="testmarkdown-test-sys-prop."/>
@@ -655,7 +656,6 @@
 
     <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <propertyset>
         <propertyref prefix="nashorn."/>
@@ -675,7 +675,6 @@
   <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <!-- use just build.test.classes.dir to avoid referring to TestNG -->
     <java classname="${parallel.test.runner}" dir="${basedir}" fork="true" failonerror="true">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <!-- avoid too many typeinfo cache files. Each script is run only once anyway -->
       <jvmarg line="-Dnashorn.typeInfo.disabled=true"/>
@@ -696,7 +695,6 @@
       <java classname="${parallel.test.runner}" dir="${basedir}"
         failonerror="true"
         fork="true">
-      <jvmarg line="${boot.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
       <classpath>
           <pathelement path="${run.test.classpath}"/>
@@ -715,7 +713,6 @@
   <target name="run" depends="jar"
       description="Run the shell with a sample script">
     <java classname="${nashorn.shell.tool}" fork="true" dir="samples">
-        <jvmarg line="${boot.class.path}"/>
         <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
         <arg value="-dump-on-error"/>
         <arg value="test.js"/>
@@ -725,7 +722,6 @@
   <target name="debug" depends="jar"
       description="Debug the shell with a sample script">
     <java classname="${nashorn.shell.tool}" fork="true" dir="samples">
-        <jvmarg line="${boot.class.path}"/>
         <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
         <arg value="--print-code"/>
         <arg value="--verify-code"/>
diff --git a/nashorn/make/nbproject/ide-targets.xml b/nashorn/make/nbproject/ide-targets.xml
index 7237f6d..503f89a 100644
--- a/nashorn/make/nbproject/ide-targets.xml
+++ b/nashorn/make/nbproject/ide-targets.xml
@@ -32,7 +32,7 @@
         </nbjpdastart>
         <java classname="jdk.nashorn.tools.Shell" classpath="${run.test.classpath}" dir="samples" fork="true">
 	    <jvmarg line="-Dnashorn.optimistic"/>
-            <jvmarg line="${boot.class.path}"/> 
+            <jvmarg line="${nashorn.override.path}"/> 
             <jvmarg line="${run.test.jvmargs}"/>
             <jvmarg value="-Xdebug"/>
             <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties
index fbaca21..9b4bdbd 100644
--- a/nashorn/make/project.properties
+++ b/nashorn/make/project.properties
@@ -31,8 +31,8 @@
 
 # source and target levels
 build.compiler=modern
-javac.source=1.8
-javac.target=1.8
+javac.source=1.9
+javac.target=1.9
 
 javadoc.option=-tag "implSpec:a:Implementation Requirements:"
 
@@ -53,6 +53,12 @@
 # nasgen tool
 nasgen.tool=jdk.nashorn.internal.tools.nasgen.Main
 
+nasgen.module.imports=\
+
+nasgen.module.imports=\
+    java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED,\
+    java.base/jdk.internal.org.objectweb.asm.util=ALL-UNNAMED
+
 # parallel test runner tool
 parallel.test.runner=jdk.nashorn.internal.test.framework.ParallelTestRunner
 
@@ -70,15 +76,11 @@
 
 # This directory is removed when the project is cleaned:
 dist.dir=dist
-dist.jar=${dist.dir}/nashorn.jar
+dynalink.jar=${dist.dir}/dynalink.jar
+nashorn.jar=${dist.dir}/nashorn.jar
+jjs.jar=${dist.dir}/jjs.jar
 dist.javadoc.dir=${dist.dir}/javadoc
 
-# nashorn javafx shell
-fxshell.tool = jdk.nashorn.tools.FXShell
-fxshell.classes.dir = ${build.dir}/fxshell/classes
-fxshell.dir = tools/fxshell
-fxshell.jar = ${dist.dir}/nashornfx.jar
-
 # configuration for java flight recorder
 run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
 
@@ -121,16 +123,28 @@
 
 javac.debug=true
 javac.encoding=ascii
-javac.classpath=\
-    ${build.classes.dir}
 javac.test.classpath=\
-    ${build.classes.dir}${path.separator}\
     ${build.test.classes.dir}${path.separator}\
     ${file.reference.testng.jar}${path.separator}\
     ${file.reference.jcommander.jar}${path.separator}\
     ${file.reference.bsh.jar}${path.separator}\
     ${file.reference.snakeyaml.jar}
 
+test.module.imports=\
+    jdk.scripting.nashorn/jdk.nashorn.internal.ir=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.codegen=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.parser=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.objects=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.linker=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.events=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.options=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp.joni=ALL-UNNAMED,\
+    jdk.scripting.nashorn/jdk.nashorn.tools=ALL-UNNAMED,\
+    java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
+
 meta.inf.dir=${nashorn.module.src.dir}/META-INF
 
 run.classpath=\
@@ -298,8 +312,11 @@
     ${nashorn.api.tests.jar}
 
 dynalink.module.src.dir=src/jdk.dynalink/share/classes
+dynalink.module.classes.dir=${build.classes.dir}/jdk.dynalink
 nashorn.module.src.dir=src/jdk.scripting.nashorn/share/classes
+nashorn.module.classes.dir=${build.classes.dir}/jdk.scripting.nashorn
 nashorn.shell.module.src.dir=src/jdk.scripting.nashorn.shell/share/classes
+nashorn.shell.module.classes.dir=${build.classes.dir}/jdk.scripting.nashorn.shell
 
 src.dir=${dynalink.module.src.dir}${path.separator}\
         ${nashorn.module.src.dir}${path.separator}\
@@ -324,6 +341,8 @@
 
 run.test.jvmargs.common=\
   -server \
+  -XaddExports:${test.module.imports} \
+  -Xpatch:${build.classes.dir} \
   -Dfile.encoding=UTF-8 \
   -Duser.language=${run.test.user.language} \
   -Duser.country=${run.test.user.country} \
diff --git a/nashorn/samples/test.js b/nashorn/samples/test.js
index 1a7e806..dfe4b7b 100644
--- a/nashorn/samples/test.js
+++ b/nashorn/samples/test.js
@@ -30,3 +30,5 @@
  */
 
 print("Hello World");
+var System = Java.type("java.lang.System");
+print(System.getProperty("jdk.launcher.patch.0"));
diff --git a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
index 215abd4..eb724e4 100644
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
@@ -384,7 +384,6 @@
         addClasses(knownLinkerClasses, fallbackLinkers);
 
         final List<GuardingDynamicLinker> discovered = discoverAutoLoadLinkers();
-
         // Now, concatenate ...
         final List<GuardingDynamicLinker> linkers =
                 new ArrayList<>(prioritizedLinkers.size() + discovered.size()
diff --git a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java
index cef183c..b855f8a 100644
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java
@@ -158,13 +158,13 @@
                 GET_LOOKUP_CONTEXT);
 
         if(target instanceof Method) {
-            final MethodHandle mh = Lookup.unreflect(lookup, (Method)target);
+            final MethodHandle mh = Lookup.unreflectCallerSensitive(lookup, (Method)target);
             if(Modifier.isStatic(((Member)target).getModifiers())) {
                 return StaticClassIntrospector.editStaticMethodHandle(mh);
             }
             return mh;
         }
-        return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup,
+        return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructorCallerSensitive(lookup,
                 (Constructor<?>)target));
     }
 
diff --git a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java
index fe428a7..2427cc6 100644
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java
@@ -84,6 +84,7 @@
 package jdk.dynalink.beans;
 
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -106,23 +107,29 @@
             // Non-public classes are always restricted
             return true;
         }
-        final SecurityManager sm = System.getSecurityManager();
-        if(sm == null) {
-            // No further restrictions if we don't have a security manager
-            return false;
-        }
         final String name = clazz.getName();
         final int i = name.lastIndexOf('.');
         if (i == -1) {
             // Classes in default package are never restricted
             return false;
         }
+        final String pkgName = name.substring(0, i);
+        final Module module = clazz.getModule();
+        if (module != null && !module.isExported(pkgName)) {
+            return true;
+        }
+
+        final SecurityManager sm = System.getSecurityManager();
+        if(sm == null) {
+            // No further restrictions if we don't have a security manager
+            return false;
+        }
         // Do a package access check from within an access control context with no permissions
         try {
             AccessController.doPrivileged(new PrivilegedAction<Void>() {
                 @Override
                 public Void run() {
-                    sm.checkPackageAccess(name.substring(0, i));
+                    sm.checkPackageAccess(pkgName);
                     return null;
                 }
             }, NO_PERMISSIONS_CONTEXT);
diff --git a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
index 4852cc0..adafcaa 100644
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
@@ -87,8 +87,11 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
+import java.lang.reflect.Module;
 import java.lang.reflect.Method;
+import jdk.internal.module.Modules;
 
 /**
  * A wrapper around {@link java.lang.invoke.MethodHandles.Lookup} that masks
@@ -127,6 +130,42 @@
         return unreflect(lookup, m);
     }
 
+    private static boolean addModuleRead(final MethodHandles.Lookup lookup, final Executable e) {
+        // may be module read missing from a script class!
+        final Class<?> declClass = e.getDeclaringClass();
+        final Module from = lookup.lookupClass().getModule();
+        final Module to = declClass.getModule();
+        if (from != null && to != null) {
+            Modules.addReads(from, to);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, of a caller sensitive method
+     * converting any encountered {@link IllegalAccessException} into an {@link IllegalAccessError}.
+     *
+     * @param lookup the lookup used to unreflect
+     * @param m the method to unreflect
+     * @return the unreflected method handle.
+     */
+    public static MethodHandle unreflectCallerSensitive(final MethodHandles.Lookup lookup, final Method m) {
+        try {
+            return unreflect(lookup, m);
+        } catch (final IllegalAccessError iae) {
+            if (addModuleRead(lookup, m)) {
+                try {
+                    return unreflect(lookup, m);
+                } catch (final IllegalAccessError e2) {
+                    // fall through and throw original error as cause
+                }
+            }
+            throw iae;
+        }
+    }
+
     /**
      * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)},
      * converting any encountered {@link IllegalAccessException} into an
@@ -228,6 +267,29 @@
     }
 
     /**
+     * Performs a caller sensitive {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any
+     * encountered {@link IllegalAccessException} into an {@link IllegalAccessError}.
+     *
+     * @param lookup the lookup used to unreflect
+     * @param c the constructor to unreflect
+     * @return the unreflected constructor handle.
+     */
+    public static MethodHandle unreflectConstructorCallerSensitive(final MethodHandles.Lookup lookup, final Constructor<?> c) {
+        try {
+            return unreflectConstructor(lookup, c);
+        } catch (final IllegalAccessError iae) {
+            if (addModuleRead(lookup, c)) {
+                try {
+                    return unreflectConstructor(lookup, c);
+                } catch (final IllegalAccessError e2) {
+                    // fall through and throw original error as cause
+                }
+            }
+            throw iae;
+        }
+    }
+
+    /**
      * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)},
      * converting any encountered {@link IllegalAccessException} into an
      * {@link IllegalAccessError}.
diff --git a/nashorn/src/jdk.dynalink/share/classes/module-info.java b/nashorn/src/jdk.dynalink/share/classes/module-info.java
new file mode 100644
index 0000000..b9abdc3
--- /dev/null
+++ b/nashorn/src/jdk.dynalink/share/classes/module-info.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.dynalink {
+    requires java.logging;
+
+    exports jdk.dynalink;
+    exports jdk.dynalink.beans;
+    exports jdk.dynalink.linker;
+    exports jdk.dynalink.linker.support;
+    exports jdk.dynalink.support;
+
+    uses jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+}
+
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
new file mode 100644
index 0000000..953ca18
--- /dev/null
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.scripting.nashorn.shell {
+    requires java.desktop;
+    requires java.compiler;
+    requires jdk.scripting.nashorn;
+    requires jdk.internal.le;
+}
+
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/MANIFEST.MF b/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/MANIFEST.MF
deleted file mode 100644
index b61190e..0000000
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,5 +0,0 @@
-Manifest-Version: 1.0

-Main-Class: jdk.nashorn.tools.Shell

-

-Name: jdk/nashorn/

-Implementation-Vendor: Oracle Corporation

diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/services/javax.script.ScriptEngineFactory b/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/services/javax.script.ScriptEngineFactory
deleted file mode 100644
index 60a8f56..0000000
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/META-INF/services/javax.script.ScriptEngineFactory
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-jdk.nashorn.api.scripting.NashornScriptEngineFactory
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
index dfaecb2..0301f46 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
@@ -353,6 +353,8 @@
         }
     }
 
+    private static final String ANCHOR_PROPS = "anchor.properties";
+
     /**
      * In order to ensure that changes in Nashorn code don't cause corruption in the data, we'll create a
      * per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath
@@ -368,7 +370,7 @@
         // getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness
         // to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our
         // package is to have a small non-class anchor file and start out from its URL.
-        final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties");
+        final URL url = OptimisticTypesPersistence.class.getResource(ANCHOR_PROPS);
         final String protocol = url.getProtocol();
         if (protocol.equals("jar")) {
             // Normal deployment: nashorn.jar
@@ -391,7 +393,7 @@
             final String fileStr = url.getFile();
             final String className = OptimisticTypesPersistence.class.getName();
             final int packageNameLen = className.lastIndexOf('.');
-            final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1);
+            final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1 - ANCHOR_PROPS.length());
             final File dir = new File(dirStr);
             return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(
                     dir, 0L)));
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 cbc4d2e..64a67d8 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
@@ -36,6 +36,7 @@
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.io.File;
+import java.io.InputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.invoke.MethodHandle;
@@ -490,7 +491,7 @@
     private static final ConcurrentMap<String, Class<?>> structureClasses = new ConcurrentHashMap<>();
 
     /*package-private*/ @SuppressWarnings("static-method")
-    ClassLoader getSharedLoader() {
+    StructureLoader getSharedLoader() {
         return sharedLoader;
     }
 
@@ -842,8 +843,8 @@
                         @Override
                         public Source run() {
                             try {
-                                final URL resURL = Context.class.getResource(resource);
-                                return resURL != null ? sourceFor(srcStr, resURL) : null;
+                                final InputStream resStream = Context.class.getResourceAsStream(resource);
+                                return resStream != null ? sourceFor(srcStr, Source.readFully(resStream)) : null;
                             } catch (final IOException exp) {
                                 return null;
                             }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java
index e307123..78256cc 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java
@@ -30,25 +30,40 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.lang.reflect.Module;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
 import java.security.SecureClassLoader;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.internal.module.Modules;
 
 /**
  * Superclass for Nashorn class loader classes.
  */
 abstract class NashornLoader extends SecureClassLoader {
-    private static final String OBJECTS_PKG        = "jdk.nashorn.internal.objects";
-    private static final String RUNTIME_PKG        = "jdk.nashorn.internal.runtime";
-    private static final String RUNTIME_ARRAYS_PKG = "jdk.nashorn.internal.runtime.arrays";
-    private static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker";
-    private static final String SCRIPTS_PKG        = "jdk.nashorn.internal.scripts";
+    protected static final String OBJECTS_PKG        = "jdk.nashorn.internal.objects";
+    protected static final String RUNTIME_PKG        = "jdk.nashorn.internal.runtime";
+    protected static final String RUNTIME_ARRAYS_PKG = "jdk.nashorn.internal.runtime.arrays";
+    protected static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker";
+    protected static final String SCRIPTS_PKG        = "jdk.nashorn.internal.scripts";
+    protected static final String OBJECTS_PKG_INTERNAL        = "jdk/nashorn/internal/objects";
+    protected static final String RUNTIME_PKG_INTERNAL        = "jdk/nashorn/internal/runtime";
+    protected static final String RUNTIME_ARRAYS_PKG_INTERNAL = "jdk/nashorn/internal/runtime/arrays";
+    protected static final String RUNTIME_LINKER_PKG_INTERNAL = "jdk/nashorn/internal/runtime/linker";
+    protected static final String SCRIPTS_PKG_INTERNAL        = "jdk/nashorn/internal/scripts";
+
+    protected static final Module nashornModule = NashornLoader.class.getModule();
 
     private static final Permission[] SCRIPT_PERMISSIONS;
 
+    private static final Set<String> scriptsPkgSet = new HashSet<>();
+
     static {
+        scriptsPkgSet.add(SCRIPTS_PKG);
+
         /*
          * Generated classes get access to runtime, runtime.linker, objects, scripts packages.
          * Note that the actual scripts can not access these because Java.type, Packages
@@ -69,6 +84,22 @@
         super(parent);
     }
 
+    protected static Module defineModule(final String moduleName, final ClassLoader loader) {
+        return Modules.defineModule(loader, moduleName, scriptsPkgSet);
+    }
+
+    protected static void addReadsModule(final Module from, final Module to) {
+        Modules.addReads(from, to);
+    }
+
+    protected static void addModuleExports(final Module from, final String pkg, final Module to) {
+        if (to == null) {
+            Modules.addExportsToAll(from, pkg);
+        } else {
+            Modules.addExports(from, pkg, to);
+        }
+    }
+
     protected static void checkPackageAccess(final String name) {
         final int i = name.lastIndexOf('.');
         if (i != -1) {
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 3b66c99..7902870 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
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.lang.reflect.Module;
 import java.security.CodeSource;
 import java.util.Objects;
 
@@ -35,6 +36,8 @@
 final class ScriptLoader extends NashornLoader {
     private static final String NASHORN_PKG_PREFIX = "jdk.nashorn.internal.";
 
+    private volatile boolean structureAccessAdded;
+    private final Module scriptModule;
     private final Context context;
 
     /*package-private*/ Context getContext() {
@@ -47,13 +50,39 @@
     ScriptLoader(final ClassLoader parent, final Context context) {
         super(parent);
         this.context = context;
+
+        // new scripts module, it's specific exports and read-edges
+        scriptModule = defineModule("jdk.scripting.nashorn.scripts", this);
+        addModuleExports(scriptModule, SCRIPTS_PKG, nashornModule);
+        addReadsModule(scriptModule, nashornModule);
+        addReadsModule(scriptModule, Object.class.getModule());
+
+        // specific exports from nashorn to new scripts module
+        nashornModule.addExports(OBJECTS_PKG, scriptModule);
+        nashornModule.addExports(RUNTIME_PKG, scriptModule);
+        nashornModule.addExports(RUNTIME_ARRAYS_PKG, scriptModule);
+        nashornModule.addExports(RUNTIME_LINKER_PKG, scriptModule);
+        nashornModule.addExports(SCRIPTS_PKG, scriptModule);
+
+        // nashorn needs to read scripts module methods,fields
+        nashornModule.addReads(scriptModule);
     }
 
     @Override
     protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
         checkPackageAccess(name);
         if (name.startsWith(NASHORN_PKG_PREFIX)) {
-            return context.getSharedLoader().loadClass(name);
+            final StructureLoader sharedCl = context.getSharedLoader();
+            final Class<?> cl = sharedCl.loadClass(name);
+            if (! structureAccessAdded) {
+                if (cl.getClassLoader() == sharedCl) {
+                    structureAccessAdded = true;
+                    final Module structModule = sharedCl.getModule();
+                    addModuleExports(structModule, SCRIPTS_PKG, scriptModule);
+                    addReadsModule(scriptModule, structModule);
+                }
+            }
+            return cl;
         }
         return super.loadClass(name, resolve);
     }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java
index 99a4bf2..2331ce1 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java
@@ -922,7 +922,7 @@
         return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is);
     }
 
-    private static char[] readFully(final InputStream is) throws IOException {
+    public static char[] readFully(final InputStream is) throws IOException {
         return byteToCharArray(readBytes(is));
     }
 
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 8324730..b179c25 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
@@ -30,6 +30,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_DUAL_FIELD_PREFIX;
 import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_SINGLE_FIELD_PREFIX;
 
+import java.lang.reflect.Module;
 import java.security.ProtectionDomain;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 
@@ -40,11 +41,26 @@
     private static final String SINGLE_FIELD_PREFIX = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_SINGLE_FIELD_PREFIX.symbolName();
     private static final String DUAL_FIELD_PREFIX   = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_DUAL_FIELD_PREFIX.symbolName();
 
+    private final Module structuresModule;
+
     /**
      * Constructor.
      */
     StructureLoader(final ClassLoader parent) {
         super(parent);
+
+        // new structures module, it's exports, read edges
+        structuresModule = defineModule("jdk.scripting.nashorn.structures", this);
+        addModuleExports(structuresModule, SCRIPTS_PKG, nashornModule);
+        addReadsModule(structuresModule, nashornModule);
+        addReadsModule(structuresModule, Object.class.getModule());
+
+        // specific exports from nashorn to the structures module
+        nashornModule.addExports(SCRIPTS_PKG, structuresModule);
+        nashornModule.addExports(RUNTIME_PKG, structuresModule);
+
+        // nashorn has to read fields from classes of the new module
+        nashornModule.addReads(structuresModule);
     }
 
     /**
@@ -74,6 +90,10 @@
         return isDualFieldStructure(name) || isSingleFieldStructure(name);
     }
 
+    protected Module getModule() {
+        return structuresModule;
+    }
+
     @Override
     protected Class<?> findClass(final String name) throws ClassNotFoundException {
         if (isDualFieldStructure(name)) {
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index ba82e64..54d2e12 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -51,6 +51,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -197,12 +198,8 @@
     private static final String GET_METHOD_PROPERTY_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, SCRIPT_OBJECT_TYPE);
     private static final String VOID_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
 
-    // Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
-    // it's a java.* package.
-    private static final String ADAPTER_PACKAGE_PREFIX = "jdk/nashorn/javaadapters/";
-    // Class name suffix used to append to the adaptee class name, when it can be defined in the adaptee's package.
-    private static final String ADAPTER_CLASS_NAME_SUFFIX = "$$NashornJavaAdapter";
-    private static final String JAVA_PACKAGE_PREFIX = "java/";
+    static final String ADAPTER_PACKAGE_INTERNAL = "jdk/nashorn/javaadapters/";
+    static final String ADAPTER_PACKAGE = "jdk.nashorn.javaadapters";
     private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
 
     // Method name prefix for invoking super-methods
@@ -237,6 +234,7 @@
     private final Set<MethodInfo> methodInfos = new HashSet<>();
     private final boolean autoConvertibleFromFunction;
     private boolean hasExplicitFinalizer = false;
+    private final Set<Module> accessedModules = new HashSet<>();
 
     private final ClassWriter cw;
 
@@ -300,7 +298,7 @@
     }
 
     JavaAdapterClassLoader createAdapterClassLoader() {
-        return new JavaAdapterClassLoader(generatedClassName, cw.toByteArray());
+        return new JavaAdapterClassLoader(generatedClassName, cw.toByteArray(), accessedModules);
     }
 
     boolean isAutoConvertibleFromFunction() {
@@ -314,12 +312,7 @@
         final Package pkg = namingType.getPackage();
         final String namingTypeName = Type.getInternalName(namingType);
         final StringBuilder buf = new StringBuilder();
-        if (namingTypeName.startsWith(JAVA_PACKAGE_PREFIX) || pkg == null || pkg.isSealed()) {
-            // Can't define new classes in java.* packages
-            buf.append(ADAPTER_PACKAGE_PREFIX).append(namingTypeName);
-        } else {
-            buf.append(namingTypeName).append(ADAPTER_CLASS_NAME_SUFFIX);
-        }
+        buf.append(ADAPTER_PACKAGE_INTERNAL).append(namingTypeName.replace('/', '_'));
         final Iterator<Class<?>> it = interfaces.iterator();
         if(superType == Object.class && it.hasNext()) {
             it.next(); // Skip first interface, it was used to primarily name the adapter
@@ -359,7 +352,7 @@
             // If the class is a SAM, allow having ScriptFunction passed as class overrides
             mv.dup();
             mv.instanceOf(SCRIPT_FUNCTION_TYPE);
-            mv.dup();
+                    mv.dup();
             mv.putstatic(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
             final Label notFunction = new Label();
             mv.ifeq(notFunction);
@@ -379,9 +372,9 @@
     private void emitInitCallThis(final InstructionAdapter mv) {
         loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
         GET_CALL_THIS.invoke(mv);
-        if(classOverride) {
+            if(classOverride) {
             mv.putstatic(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
-        } else {
+            } else {
             // It is presumed ALOAD 0 was already executed
             mv.putfield(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
         }
@@ -404,6 +397,14 @@
     }
 
     private boolean generateConstructors(final Constructor<?> ctor) {
+        for (final Class<?> pt : ctor.getParameterTypes()) {
+            if (pt.isPrimitive()) continue;
+            final Module ptMod = pt.getModule();
+            if (ptMod != null) {
+                accessedModules.add(ptMod);
+            }
+        }
+
         if(classOverride) {
             // Generate a constructor that just delegates to ctor. This is used with class-level overrides, when we want
             // to create instances without further per-instance overrides.
@@ -411,16 +412,16 @@
             return false;
         }
 
-        // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
-        // beginning of its parameter list.
-        generateOverridingConstructor(ctor, false);
+            // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
+            // beginning of its parameter list.
+            generateOverridingConstructor(ctor, false);
 
         if (samName == null) {
             return false;
-        }
-        // If all our abstract methods have a single name, generate an additional constructor, one that takes a
-        // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
-        generateOverridingConstructor(ctor, true);
+                }
+                // If all our abstract methods have a single name, generate an additional constructor, one that takes a
+                // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
+                generateOverridingConstructor(ctor, true);
         // If the original type only has a single abstract method name, as well as a default ctor, then it can
         // be automatically converted from JS function.
         return ctor.getParameterTypes().length == 0;
@@ -499,7 +500,7 @@
             mv.iconst(1);
             mv.putfield(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 
-            mv.visitVarInsn(ALOAD, 0);
+        mv.visitVarInsn(ALOAD, 0);
             mv.visitVarInsn(ALOAD, extraArgOffset);
             emitInitCallThis(mv);
         }
@@ -668,7 +669,7 @@
                 // stack: [callThis, delegate]
                 mv.goTo(callCallee);
                 mv.visitLabel(notFunction);
-            } else {
+        } else {
                 // If it's not a SAM method, and the delegate is a function,
                 // it'll fall back to default behavior
                 mv.ifne(defaultBehavior);
@@ -808,7 +809,7 @@
         if (isVarArgCall) {
             // Variable arity calls are always (Object callee, Object this, Object[] params)
             callParamTypes = new Class<?>[] { Object.class, Object.class, Object[].class };
-        } else {
+            } else {
             // Adjust invocation type signature for conversions we instituted in
             // convertParam; also, byte and short get passed as ints.
             final Class<?>[] origParamTypes = type.parameterArray();
@@ -858,13 +859,13 @@
 
 
     private void loadField(final InstructionAdapter mv, final String name, final String desc) {
-        if(classOverride) {
+                if(classOverride) {
             mv.getstatic(generatedClassName, name, desc);
-        } else {
-            mv.visitVarInsn(ALOAD, 0);
+                } else {
+                    mv.visitVarInsn(ALOAD, 0);
             mv.getfield(generatedClassName, name, desc);
-        }
-    }
+                }
+            }
 
     private static void convertReturnValue(final InstructionAdapter mv, final Class<?> origReturnType) {
         if (origReturnType == void.class) {
@@ -1082,6 +1083,11 @@
      */
     private void gatherMethods(final Class<?> type) throws AdaptationException {
         if (Modifier.isPublic(type.getModifiers())) {
+            final Module module = type.getModule();
+            if (module != null) {
+                accessedModules.add(module);
+            }
+
             final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods();
 
             for (final Method typeMethod: typeMethods) {
@@ -1106,12 +1112,26 @@
                         continue;
                     }
 
+                    for (final Class<?> pt : typeMethod.getParameterTypes()) {
+                        if (pt.isPrimitive()) continue;
+                        final Module ptMod = pt.getModule();
+                        if (ptMod != null) {
+                            accessedModules.add(ptMod);
+                        }
+                    }
+
+                    final Class<?> rt = typeMethod.getReturnType();
+                    if (!rt.isPrimitive()) {
+                        final Module rtMod = rt.getModule();
+                        if (rtMod != null) accessedModules.add(rtMod);
+                    }
+
                     final MethodInfo mi = new MethodInfo(typeMethod);
                     if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
                         finalMethods.add(mi);
                     } else if (!finalMethods.contains(mi) && methodInfos.add(mi) && Modifier.isAbstract(m)) {
-                        abstractMethodNames.add(mi.getName());
-                    }
+                            abstractMethodNames.add(mi.getName());
+                        }
                 }
             }
         }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
index 6c61607..5498bed 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.lang.reflect.Module;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -34,12 +35,14 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Set;
 import jdk.dynalink.beans.StaticClass;
 import jdk.nashorn.internal.codegen.DumpBytecode;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.internal.module.Modules;
 
 /**
  * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
@@ -49,6 +52,12 @@
  * class are normally created by {@code JavaAdapterBytecodeGenerator}.
  */
 final class JavaAdapterClassLoader {
+    private static final Module nashornModule = JavaAdapterClassLoader.class.getModule();
+    private static final Set<String> adapterPkgs = new HashSet<>();
+    static {
+        adapterPkgs.add(JavaAdapterBytecodeGenerator.ADAPTER_PACKAGE);
+    }
+
     private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
     private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
     private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
@@ -56,10 +65,12 @@
 
     private final String className;
     private final byte[] classBytes;
+    private final Set<Module> accessedModules;
 
-    JavaAdapterClassLoader(final String className, final byte[] classBytes) {
+    JavaAdapterClassLoader(final String className, final byte[] classBytes, final Set<Module> accessedModules) {
         this.className = className.replace('/', '.');
         this.classBytes = classBytes;
+        this.accessedModules = accessedModules;
     }
 
     /**
@@ -82,6 +93,14 @@
         }, CREATE_LOADER_ACC_CTXT);
     }
 
+    private static void addExports(final Module from, final String pkg, final Module to) {
+        if (to == null) {
+            Modules.addExportsToAll(from, pkg);
+        } else {
+            Modules.addExports(from, pkg, to);
+        }
+    }
+
     // Note that the adapter class is created in the protection domain of the class/interface being
     // extended/implemented, and only the privileged global setter action class is generated in the protection domain
     // of Nashorn itself. Also note that the creation and loading of the global setter is deferred until it is
@@ -93,6 +112,26 @@
         return new SecureClassLoader(parentLoader) {
             private final ClassLoader myLoader = getClass().getClassLoader();
 
+            // new adapter module
+            private final Module adapterModule = Modules.defineModule(this, "jdk.scripting.nashorn.javaadapters", adapterPkgs);
+
+            {
+                // new adapter module exports and read-edges
+                addExports(adapterModule, JavaAdapterBytecodeGenerator.ADAPTER_PACKAGE, null);
+                Modules.addReads(adapterModule, nashornModule);
+                Modules.addReads(adapterModule, Object.class.getModule());
+                for (Module mod : accessedModules) {
+                    Modules.addReads(adapterModule, mod);
+                }
+
+                // specific exports from nashorn to the new adapter module
+                nashornModule.addExports("jdk.nashorn.internal.runtime", adapterModule);
+                nashornModule.addExports("jdk.nashorn.internal.runtime.linker", adapterModule);
+
+                // nashorn should be be able to read methods of classes loaded in adapter module
+                nashornModule.addReads(adapterModule);
+            }
+
             @Override
             public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
                 try {
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
index 8dc490c..19c6d32 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
@@ -228,7 +228,7 @@
         });
 
         try {
-            return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke",
+            return MethodHandles.publicLookup().findStatic(Class.forName(className, true, loader), "invoke",
                     MethodType.methodType(void.class, MethodHandle.class, Object.class));
         } catch(final ReflectiveOperationException e) {
             throw new AssertionError(e.getMessage(), e);
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
index 8201aa6..60c44c6 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@@ -25,7 +25,9 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Modifier;
+import jdk.internal.module.Modules;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
 import jdk.dynalink.StandardOperation;
@@ -87,8 +89,11 @@
             if (NashornLinker.isAbstractClass(receiverClass)) {
                 // Change this link request into a link request on the adapter class.
                 final Object[] args = request.getArguments();
-                args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null,
-                        NashornCallSiteDescriptor.getLookupInternal(request.getCallSiteDescriptor()));
+                final MethodHandles.Lookup lookup =
+                        NashornCallSiteDescriptor.getLookupInternal(request.getCallSiteDescriptor());
+
+                args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null, lookup);
+                Modules.addReads(lookup.lookupClass().getModule(), ((StaticClass)args[0]).getRepresentedClass().getModule());
                 final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args);
                 final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass);
                 // Finally, modify the guard to test for the original abstract class.
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java b/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java
new file mode 100644
index 0000000..fbf83d1
--- /dev/null
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.scripting.nashorn {
+    requires java.logging;
+    requires public java.scripting;
+    requires jdk.dynalink;
+
+    exports jdk.nashorn.api.scripting;
+    exports jdk.nashorn.api.tree;
+
+    exports jdk.nashorn.internal.runtime to
+        jdk.scripting.nashorn.shell;
+    exports jdk.nashorn.internal.objects to
+        jdk.scripting.nashorn.shell;
+    exports jdk.nashorn.tools to
+        jdk.scripting.nashorn.shell;
+
+    provides javax.script.ScriptEngineFactory with jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+}
+
diff --git a/nashorn/test/TEST.ROOT b/nashorn/test/TEST.ROOT
index ad4b96f..bbdb534 100644
--- a/nashorn/test/TEST.ROOT
+++ b/nashorn/test/TEST.ROOT
@@ -8,4 +8,4 @@
 groups=TEST.groups
 
 # Minimum jtreg version
-requiredVersion=4.1 b12
+requiredVersion=4.2 b01
diff --git a/nashorn/test/script/currently-failing/JDK-8055034.js b/nashorn/test/script/currently-failing/JDK-8055034.js
index 3212203..0f90515 100644
--- a/nashorn/test/script/currently-failing/JDK-8055034.js
+++ b/nashorn/test/script/currently-failing/JDK-8055034.js
@@ -51,7 +51,7 @@
     jjsCmd = javahome + "/bin/jjs";
     jjsCmd = jjsCmd.toString().replace(/\//g, File.separator);
 }
-jjsCmd += " -J-Xbootclasspath/p:" + nashornJar;
+jjsCmd += " -J-Xpatch:" + nashornJar;
 
 $ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
 $EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
diff --git a/nashorn/test/script/nosecurity/JDK-8044798.js b/nashorn/test/script/nosecurity/JDK-8044798.js
index cc2ef83..dcf1796 100644
--- a/nashorn/test/script/nosecurity/JDK-8044798.js
+++ b/nashorn/test/script/nosecurity/JDK-8044798.js
@@ -27,7 +27,6 @@
  * @test
  * @option -Dnashorn.mirror.always=false
  * @fork
- * @run
  */
 
 // basic API exercise checks
@@ -120,18 +119,25 @@
 
 var Source = Java.type("jdk.nashorn.internal.runtime.Source");
 var Context = Java.type("jdk.nashorn.internal.runtime.Context");
+var ThrowErrorManager = Java.type("jdk.nashorn.internal.runtime.Context.ThrowErrorManager");
+var contextCls = java.lang.Class.forName("jdk.nashorn.internal.runtime.Context");
 var sourceCls = Source.class;
 var errorMgrCls = Java.type("jdk.nashorn.internal.runtime.ErrorManager").class;
 var booleanCls = Java.type("java.lang.Boolean").TYPE;
+var stringCls = Java.type("java.lang.String").class;
 
 // private compile method of Context class
-var compileMethod = Context.class.getDeclaredMethod("compile",
+var compileMethod = contextCls.getDeclaredMethod("compile",
                 sourceCls, errorMgrCls, booleanCls, booleanCls);
 compileMethod.accessible = true;
 
-var scriptCls = compileMethod.invoke(Context.context,
-    Source.sourceFor("test", "print('hello')"),
-    new Context.ThrowErrorManager(), false, false);
+var getContextMethod = contextCls.getMethod("getContext");
+getContextMethod.accessible = true;
+
+var sourceForMethod = sourceCls.getMethod("sourceFor", stringCls, stringCls);
+var scriptCls = compileMethod.invoke(getContextMethod.invoke(null),
+    sourceForMethod.invoke(null, "test", "print('hello')"),
+    ThrowErrorManager.class.newInstance(), false, false);
 
 var SCRIPT_CLASS_NAME_PREFIX = "jdk.nashorn.internal.scripts.Script$";
 print("script class name pattern satisfied? " +
diff --git a/nashorn/test/script/nosecurity/JDK-8044851.js b/nashorn/test/script/nosecurity/JDK-8044851.js
index 679c349..8be2fe2 100644
--- a/nashorn/test/script/nosecurity/JDK-8044851.js
+++ b/nashorn/test/script/nosecurity/JDK-8044851.js
@@ -25,13 +25,32 @@
  * JDK-8044851: nashorn properties leak memory
  *
  * @test
- * @run
  * @option -Dnashorn.debug=true
  * @fork
  */
 
+var Property = Java.type("jdk.nashorn.internal.runtime.Property");
+var PropertyMap = Java.type("jdk.nashorn.internal.runtime.PropertyMap");
+
+// Class objects
+var objectCls = Java.type("java.lang.Object").class;
+var propertyCls = Property.class;
+var propertyMapCls = PropertyMap.class;
+
+// Method objects
+var findPropertyMethod = propertyMapCls.getMethod("findProperty", objectCls);
+var getKeyMethod = propertyCls.getMethod("getKey");
+var isSpillMethod = propertyCls.getMethod("isSpill");
+var getSlotMethod = propertyCls.getMethod("getSlot");
+
 function printProperty(value, property) {
-    print(value, property.getKey(), property.isSpill() ? "spill" : "field", property.getSlot());
+    print(value, getKeyMethod.invoke(property), 
+        isSpillMethod.invoke(property) ? "spill" : "field", getSlotMethod.invoke(property));
+}
+
+function findProperty(obj, name) {
+    var map = Debug.map(obj);
+    return findPropertyMethod.invoke(map, name);
 }
 
 var obj = {}, i, name;
@@ -39,7 +58,7 @@
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     obj[name] = 'a' + i;
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
 print();
 
@@ -51,14 +70,14 @@
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     obj[name] = 'b' + i;
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
 print();
 
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}, configurable: true});
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
 print();
 
@@ -70,7 +89,7 @@
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     obj[name] = 'c' + i;
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
 print();
 
@@ -82,12 +101,12 @@
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     obj[name] = 'd' + i;
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
 print();
 
 for (i = 0; i < 8; ++i) {
     name = 'property' + i;
     Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}});
-    printProperty(obj[name], Debug.map(obj).findProperty(name));
+    printProperty(obj[name], findProperty(obj, name));
 }
diff --git a/nashorn/test/script/nosecurity/JDK-8067215.js b/nashorn/test/script/nosecurity/JDK-8067215.js
index b18163a..e6e5597 100644
--- a/nashorn/test/script/nosecurity/JDK-8067215.js
+++ b/nashorn/test/script/nosecurity/JDK-8067215.js
@@ -27,6 +27,7 @@
  * @test
  * @run
  * @option -Dnashorn.debug=true
+ * @option -scripting
  * @fork
  */
 
@@ -36,10 +37,27 @@
 
 var Context = Java.type("jdk.nashorn.internal.runtime.Context");
 var JSType  = Java.type("jdk.nashorn.internal.runtime.JSType");
+var Property = Java.type("jdk.nashorn.internal.runtime.Property");
+var PropertyMap  = Java.type("jdk.nashorn.internal.runtime.PropertyMap");
 
-var context = Context.getContext();
-var dualFields = context.useDualFields();
-var optimisticTypes = context.getEnv()._optimistic_types;
+// Class objects
+var objectCls = Java.type("java.lang.Object").class;
+var contextCls = Context.class;
+var JSTypeCls = JSType.class;
+var propertyCls = Property.class;
+var propertyMapCls  = PropertyMap.class;
+
+// Method objects
+var getContextMethod = contextCls.getMethod("getContext");
+var isRepresentableAsIntMethod = JSTypeCls.getMethod("isRepresentableAsInt", java.lang.Double.TYPE);
+var hasDualFieldsMethod = propertyCls.getMethod("hasDualFields");
+var getTypeMethod = propertyCls.getMethod("getType");
+var findPropertyMethod = propertyMapCls.getMethod("findProperty", objectCls);
+
+var context = getContextMethod.invoke(null);
+var useDualFieldsMethod = contextCls.getMethod("useDualFields");
+var dualFields = useDualFieldsMethod.invoke(context);
+var optimisticTypes = $OPTIONS._optimistic_types;
 
 if (dualFields != optimisticTypes) {
     throw new Error("Wrong dual fields setting");
@@ -51,11 +69,11 @@
     Object.defineProperty(obj, "z", {value: 0.5});
     var map = Debug.map(obj);
     for (var key in obj) {
-        var prop = map.findProperty(key);
-        if (prop.hasDualFields() !== dualFields) {
+        var prop = findPropertyMethod.invoke(map, key);
+        if (hasDualFieldsMethod.invoke(prop) !== dualFields) {
             throw new Error("Wrong property flags: " + prop);
         }
-        if (prop.getType() != getExpectedType(obj[key])) {
+        if (getTypeMethod.invoke(prop) != getExpectedType(obj[key])) {
             throw new Error("Wrong property type: " + prop.getType() + " // " + getExpectedType(obj[key]));
         }
     }
@@ -66,7 +84,7 @@
         return objectType.class;
     }
     if (typeof value === "number") {
-        return JSType.isRepresentableAsInt(value) ? intType.class : doubleType.class;
+        return isRepresentableAsIntMethod.invoke(null, value) ? intType.class : doubleType.class;
     }
     return objectType.class;
 }
diff --git a/nashorn/test/script/nosecurity/JDK-8078049.js b/nashorn/test/script/nosecurity/JDK-8078049.js
index 6a441a1..74e3a62 100644
--- a/nashorn/test/script/nosecurity/JDK-8078049.js
+++ b/nashorn/test/script/nosecurity/JDK-8078049.js
@@ -543,11 +543,14 @@
 
 var AccessorProperty = Java.type("jdk.nashorn.internal.runtime.AccessorProperty");
 var SpillProperty    = Java.type("jdk.nashorn.internal.runtime.SpillProperty");
+var PropertyMap = Java.type("jdk.nashorn.internal.runtime.PropertyMap");
+var findPropertyMethod = PropertyMap.class.getMethod("findProperty", java.lang.Object.class);
 
 Assert.assertTrue(Object.keys(fields).length === 3);
-Assert.assertTrue(Debug.map(fields).findProperty("p0").getClass() === AccessorProperty.class);
-Assert.assertTrue(Debug.map(fields).findProperty("p2").getClass() === AccessorProperty.class);
+Assert.assertTrue(findPropertyMethod.invoke(Debug.map(fields), "p0").getClass() === AccessorProperty.class);
+Assert.assertTrue(findPropertyMethod.invoke(Debug.map(fields), "p2").getClass() === AccessorProperty.class);
 
 Assert.assertTrue(Object.keys(spill).length === 500);
-Assert.assertTrue(Debug.map(spill).findProperty("p0").getClass() === SpillProperty.class);
-Assert.assertTrue(Debug.map(spill).findProperty("p499").getClass() === SpillProperty.class);
+
+Assert.assertTrue(findPropertyMethod.invoke(Debug.map(spill), "p0").getClass() === SpillProperty.class);
+Assert.assertTrue(findPropertyMethod.invoke(Debug.map(spill), "p499").getClass() === SpillProperty.class);
diff --git a/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED b/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED
index e0cf856..884e95a 100644
--- a/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED
+++ b/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED
@@ -6,9 +6,9 @@
 [JavaClass java.util.ArrayList]
 [JavaClass java.lang.String]
 [JavaPackage java.lang.String]
-[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
-[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
-[JavaClass jdk.nashorn.javaadapters.java.io.File]
+[JavaClass jdk.nashorn.javaadapters.java_util_ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java_util_ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java_io_File]
 TypeError: Java.extend needs Java types as its arguments. in <eval> at line number 1
 java.lang.NullPointerException
 java.lang.ClassNotFoundException: java.lang.NullPointerException
diff --git a/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
index 9481e98..7491e44 100644
--- a/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
+++ b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
@@ -1,7 +1,7 @@
-class javax.script.ScriptContext$$NashornJavaAdapter
+class jdk.nashorn.javaadapters.javax_script_ScriptContext
 TypeError: Java.extend needs at least one type argument. in nashorn:mozilla_compat.js at line number 39
-class jdk.nashorn.javaadapters.java.util.ArrayList
-class jdk.nashorn.javaadapters.java.util.ArrayList
+class jdk.nashorn.javaadapters.java_util_ArrayList
+class jdk.nashorn.javaadapters.java_util_ArrayList
 [JavaClass java.lang.Integer]
 TypeError: [object JavaPackage] is not a Java class in nashorn:mozilla_compat.js at line number 373 at column number 16
 [JavaClass java.util.HashSet]
diff --git a/nashorn/test/script/trusted/event_queue.js b/nashorn/test/script/trusted/event_queue.js
index feecc20..22a86a2 100644
--- a/nashorn/test/script/trusted/event_queue.js
+++ b/nashorn/test/script/trusted/event_queue.js
@@ -30,6 +30,7 @@
  * @option -Dnashorn.debug=true
  * @option --log=recompile:quiet
  * @option --optimistic-types=true
+ * @run
  */
 
 print(Debug);
diff --git a/nashorn/test/script/trusted/optimistic_recompilation.js b/nashorn/test/script/trusted/optimistic_recompilation.js
index 9c9a9c7..9d9724d 100644
--- a/nashorn/test/script/trusted/optimistic_recompilation.js
+++ b/nashorn/test/script/trusted/optimistic_recompilation.js
@@ -29,6 +29,7 @@
  * @option -Dnashorn.debug=true
  * @option --log=recompile:quiet
  * @option --optimistic-types=true
+ * @run
  */
 
 var forName       = java.lang.Class["forName(String)"];
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 76c99d5..4f2bb9d 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
@@ -69,6 +69,7 @@
  * Bignum class tests
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv
  * @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 00e49ea..5432e53 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
@@ -44,6 +44,7 @@
  * DiyFp class tests
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv
  * @run testng jdk.nashorn.internal.runtime.doubleconv.test.DiyFpTest
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
index a907f8f..27ffd84 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
@@ -32,6 +32,7 @@
  * Joni coverage tests
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp.joni
  * @run testng jdk.nashorn.internal.runtime.regexp.joni.test.JoniTest
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
index 20cb367..32d5d42 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
@@ -38,6 +38,7 @@
  * Basic tests for the JDK based RegExp implementation.
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp
  * @run testng jdk.nashorn.internal.runtime.regexp.test.JdkRegExpTest
  */
 public class JdkRegExpTest {
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
index f86c5b7..12f4902 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
@@ -34,6 +34,7 @@
  * Tests for JSType methods.
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
  * @run testng jdk.nashorn.internal.runtime.test.ConsStringTest
  */
 public class ConsStringTest {
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
index b927de2..35f902e 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
@@ -44,6 +44,9 @@
  * Basic Context API tests.
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
+ *          jdk.scripting.nashorn/jdk.nashorn.internal.runtime.options
+ *          jdk.scripting.nashorn/jdk.nashorn.internal.objects
  * @run testng jdk.nashorn.internal.runtime.test.ContextTest
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
index 2f498af..cac02e0 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
@@ -42,6 +42,7 @@
  * JDK-8044518: Ensure exceptions related to optimistic recompilation are not serializable
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
  * @run testng jdk.nashorn.internal.runtime.test.ExceptionsNotSerializable
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java
index 30755ed..845cc1a 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java
@@ -47,6 +47,10 @@
  * @test
  * @bug 8078414
  * @summary Test that arbitrary classes can't be converted to mirror's superclasses/interfaces.
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.linker
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.options
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.objects
  * @run testng jdk.nashorn.internal.runtime.test.JDK_8078414_Test
  */
 public class JDK_8078414_Test {
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
index a91a442..9d0c0bb 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
@@ -37,6 +37,7 @@
  * Tests for JSType methods.
  *
  * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
  * @run testng jdk.nashorn.internal.runtime.test.JSTypeTest
  */
 public class JSTypeTest {
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
index 8ca3405..3e3c951 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
@@ -176,8 +176,6 @@
         final List<String> cmd = new ArrayList<>();
 
         cmd.add(System.getProperty("java.home") + separator + "bin" + separator + "java");
-        // cmd.add("-Djava.ext.dirs=dist");
-        cmd.add("-Xbootclasspath/a:dist/nashorn.jar");
         for (final String str : forkJVMOptions) {
             if(!str.isEmpty()) {
                 cmd.add(str);
diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java
index 668d2f0..4eb5dfa 100644
--- a/test/lib/sun/hotspot/WhiteBox.java
+++ b/test/lib/sun/hotspot/WhiteBox.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
@@ -32,7 +32,6 @@
 import java.util.function.Function;
 import java.security.BasicPermission;
 import java.util.Objects;
-import jdk.internal.HotSpotIntrinsicCandidate;
 
 import sun.hotspot.parser.DiagnosticCommand;
 
@@ -211,8 +210,6 @@
   public native int     deoptimizeFrames(boolean makeNotEntrant);
   public native void    deoptimizeAll();
 
-  @HotSpotIntrinsicCandidate
-  public        void    deoptimize() {}
   public        boolean isMethodCompiled(Executable method) {
     return isMethodCompiled(method, false /*not osr*/);
   }
@@ -422,6 +419,19 @@
                        .findAny()
                        .orElse(null);
   }
+
+  // Jigsaw
+  public native void DefineModule(Object module, String version, String location,
+                                  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);
+  public native Object GetModuleByPackageName(Object ldr, String pkg);
+
   public native int getOffsetForName0(String name);
   public int getOffsetForName(String name) throws Exception {
     int offset = getOffsetForName0(name);
@@ -452,7 +462,7 @@
   public native void assertMatchingSafepointCalls(boolean mutexSafepointValue, boolean attemptedNoSafepointValue);
 
   // Sharing
-  public native boolean isSharedClass(Class<?> c);
   public native boolean isShared(Object o);
+  public native boolean isSharedClass(Class<?> c);
   public native boolean areSharedStringsIgnored();
 }